Skip to content

Commit d164f4c

Browse files
authored
Merge pull request #122 from nertpinx/extras
Allow other attributes in #[pin_data] structs
2 parents d5ac5a8 + 7073924 commit d164f4c

4 files changed

Lines changed: 52 additions & 24 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ libc = "0.2"
3232
trybuild = { version = "1.0", features = ["diff"] }
3333
macrotest = "1.0"
3434

35+
# Macro compatibility test
36+
serde = { version = "1.0", features = ["derive"] }
37+
3538
[lints.rust]
3639
stable_features = "allow"
3740
unused_features = "allow"

internal/src/pin_data.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use syn::{
77
parse_quote, parse_quote_spanned,
88
spanned::Spanned,
99
visit_mut::VisitMut,
10-
Field, Generics, Ident, Item, PathSegment, Type, TypePath, Visibility, WhereClause,
10+
Attribute, Field, Generics, Ident, Item, PathSegment, Type, TypePath, Visibility, WhereClause,
1111
};
1212

1313
use crate::diagnostics::{DiagCtxt, ErrorGuaranteed};
@@ -38,6 +38,7 @@ impl Parse for Args {
3838
struct FieldInfo<'a> {
3939
field: &'a Field,
4040
pinned: bool,
41+
cfg_attrs: Vec<&'a Attribute>,
4142
}
4243

4344
pub(crate) fn pin_data(
@@ -86,9 +87,16 @@ pub(crate) fn pin_data(
8687
field.attrs.retain(|a| !a.path().is_ident("pin"));
8788
let pinned = len != field.attrs.len();
8889

90+
let cfg_attrs = field
91+
.attrs
92+
.iter()
93+
.filter(|a| a.path().is_ident("cfg"))
94+
.collect();
95+
8996
FieldInfo {
9097
field: &*field,
9198
pinned,
99+
cfg_attrs,
92100
}
93101
})
94102
.collect();
@@ -171,7 +179,15 @@ fn generate_unpin_impl(
171179
else {
172180
unreachable!()
173181
};
174-
let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| f.field);
182+
let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| {
183+
let ident = f.field.ident.as_ref().unwrap();
184+
let ty = &f.field.ty;
185+
let cfg_attrs = &f.cfg_attrs;
186+
quote!(
187+
#(#cfg_attrs)*
188+
#ident: #ty
189+
)
190+
});
175191
quote! {
176192
// This struct will be used for the unpin analysis. It is needed, because only structurally
177193
// pinned fields are relevant whether the struct should implement `Unpin`.
@@ -259,39 +275,32 @@ fn generate_projections(
259275
let (fields_decl, fields_proj): (Vec<_>, Vec<_>) = fields
260276
.iter()
261277
.map(|field| {
262-
let Field {
263-
vis,
264-
ident,
265-
ty,
266-
attrs,
267-
..
268-
} = &field.field;
269-
270-
let mut no_doc_attrs = attrs.clone();
271-
no_doc_attrs.retain(|a| !a.path().is_ident("doc"));
278+
let Field { vis, ident, ty, .. } = &field.field;
279+
let cfg_attrs = &field.cfg_attrs;
280+
272281
let ident = ident
273282
.as_ref()
274283
.expect("only structs with named fields are supported");
275284
if field.pinned {
276285
(
277286
quote!(
278-
#(#attrs)*
287+
#(#cfg_attrs)*
279288
#vis #ident: ::core::pin::Pin<&'__pin mut #ty>,
280289
),
281290
quote!(
282-
#(#no_doc_attrs)*
291+
#(#cfg_attrs)*
283292
// SAFETY: this field is structurally pinned.
284293
#ident: unsafe { ::core::pin::Pin::new_unchecked(&mut #this.#ident) },
285294
),
286295
)
287296
} else {
288297
(
289298
quote!(
290-
#(#attrs)*
299+
#(#cfg_attrs)*
291300
#vis #ident: &'__pin mut #ty,
292301
),
293302
quote!(
294-
#(#no_doc_attrs)*
303+
#(#cfg_attrs)*
295304
#ident: &mut #this.#ident,
296305
),
297306
)
@@ -358,13 +367,8 @@ fn generate_the_pin_data(
358367
let field_accessors = fields
359368
.iter()
360369
.map(|f| {
361-
let Field {
362-
vis,
363-
ident,
364-
ty,
365-
attrs,
366-
..
367-
} = f.field;
370+
let Field { vis, ident, ty, .. } = f.field;
371+
let cfg_attrs = &f.cfg_attrs;
368372

369373
let field_name = ident
370374
.as_ref()
@@ -381,7 +385,7 @@ fn generate_the_pin_data(
381385
/// - `(*slot).#field_name` is properly aligned.
382386
/// - `(*slot).#field_name` points to uninitialized and exclusively accessed
383387
/// memory.
384-
#(#attrs)*
388+
#(#cfg_attrs)*
385389
#[inline(always)]
386390
#vis unsafe fn #field_name(
387391
self,

tests/attrs.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use pin_init::*;
2+
3+
#[pin_data]
4+
#[derive(serde::Serialize)]
5+
struct Foo {
6+
#[pin]
7+
#[serde()]
8+
#[cfg(test)]
9+
member: i8,
10+
#[pin]
11+
#[serde()]
12+
#[cfg(not(test))]
13+
member: u8,
14+
}
15+
16+
#[test]
17+
fn test_attribute() {
18+
stack_pin_init!(let p = init!(Foo { member: 0 }));
19+
println!("{}", p.member);
20+
}

0 commit comments

Comments
 (0)