Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a99ad13

Browse files
committedSep 7, 2019
Move automatic generation of Unpin implementation to proc-macro-derive
To generate the correct `Unpin` implementation, we need to collect the types of the pinned fields. However, since proc-macro-attribute is applied before cfg, we cannot be collecting field types at this timing. So instead of generating the `Unpin` implementation here, we need to delegate automatic generation of the `Unpin` implementation to proc-macro-derive.
1 parent 69f8014 commit a99ad13

25 files changed

+668
-260
lines changed
 

‎azure-pipelines.yml

+7-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jobs:
3939
parameters:
4040
toolchain: nightly
4141
name: nightly
42+
cross: true
4243

4344
- job: compiletest
4445
pool:
@@ -49,7 +50,9 @@ jobs:
4950
toolchain: nightly
5051
- script: |
5152
cargo clean
52-
RUSTFLAGS='--cfg compiletest --cfg pin_project_show_unpin_struct' cargo test -p pin-project --all-features --test compiletest
53+
cargo test -p pin-project --all-features --test compiletest
54+
env:
55+
RUSTFLAGS: -Dwarnings --cfg compiletest --cfg pin_project_show_unpin_struct
5356
displayName: compiletest
5457
5558
- job: clippy
@@ -122,5 +125,7 @@ jobs:
122125
parameters:
123126
toolchain: nightly
124127
- script: |
125-
RUSTDOCFLAGS=-Dwarnings cargo doc --no-deps --all --all-features
128+
cargo doc --no-deps --all --all-features
129+
env:
130+
RUSTDOCFLAGS: -Dwarnings
126131
displayName: cargo doc

‎ci/azure-test.yml

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
parameters:
2-
vmImage: ubuntu-16.04
32
cmd: test
43

54
jobs:
65
- job: ${{ parameters.name }}
6+
strategy:
7+
matrix:
8+
Linux:
9+
vmImage: ubuntu-16.04
10+
${{ if parameters.cross }}:
11+
MacOS:
12+
vmImage: macOS-10.13
13+
Windows:
14+
vmImage: vs2017-win2016
715
pool:
8-
vmImage: ${{ parameters.vmImage }}
16+
vmImage: $(vmImage)
917

1018
steps:
1119
- template: azure-install-rust.yml

‎compiletest.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
# A script to run compile tests with the same condition that pin-project executes with CI.
4+
5+
rm -rf target/debug/deps/libpin_project* && RUSTFLAGS='--cfg compiletest --cfg pin_project_show_unpin_struct' cargo test -p pin-project --all-features --test compiletest

‎pin-project-internal/src/lib.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,8 @@ use syn::parse::Nothing;
333333
/// [`pinned_drop`]: ./attr.pinned_drop.html
334334
#[proc_macro_attribute]
335335
pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
336-
pin_project::attribute(args.into(), input.into()).into()
336+
let input = syn::parse_macro_input!(input);
337+
pin_project::attribute(args.into(), input).into()
337338
}
338339

339340
// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged.
@@ -372,7 +373,8 @@ pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
372373
#[proc_macro_attribute]
373374
pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
374375
let _: Nothing = syn::parse_macro_input!(args);
375-
pinned_drop::attribute(input.into()).into()
376+
let input = syn::parse_macro_input!(input);
377+
pinned_drop::attribute(&input).into()
376378
}
377379

378380
// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged.
@@ -493,7 +495,15 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
493495
#[proc_macro_attribute]
494496
pub fn project(args: TokenStream, input: TokenStream) -> TokenStream {
495497
let _: Nothing = syn::parse_macro_input!(args);
496-
project::attribute(input.into()).into()
498+
let input = syn::parse_macro_input!(input);
499+
project::attribute(input).into()
500+
}
501+
502+
#[doc(hidden)]
503+
#[proc_macro_derive(__PinProjectAutoImplUnpin, attributes(pin))]
504+
pub fn derive_unpin(input: TokenStream) -> TokenStream {
505+
let input = syn::parse_macro_input!(input);
506+
pin_project::derive(input).into()
497507
}
498508

499509
#[cfg(feature = "renamed")]

‎pin-project-internal/src/pin_project/enums.rs

