1 #![warn(rust_2018_idioms, single_use_lifetimes)]
2 #![allow(dead_code)]
3 
4 // Refs: https://doc.rust-lang.org/reference/attributes.html
5 
6 #[macro_use]
7 mod auxiliary;
8 
9 use std::{marker::PhantomPinned, pin::Pin};
10 
11 use pin_project::pin_project;
12 
13 struct Always;
14 
15 // Use this type to check that `cfg(any())` is working properly.
16 struct Never(PhantomPinned);
17 
18 #[test]
cfg()19 fn cfg() {
20     // structs
21 
22     #[pin_project(project_replace)]
23     struct SameName {
24         #[cfg(not(any()))]
25         #[pin]
26         inner: Always,
27         #[cfg(any())]
28         #[pin]
29         inner: Never,
30     }
31 
32     assert_unpin!(SameName);
33 
34     let _ = SameName { inner: Always };
35 
36     #[pin_project(project_replace)]
37     struct DifferentName {
38         #[cfg(not(any()))]
39         #[pin]
40         a: Always,
41         #[cfg(any())]
42         #[pin]
43         n: Never,
44     }
45 
46     assert_unpin!(DifferentName);
47 
48     let _ = DifferentName { a: Always };
49 
50     #[pin_project(project_replace)]
51     struct TupleStruct(
52         #[cfg(not(any()))]
53         #[pin]
54         Always,
55         #[cfg(any())]
56         #[pin]
57         Never,
58     );
59 
60     assert_unpin!(TupleStruct);
61 
62     let _ = TupleStruct(Always);
63 
64     // enums
65 
66     #[pin_project(
67         project = VariantProj,
68         project_ref = VariantProjRef,
69         project_replace = VariantProjOwn,
70     )]
71     enum Variant {
72         #[cfg(not(any()))]
73         Inner(#[pin] Always),
74         #[cfg(any())]
75         Inner(#[pin] Never),
76 
77         #[cfg(not(any()))]
78         A(#[pin] Always),
79         #[cfg(any())]
80         N(#[pin] Never),
81     }
82 
83     assert_unpin!(Variant);
84 
85     let _ = Variant::Inner(Always);
86     let _ = Variant::A(Always);
87 
88     #[pin_project(
89         project = FieldProj,
90         project_ref = FieldProjRef,
91         project_replace = FieldProjOwn,
92     )]
93     enum Field {
94         SameName {
95             #[cfg(not(any()))]
96             #[pin]
97             inner: Always,
98             #[cfg(any())]
99             #[pin]
100             inner: Never,
101         },
102         DifferentName {
103             #[cfg(not(any()))]
104             #[pin]
105             a: Always,
106             #[cfg(any())]
107             #[pin]
108             n: Never,
109         },
110         TupleVariant(
111             #[cfg(not(any()))]
112             #[pin]
113             Always,
114             #[cfg(any())]
115             #[pin]
116             Never,
117         ),
118     }
119 
120     assert_unpin!(Field);
121 
122     let _ = Field::SameName { inner: Always };
123     let _ = Field::DifferentName { a: Always };
124     let _ = Field::TupleVariant(Always);
125 }
126 
127 #[test]
cfg_attr()128 fn cfg_attr() {
129     #[pin_project(project_replace)]
130     struct SameCfg {
131         #[cfg(not(any()))]
132         #[cfg_attr(not(any()), pin)]
133         inner: Always,
134         #[cfg(any())]
135         #[cfg_attr(any(), pin)]
136         inner: Never,
137     }
138 
139     assert_unpin!(SameCfg);
140 
141     let mut x = SameCfg { inner: Always };
142     let x = Pin::new(&mut x).project();
143     let _: Pin<&mut Always> = x.inner;
144 
145     #[pin_project(project_replace)]
146     struct DifferentCfg {
147         #[cfg(not(any()))]
148         #[cfg_attr(any(), pin)]
149         inner: Always,
150         #[cfg(any())]
151         #[cfg_attr(not(any()), pin)]
152         inner: Never,
153     }
154 
155     assert_unpin!(DifferentCfg);
156 
157     let mut x = DifferentCfg { inner: Always };
158     let x = Pin::new(&mut x).project();
159     let _: &mut Always = x.inner;
160 
161     #[cfg_attr(not(any()), pin_project)]
162     struct Foo<T> {
163         #[cfg_attr(not(any()), pin)]
164         inner: T,
165     }
166 
167     assert_unpin!(Foo<()>);
168     assert_not_unpin!(Foo<PhantomPinned>);
169 
170     let mut x = Foo { inner: 0_u8 };
171     let x = Pin::new(&mut x).project();
172     let _: Pin<&mut u8> = x.inner;
173 }
174 
175 #[test]
cfg_attr_any_packed()176 fn cfg_attr_any_packed() {
177     // Since `cfg(any())` can never be true, it is okay for this to pass.
178     #[pin_project(project_replace)]
179     #[cfg_attr(any(), repr(packed))]
180     struct Struct {
181         #[pin]
182         f: u32,
183     }
184 }
185