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]
7mod auxiliary;
8
9use std::{marker::PhantomPinned, pin::Pin};
10
11use pin_project::pin_project;
12
13struct Always;
14
15// Use this type to check that `cfg(any())` is working properly.
16struct Never(PhantomPinned);
17
18#[test]
19fn 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]
128fn 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]
176fn 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