+57-28
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use proc_macro2::TokenStream;
22
use quote::{format_ident, quote, ToTokens};
3-
use syn::{parse::Nothing, Field, Fields, FieldsNamed, FieldsUnnamed, ItemEnum, Result, Variant};
3+
use syn::{Field, Fields, FieldsNamed, FieldsUnnamed, ItemEnum, Result, Variant};
44

5-
use crate::utils::VecExt;
5+
use crate::utils::collect_cfg;
66

7-
use super::{Context, PIN};
7+
use super::Context;
88

99
pub(super) fn parse(cx: &mut Context, mut item: ItemEnum) -> Result<TokenStream> {
1010
if item.variants.is_empty() {
11-
return Err(error!(
12-
item,
13-
"#[pin_project] attribute may not be used on enums without variants"
11+
return Err(syn::Error::new(
12+
item.brace_token.span,
13+
"#[pin_project] attribute may not be used on enums without variants",
1414
));
1515
}
1616
let has_field = item.variants.iter().try_fold(false, |has_field, v| {
@@ -62,17 +62,22 @@ pub(super) fn parse(cx: &mut Context, mut item: ItemEnum) -> Result<TokenStream>
6262
fn variants(cx: &mut Context, item: &mut ItemEnum) -> Result<(Vec<TokenStream>, Vec<TokenStream>)> {
6363
let mut proj_variants = Vec::with_capacity(item.variants.len());
6464
let mut proj_arms = Vec::with_capacity(item.variants.len());
65-
for Variant { fields, ident, .. } in &mut item.variants {
65+
for Variant { attrs, fields, ident, .. } in &mut item.variants {
6666
let (proj_pat, proj_body, proj_fields) = match fields {
6767
Fields::Unnamed(fields) => unnamed(cx, fields)?,
6868
Fields::Named(fields) => named(cx, fields)?,
6969
Fields::Unit => (TokenStream::new(), TokenStream::new(), TokenStream::new()),
7070
};
71+
let cfg = collect_cfg(attrs);
7172
let Context { orig_ident, proj_ident, .. } = &cx;
72-
let proj_arm = quote!(#orig_ident::#ident #proj_pat => #proj_ident::#ident #proj_body );
73-
let proj_variant = quote!(#ident #proj_fields);
74-
proj_arms.push(proj_arm);
75-
proj_variants.push(proj_variant);
73+
proj_variants.push(quote! {
74+
#(#cfg)* #ident #proj_fields
75+
});
76+
proj_arms.push(quote! {
77+
#(#cfg)* #orig_ident::#ident #proj_pat => {
78+
#proj_ident::#ident #proj_body
79+
}
80+
});
7681
}
7782

7883
Ok((proj_variants, proj_arms))
@@ -86,18 +91,27 @@ fn named(
8691
let mut proj_body = Vec::with_capacity(fields.len());
8792
let mut proj_fields = Vec::with_capacity(fields.len());
8893
for Field { attrs, ident, ty, .. } in fields {
89-
if let Some(attr) = attrs.find_remove(PIN) {
90-
let _: Nothing = syn::parse2(attr.tokens)?;
91-
cx.push_unpin_bounds(ty.clone());
94+
let cfg = collect_cfg(attrs);
95+
if cx.find_pin_attr(attrs)? {
9296
let lifetime = &cx.lifetime;
93-
proj_fields.push(quote!(#ident: ::core::pin::Pin<&#lifetime mut #ty>));
94-
proj_body.push(quote!(#ident: ::core::pin::Pin::new_unchecked(#ident)));
97+
proj_fields.push(quote! {
98+
#(#cfg)* #ident: ::core::pin::Pin<&#lifetime mut #ty>
99+
});
100+
proj_body.push(quote! {
101+
#(#cfg)* #ident: ::core::pin::Pin::new_unchecked(#ident)
102+
});
95103
} else {
96104
let lifetime = &cx.lifetime;
97-
proj_fields.push(quote!(#ident: &#lifetime mut #ty));
98-
proj_body.push(quote!(#ident));
105+
proj_fields.push(quote! {
106+
#(#cfg)* #ident: &#lifetime mut #ty
107+
});
108+
proj_body.push(quote! {
109+
#(#cfg)* #ident: #ident
110+
});
99111
}
100-
proj_pat.push(ident);
112+
proj_pat.push(quote! {
113+
#(#cfg)* #ident
114+
});
101115
}
102116

103117
let proj_pat = quote!({ #(#proj_pat),* });
@@ -114,19 +128,34 @@ fn unnamed(
114128
let mut proj_body = Vec::with_capacity(fields.len());
115129
let mut proj_fields = Vec::with_capacity(fields.len());
116130
for (i, Field { attrs, ty, .. }) in fields.iter_mut().enumerate() {
117-
let x = format_ident!("_x{}", i);
118-
if let Some(attr) = attrs.find_remove(PIN) {
119-
let _: Nothing = syn::parse2(attr.tokens)?;
120-
cx.push_unpin_bounds(ty.clone());
131+
let id = format_ident!("_x{}", i);
132+
let cfg = collect_cfg(attrs);
133+
if !cfg.is_empty() {
134+
return Err(error!(
135+
cfg.first(),
136+
"`cfg` attributes on the field of tuple variants are not supported"
137+
));
138+
}
139+
if cx.find_pin_attr(attrs)? {
121140
let lifetime = &cx.lifetime;
122-
proj_fields.push(quote!(::core::pin::Pin<&#lifetime mut #ty>));
123-
proj_body.push(quote!(::core::pin::Pin::new_unchecked(#x)));
141+
proj_fields.push(quote! {
142+
::core::pin::Pin<&#lifetime mut #ty>
143+
});
144+
proj_body.push(quote! {
145+
::core::pin::Pin::new_unchecked(#id)
146+
});
124147
} else {
125148
let lifetime = &cx.lifetime;
126-
proj_fields.push(quote!(&#lifetime mut #ty));
127-
proj_body.push(quote!(#x));
149+
proj_fields.push(quote! {
150+
&#lifetime mut #ty
151+
});
152+
proj_body.push(quote! {
153+
#id
154+
});
128155
}
129-
proj_pat.push(x);
156+
proj_pat.push(quote! {
157+
#id
158+
});
130159
}
131160

132161
let proj_pat = quote!((#(#proj_pat),*));

‎pin-project-internal/src/pin_project/mod.rs

+273-189
Large diffs are not rendered by default.

‎pin-project-internal/src/pin_project/structs.rs

+40-20
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use proc_macro2::TokenStream;
22
use quote::{quote, ToTokens};
3-
use syn::{parse::Nothing, Field, Fields, FieldsNamed, FieldsUnnamed, Index, ItemStruct, Result};
3+
use syn::{Field, Fields, FieldsNamed, FieldsUnnamed, Index, ItemStruct, Result};
44

5-
use crate::utils::VecExt;
5+
use crate::utils::collect_cfg;
66

7-
use super::{Context, PIN};
7+
use super::Context;
88

99
pub(super) fn parse(cx: &mut Context, mut item: ItemStruct) -> Result<TokenStream> {
1010
let (proj_fields, proj_init) = match &mut item.fields {
@@ -19,7 +19,7 @@ pub(super) fn parse(cx: &mut Context, mut item: ItemStruct) -> Result<TokenStrea
1919
}
2020
Fields::Unit => {
2121
return Err(error!(
22-
item,
22+
item.ident,
2323
"#[pin_project] attribute may not be used on structs with units"
2424
));
2525
}
@@ -61,16 +61,23 @@ fn named(
6161
let mut proj_fields = Vec::with_capacity(fields.len());
6262
let mut proj_init = Vec::with_capacity(fields.len());
6363
for Field { attrs, ident, ty, .. } in fields {
64-
if let Some(attr) = attrs.find_remove(PIN) {
65-
let _: Nothing = syn::parse2(attr.tokens)?;
66-
cx.push_unpin_bounds(ty.clone());
64+
let cfg = collect_cfg(attrs);
65+
if cx.find_pin_attr(attrs)? {
6766
let lifetime = &cx.lifetime;
68-
proj_fields.push(quote!(#ident: ::core::pin::Pin<&#lifetime mut #ty>));
69-
proj_init.push(quote!(#ident: ::core::pin::Pin::new_unchecked(&mut this.#ident)));
67+
proj_fields.push(quote! {
68+
#(#cfg)* #ident: ::core::pin::Pin<&#lifetime mut #ty>
69+
});
70+
proj_init.push(quote! {
71+
#(#cfg)* #ident: ::core::pin::Pin::new_unchecked(&mut this.#ident)
72+
});
7073
} else {
7174
let lifetime = &cx.lifetime;
72-
proj_fields.push(quote!(#ident: &#lifetime mut #ty));
73-
proj_init.push(quote!(#ident: &mut this.#ident));
75+
proj_fields.push(quote! {
76+
#(#cfg)* #ident: &#lifetime mut #ty
77+
});
78+
proj_init.push(quote! {
79+
#(#cfg)* #ident: &mut this.#ident
80+
});
7481
}
7582
}
7683

@@ -85,18 +92,31 @@ fn unnamed(
8592
) -> Result<(TokenStream, TokenStream)> {
8693
let mut proj_fields = Vec::with_capacity(fields.len());
8794
let mut proj_init = Vec::with_capacity(fields.len());
88-
for (i, Field { attrs, ty, .. }) in fields.iter_mut().enumerate() {
89-
let i = Index::from(i);
90-
if let Some(attr) = attrs.find_remove(PIN) {
91-
let _: Nothing = syn::parse2(attr.tokens)?;
92-
cx.push_unpin_bounds(ty.clone());
95+
for (index, Field { attrs, ty, .. }) in fields.iter_mut().enumerate() {
96+
let index = Index::from(index);
97+
let cfg = collect_cfg(attrs);
98+
if !cfg.is_empty() {
99+
return Err(error!(
100+
cfg.first(),
101+
"`cfg` attributes on the field of tuple structs are not supported"
102+
));
103+
}
104+
if cx.find_pin_attr(attrs)? {
93105
let lifetime = &cx.lifetime;
94-
proj_fields.push(quote!(::core::pin::Pin<&#lifetime mut #ty>));
95-
proj_init.push(quote!(::core::pin::Pin::new_unchecked(&mut this.#i)));
106+
proj_fields.push(quote! {
107+
::core::pin::Pin<&#lifetime mut #ty>
108+
});
109+
proj_init.push(quote! {
110+
::core::pin::Pin::new_unchecked(&mut this.#index)
111+
});
96112
} else {
97113
let lifetime = &cx.lifetime;
98-
proj_fields.push(quote!(&#lifetime mut #ty));
99-
proj_init.push(quote!(&mut this.#i));
114+
proj_fields.push(quote! {
115+
&#lifetime mut #ty
116+
});
117+
proj_init.push(quote! {
118+
&mut this.#index
119+
});
100120
}
101121
}
102122

‎pin-project-internal/src/pinned_drop.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use syn::{
77

88
use crate::utils::crate_path;
99

10-
pub(super) fn attribute(input: TokenStream) -> TokenStream {
10+
pub(crate) fn attribute(input: &ItemFn) -> TokenStream {
1111
parse(input).unwrap_or_else(|e| e.to_compile_error())
1212
}
1313

@@ -34,8 +34,7 @@ fn parse_arg(arg: &FnArg) -> Result<&Type> {
3434
Err(error!(arg, "#[pinned_drop] function must take a argument `Pin<&mut Type>`"))
3535
}
3636

37-
fn parse(input: TokenStream) -> Result<TokenStream> {
38-
let item: ItemFn = syn::parse2(input)?;
37+
fn parse(item: &ItemFn) -> Result<TokenStream> {
3938
if let ReturnType::Type(_, ty) = &item.sig.output {
4039
match &**ty {
4140
Type::Tuple(TypeTuple { elems, .. }) if elems.is_empty() => {}

‎pin-project-internal/src/project.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ use crate::utils::{proj_generics, proj_ident, proj_lifetime_name, VecExt, DEFAUL
1111
/// The attribute name.
1212
const NAME: &str = "project";
1313

14-
pub(super) fn attribute(input: TokenStream) -> TokenStream {
14+
pub(crate) fn attribute(input: Stmt) -> TokenStream {
1515
parse(input).unwrap_or_else(|e| e.to_compile_error())
1616
}
1717

18-
fn parse(input: TokenStream) -> Result<TokenStream> {
19-
let mut stmt = syn::parse2(input)?;
18+
fn parse(mut stmt: Stmt) -> Result<TokenStream> {
2019
match &mut stmt {
2120
Stmt::Expr(Expr::Match(expr)) | Stmt::Semi(Expr::Match(expr), _) => {
2221
Context::default().replace_expr_match(expr)

‎pin-project-internal/src/utils.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,21 @@ pub(crate) fn proj_generics(generics: &mut Generics, lifetime: Lifetime) {
5858
);
5959
}
6060

61+
pub(crate) fn collect_cfg(attrs: &[Attribute]) -> Vec<Attribute> {
62+
attrs.iter().filter(|attr| attr.path.is_ident("cfg")).cloned().collect()
63+
}
64+
6165
pub(crate) trait VecExt {
66+
fn position(&self, ident: &str) -> Option<usize>;
6267
fn find_remove(&mut self, ident: &str) -> Option<Attribute>;
6368
}
6469

6570
impl VecExt for Vec<Attribute> {
71+
fn position(&self, ident: &str) -> Option<usize> {
72+
self.iter().position(|attr| attr.path.is_ident(ident))
73+
}
6674
fn find_remove(&mut self, ident: &str) -> Option<Attribute> {
67-
self.iter().position(|attr| attr.path.is_ident(ident)).map(|i| self.remove(i))
75+
self.position(ident).map(|i| self.remove(i))
6876
}
6977
}
7078

‎src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ pub mod __private {
124124
use super::UnsafeUnpin;
125125
use core::pin::Pin;
126126

127+
#[doc(hidden)]
128+
pub use pin_project_internal::__PinProjectAutoImplUnpin;
129+
127130
// This is an internal helper trait used by `pin-project-internal`.
128131
// This allows us to force an error if the user tries to provide
129132
// a regular `Drop` impl when they specify the `PinnedDrop` argument.

‎tests/cfg.rs

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#![warn(unsafe_code)]
2+
#![warn(rust_2018_idioms, single_use_lifetimes)]
3+
#![allow(dead_code)]
4+
5+
// Refs: https://doc.rust-lang.org/reference/attributes.html
6+
7+
use core::marker::PhantomPinned;
8+
use pin_project::pin_project;
9+
10+
#[cfg(all(unix, target_os = "macos"))]
11+
pub struct MacOS;
12+
#[cfg(all(unix, not(target_os = "macos")))]
13+
pub struct Linux;
14+
#[cfg(windows)]
15+
pub struct Windows;
16+
17+
// Using `PhantomPinned: Unpin` without #![feature(trivial_bounds)] will result in an error.
18+
// Use this type to check that `cfg(any())` is working properly.
19+
pub struct Any(PhantomPinned);
20+
21+
#[test]
22+
fn struct_() {
23+
#[pin_project]
24+
pub struct SameName {
25+
#[cfg(all(unix, target_os = "macos"))]
26+
#[pin]
27+
inner: MacOS,
28+
#[cfg(all(unix, not(target_os = "macos")))]
29+
#[pin]
30+
inner: Linux,
31+
#[cfg(windows)]
32+
#[pin]
33+
inner: Windows,
34+
#[cfg(any())]
35+
#[pin]
36+
any: Any,
37+
}
38+
39+
#[cfg(all(unix, target_os = "macos"))]
40+
let _x = SameName { inner: MacOS };
41+
#[cfg(all(unix, not(target_os = "macos")))]
42+
let _x = SameName { inner: Linux };
43+
#[cfg(windows)]
44+
let _x = SameName { inner: Windows };
45+
46+
#[pin_project]
47+
pub struct DifferentName {
48+
#[cfg(all(unix, target_os = "macos"))]
49+
#[pin]
50+
m: MacOS,
51+
#[cfg(all(unix, not(target_os = "macos")))]
52+
#[pin]
53+
l: Linux,
54+
#[cfg(windows)]
55+
#[pin]
56+
w: Windows,
57+
#[cfg(any())]
58+
#[pin]
59+
a: Any,
60+
}
61+
62+
#[cfg(all(unix, target_os = "macos"))]
63+
let _x = DifferentName { m: MacOS };
64+
#[cfg(all(unix, not(target_os = "macos")))]
65+
let _x = DifferentName { l: Linux };
66+
#[cfg(windows)]
67+
let _x = DifferentName { w: Windows };
68+
}
69+
70+
#[test]
71+
fn enum_() {
72+
#[pin_project]
73+
pub enum Variant {
74+
#[cfg(all(unix, target_os = "macos"))]
75+
Inner(#[pin] MacOS),
76+
#[cfg(all(unix, not(target_os = "macos")))]
77+
Inner(#[pin] Linux),
78+
#[cfg(windows)]
79+
Inner(#[pin] Windows),
80+
81+
#[cfg(all(unix, target_os = "macos"))]
82+
MacOS(#[pin] MacOS),
83+
#[cfg(all(unix, not(target_os = "macos")))]
84+
Linux(#[pin] Linux),
85+
#[cfg(windows)]
86+
Windows(#[pin] Windows),
87+
#[cfg(any())]
88+
Any(#[pin] Any),
89+
}
90+
91+
#[cfg(all(unix, target_os = "macos"))]
92+
let _x = Variant::Inner(MacOS);
93+
#[cfg(all(unix, not(target_os = "macos")))]
94+
let _x = Variant::Inner(Linux);
95+
#[cfg(windows)]
96+
let _x = Variant::Inner(Windows);
97+
98+
#[cfg(all(unix, target_os = "macos"))]
99+
let _x = Variant::MacOS(MacOS);
100+
#[cfg(all(unix, not(target_os = "macos")))]
101+
let _x = Variant::Linux(Linux);
102+
#[cfg(windows)]
103+
let _x = Variant::Windows(Windows);
104+
105+
#[pin_project]
106+
pub enum Field {
107+
SameName {
108+
#[cfg(all(unix, target_os = "macos"))]
109+
#[pin]
110+
inner: MacOS,
111+
#[cfg(all(unix, not(target_os = "macos")))]
112+
#[pin]
113+
inner: Linux,
114+
#[cfg(windows)]
115+
#[pin]
116+
inner: Windows,
117+
#[cfg(any())]
118+
#[pin]
119+
any: Any,
120+
},
121+
DifferentName {
122+
#[cfg(all(unix, target_os = "macos"))]
123+
#[pin]
124+
m: MacOS,
125+
#[cfg(all(unix, not(target_os = "macos")))]
126+
#[pin]
127+
l: Linux,
128+
#[cfg(windows)]
129+
#[pin]
130+
w: Windows,
131+
#[cfg(any())]
132+
#[pin]
133+
any: Any,
134+
},
135+
}
136+
137+
#[cfg(all(unix, target_os = "macos"))]
138+
let _x = Field::SameName { inner: MacOS };
139+
#[cfg(all(unix, not(target_os = "macos")))]
140+
let _x = Field::SameName { inner: Linux };
141+
#[cfg(windows)]
142+
let _x = Field::SameName { inner: Windows };
143+
144+
#[cfg(all(unix, target_os = "macos"))]
145+
let _x = Field::DifferentName { m: MacOS };
146+
#[cfg(all(unix, not(target_os = "macos")))]
147+
let _x = Field::DifferentName { l: Linux };
148+
#[cfg(windows)]
149+
let _x = Field::DifferentName { w: Windows };
150+
}

‎tests/pinned_drop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![no_std]
21
#![warn(unsafe_code)]
32
#![warn(rust_2018_idioms, single_use_lifetimes)]
43
#![allow(dead_code)]

‎tests/project.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg(feature = "project_attr")]
2-
#![no_std]
32
#![warn(unsafe_code)]
43
#![warn(rust_2018_idioms, single_use_lifetimes)]
54
#![allow(dead_code)]

‎tests/project_nightly.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg(feature = "project_attr")]
2-
#![no_std]
32
#![warn(unsafe_code)]
43
#![warn(rust_2018_idioms, single_use_lifetimes)]
54
#![allow(dead_code)]

‎tests/ui/cfg/tuple-struct.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-fail
2+
3+
use pin_project::pin_project;
4+
5+
#[pin_project]
6+
pub struct TupleStruct(
7+
#[cfg(unix)] //~ ERROR `cfg` attributes on the field of tuple structs are not supported
8+
#[pin]
9+
Unix,
10+
#[cfg(windows)]
11+
#[pin]
12+
Windows,
13+
);
14+
15+
fn main() {}

‎tests/ui/cfg/tuple-struct.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `cfg` attributes on the field of tuple structs are not supported
2+
--> $DIR/tuple-struct.rs:7:5
3+
|
4+
7 | #[cfg(unix)] //~ ERROR `cfg` attributes on the field of tuple structs are not supported
5+
| ^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

‎tests/ui/cfg/tuple-variant.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// compile-fail
2+
3+
use pin_project::pin_project;
4+
5+
#[pin_project]
6+
pub enum Field {
7+
Tuple(
8+
#[cfg(unix)] //~ ERROR `cfg` attributes on the field of tuple variants are not supported
9+
#[pin]
10+
Unix,
11+
#[cfg(windows)]
12+
#[pin]
13+
Windows,
14+
),
15+
}
16+
17+
fn main() {}

‎tests/ui/cfg/tuple-variant.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `cfg` attributes on the field of tuple variants are not supported
2+
--> $DIR/tuple-variant.rs:8:9
3+
|
4+
8 | #[cfg(unix)] //~ ERROR `cfg` attributes on the field of tuple variants are not supported
5+
| ^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// compile-fail
2+
3+
// Refs: https://github.com/rust-lang/rust/issues/48214
4+
5+
use core::marker::PhantomPinned;
6+
use pin_project::pin_project;
7+
8+
struct Inner(PhantomPinned);
9+
10+
#[pin_project]
11+
struct Foo(#[pin] Inner);
12+
13+
fn main() {}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructFoo`
2+
--> $DIR/phantom-pinned.rs:10:1
3+
|
4+
10 | #[pin_project]
5+
| ^^^^^^^^^^^^^^ within `UnpinStructFoo`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
6+
|
7+
= help: the following implementations were found:
8+
<std::marker::PhantomPinned as std::marker::Unpin>
9+
= note: required because it appears within the type `Inner`
10+
= note: required because it appears within the type `UnpinStructFoo`
11+
= help: see issue #48214
12+
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0277`.

‎tests/ui/pin_project/proper_unpin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// compile-fail
22

3-
use pin_project::{pin_project, pinned_drop};
3+
use pin_project::pin_project;
44
use std::pin::Pin;
55

66
struct Inner<T> {
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-pass
2+
3+
// Refs: https://github.com/rust-lang/rust/issues/48214
4+
5+
#![feature(trivial_bounds)]
6+
7+
use core::marker::PhantomPinned;
8+
use pin_project::pin_project;
9+
10+
struct Inner(PhantomPinned);
11+
12+
#[pin_project]
13+
struct Foo(#[pin] Inner);
14+
15+
fn main() {}

‎tests/ui/pin_project/unsupported.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ error: #[pin_project] attribute may not be used on structs with zero fields
1111
| ^^
1212

1313
error: #[pin_project] attribute may not be used on structs with units
14-
--> $DIR/unsupported.rs:12:1
14+
--> $DIR/unsupported.rs:12:8
1515
|
1616
12 | struct Struct3; //~ ERROR may not be used on structs with units
17-
| ^^^^^^^^^^^^^^^
17+
| ^^^^^^^
1818

1919
error: #[pin_project] attribute may not be used on enums without variants
20-
--> $DIR/unsupported.rs:15:1
20+
--> $DIR/unsupported.rs:15:12
2121
|
2222
15 | enum Enum1 {} //~ ERROR may not be used on enums without variants
23-
| ^^^^^^^^^^^^^
23+
| ^^
2424

2525
error: #[pin_project] attribute may not be used on enums with discriminants
2626
--> $DIR/unsupported.rs:19:9

‎tests/unsafe_unpin.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![no_std]
21
#![warn(unsafe_code)]
32
#![warn(rust_2018_idioms, single_use_lifetimes)]
43
#![allow(dead_code)]

0 commit comments

Comments
 (0)
Please sign in to comment.