Skip to content

Commit ef572c1

Browse files
mqqznbdd0121
authored andcommitted
internal: pin_data: add struct to record field info
Introduce `FieldInfo` struct to encapsulate field and other relevant data, instead of carrying a pair of `(pinned, field)` in all places. This allows us to add more information to the struct in the future. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Co-developed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Gary Guo <gary@garyguo.net>
1 parent 13111ef commit ef572c1

1 file changed

Lines changed: 32 additions & 21 deletions

File tree

internal/src/pin_data.rs

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ impl Parse for Args {
3535
}
3636
}
3737

38+
struct FieldInfo<'a> {
39+
field: &'a Field,
40+
pinned: bool,
41+
}
42+
3843
pub(crate) fn pin_data(
3944
args: Args,
4045
input: Item,
@@ -73,24 +78,30 @@ pub(crate) fn pin_data(
7378
replacer.visit_generics_mut(&mut struct_.generics);
7479
replacer.visit_fields_mut(&mut struct_.fields);
7580

76-
let fields: Vec<(bool, &Field)> = struct_
81+
let fields: Vec<FieldInfo<'_>> = struct_
7782
.fields
7883
.iter_mut()
7984
.map(|field| {
8085
let len = field.attrs.len();
8186
field.attrs.retain(|a| !a.path().is_ident("pin"));
82-
(len != field.attrs.len(), &*field)
87+
let pinned = len != field.attrs.len();
88+
89+
FieldInfo {
90+
field: &*field,
91+
pinned,
92+
}
8393
})
8494
.collect();
8595

86-
for (pinned, field) in &fields {
87-
if !pinned && is_phantom_pinned(&field.ty) {
96+
for field in &fields {
97+
let ident = field.field.ident.as_ref().unwrap();
98+
99+
if !field.pinned && is_phantom_pinned(&field.field.ty) {
88100
dcx.warn(
89-
field,
101+
field.field,
90102
format!(
91-
"The field `{}` of type `PhantomPinned` only has an effect \
103+
"The field `{ident}` of type `PhantomPinned` only has an effect \
92104
if it has the `#[pin]` attribute",
93-
field.ident.as_ref().unwrap(),
94105
),
95106
);
96107
}
@@ -143,7 +154,7 @@ fn is_phantom_pinned(ty: &Type) -> bool {
143154
fn generate_unpin_impl(
144155
ident: &Ident,
145156
generics: &Generics,
146-
fields: &[(bool, &Field)],
157+
fields: &[FieldInfo<'_>],
147158
) -> TokenStream {
148159
let (_, ty_generics, _) = generics.split_for_impl();
149160
let mut generics_with_pin_lt = generics.clone();
@@ -160,7 +171,7 @@ fn generate_unpin_impl(
160171
else {
161172
unreachable!()
162173
};
163-
let pinned_fields = fields.iter().filter_map(|(b, f)| b.then_some(f));
174+
let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| f.field);
164175
quote! {
165176
// This struct will be used for the unpin analysis. It is needed, because only structurally
166177
// pinned fields are relevant whether the struct should implement `Unpin`.
@@ -238,7 +249,7 @@ fn generate_projections(
238249
vis: &Visibility,
239250
ident: &Ident,
240251
generics: &Generics,
241-
fields: &[(bool, &Field)],
252+
fields: &[FieldInfo<'_>],
242253
) -> TokenStream {
243254
let (impl_generics, ty_generics, _) = generics.split_for_impl();
244255
let mut generics_with_pin_lt = generics.clone();
@@ -249,21 +260,21 @@ fn generate_projections(
249260

250261
let (fields_decl, fields_proj): (Vec<_>, Vec<_>) = fields
251262
.iter()
252-
.map(|(pinned, field)| {
263+
.map(|field| {
253264
let Field {
254265
vis,
255266
ident,
256267
ty,
257268
attrs,
258269
..
259-
} = field;
270+
} = &field.field;
260271

261272
let mut no_doc_attrs = attrs.clone();
262273
no_doc_attrs.retain(|a| !a.path().is_ident("doc"));
263274
let ident = ident
264275
.as_ref()
265276
.expect("only structs with named fields are supported");
266-
if *pinned {
277+
if field.pinned {
267278
(
268279
quote!(
269280
#(#attrs)*
@@ -291,12 +302,12 @@ fn generate_projections(
291302
.collect();
292303
let structurally_pinned_fields_docs = fields
293304
.iter()
294-
.filter_map(|(pinned, field)| pinned.then_some(field))
295-
.map(|Field { ident, .. }| format!(" - `{}`", ident.as_ref().unwrap()));
305+
.filter(|f| f.pinned)
306+
.map(|f| format!(" - `{}`", f.field.ident.as_ref().unwrap()));
296307
let not_structurally_pinned_fields_docs = fields
297308
.iter()
298-
.filter_map(|(pinned, field)| (!pinned).then_some(field))
299-
.map(|Field { ident, .. }| format!(" - `{}`", ident.as_ref().unwrap()));
309+
.filter(|f| !f.pinned)
310+
.map(|f| format!(" - `{}`", f.field.ident.as_ref().unwrap()));
300311
let docs = format!(" Pin-projections of [`{ident}`]");
301312
quote! {
302313
#[doc = #docs]
@@ -338,7 +349,7 @@ fn generate_the_pin_data(
338349
vis: &Visibility,
339350
struct_name: &Ident,
340351
generics: &Generics,
341-
fields: &[(bool, &Field)],
352+
fields: &[FieldInfo<'_>],
342353
) -> TokenStream {
343354
let (impl_generics, ty_generics, whr) = generics.split_for_impl();
344355

@@ -349,20 +360,20 @@ fn generate_the_pin_data(
349360
// The functions are `unsafe` to prevent accidentally calling them.
350361
let field_accessors = fields
351362
.iter()
352-
.map(|(pinned, field)| {
363+
.map(|f| {
353364
let Field {
354365
vis,
355366
ident,
356367
ty,
357368
attrs,
358369
..
359-
} = field;
370+
} = f.field;
360371

361372
let field_name = ident
362373
.as_ref()
363374
.expect("only structs with named fields are supported");
364375
let project_ident = format_ident!("__project_{field_name}");
365-
let (init_ty, init_fn, project_ty, project_body, pin_safety) = if *pinned {
376+
let (init_ty, init_fn, project_ty, project_body, pin_safety) = if f.pinned {
366377
(
367378
quote!(PinInit),
368379
quote!(__pinned_init),

0 commit comments

Comments
 (0)