Skip to content

Commit 41a4826

Browse files
authored
bitfields-derive: strip :: prefix from type if present (#1411)
The code was testing whether the initial `::` was present, but was not taking it out of the string/iterator. That would then lead to a panic when creating the `Ident` on an empty string.
2 parents 55e1c24 + 7d0e0b6 commit 41a4826

File tree

1 file changed

+24
-18
lines changed
  • c2rust-bitfields-derive/src

1 file changed

+24
-18
lines changed

c2rust-bitfields-derive/src/lib.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![recursion_limit = "512"]
22

3-
use proc_macro::{Span, TokenStream};
3+
use proc_macro::TokenStream;
4+
use proc_macro2::Span;
45
use quote::quote;
56
use syn::parse::Error;
67
use syn::punctuated::Punctuated;
@@ -20,7 +21,7 @@ struct BFFieldAttr {
2021
field_name: Ident,
2122
name: String,
2223
ty: String,
23-
bits: (String, proc_macro2::Span),
24+
bits: (String, Span),
2425
}
2526

2627
fn parse_bitfield_attr(
@@ -111,29 +112,19 @@ fn filter_and_parse_fields(field: &Field) -> Vec<Result<BFFieldAttr, Error>> {
111112
}
112113

113114
fn parse_bitfield_ty_path(field: &BFFieldAttr) -> Path {
114-
let leading_colon = if field.ty.starts_with("::") {
115-
Some(Token![::]([
116-
Span::call_site().into(),
117-
Span::call_site().into(),
118-
]))
119-
} else {
120-
None
121-
};
122-
123115
let mut segments = Punctuated::new();
124116
let mut segment_strings = field.ty.split("::").peekable();
117+
let colon = Token![::]([Span::call_site(), Span::call_site()]);
118+
let leading_colon = segment_strings.next_if_eq(&"").map(|_| colon);
125119

126120
while let Some(segment_string) = segment_strings.next() {
127121
segments.push_value(PathSegment {
128-
ident: Ident::new(segment_string, Span::call_site().into()),
122+
ident: Ident::new(segment_string, Span::call_site()),
129123
arguments: PathArguments::None,
130124
});
131125

132126
if segment_strings.peek().is_some() {
133-
segments.push_punct(Token![::]([
134-
Span::call_site().into(),
135-
Span::call_site().into(),
136-
]));
127+
segments.push_punct(colon);
137128
}
138129
}
139130

@@ -143,6 +134,21 @@ fn parse_bitfield_ty_path(field: &BFFieldAttr) -> Path {
143134
}
144135
}
145136

137+
#[cfg(test)]
138+
#[test]
139+
fn test_parse_bitfield_ty_path_non_empty_idents() {
140+
let tys = ["::core::ffi::c_int", "core::ffi::c_int"];
141+
for ty in tys {
142+
let field = BFFieldAttr {
143+
field_name: Ident::new("field", Span::call_site()),
144+
name: Default::default(),
145+
ty: ty.into(),
146+
bits: (Default::default(), Span::call_site()),
147+
};
148+
let _path = parse_bitfield_ty_path(&field);
149+
}
150+
}
151+
146152
#[proc_macro_derive(BitfieldStruct, attributes(bitfield))]
147153
pub fn bitfield_struct(input: TokenStream) -> TokenStream {
148154
let struct_item = parse_macro_input!(input as ItemStruct);
@@ -181,15 +187,15 @@ fn bitfield_struct_impl(struct_item: ItemStruct) -> Result<TokenStream, Error> {
181187
let field_types_setter_arg = &field_types;
182188
let method_names: Vec<_> = bitfields
183189
.iter()
184-
.map(|field| Ident::new(&field.name, Span::call_site().into()))
190+
.map(|field| Ident::new(&field.name, Span::call_site()))
185191
.collect();
186192
let field_names: Vec<_> = bitfields.iter().map(|field| &field.field_name).collect();
187193
let field_names_setters = &field_names;
188194
let field_names_getters = &field_names;
189195
let method_name_setters: Vec<_> = method_names
190196
.iter()
191197
.map(|field_ident| {
192-
let span = Span::call_site().into();
198+
let span = Span::call_site();
193199
let setter_name = &format!("set_{}", field_ident);
194200

195201
Ident::new(setter_name, span)

0 commit comments

Comments
 (0)