]> git.proxmox.com Git - rustc.git/blame - vendor/syn/tests/test_generics.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / syn / tests / test_generics.rs
CommitLineData
e74abb32
XL
1#[macro_use]
2mod macros;
3
4use quote::quote;
5use syn::{DeriveInput, ItemFn, TypeParamBound, WhereClause, WherePredicate};
6
7#[test]
8fn test_split_for_impl() {
9 let input = quote! {
10 struct S<'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug;
11 };
12
13 snapshot!(input as DeriveInput, @r###"
60c5eb7d
XL
14 DeriveInput {
15 vis: Inherited,
16 ident: "S",
17 generics: Generics {
18 lt_token: Some,
19 params: [
20 Lifetime(LifetimeDef {
21 lifetime: Lifetime {
22 ident: "a",
23 },
24 }),
25 Lifetime(LifetimeDef {
26 lifetime: Lifetime {
27 ident: "b",
28 },
29 colon_token: Some,
30 bounds: [
31 Lifetime {
32 ident: "a",
33 },
34 ],
35 }),
36 Type(TypeParam {
37 attrs: [
38 Attribute {
39 style: Outer,
40 path: Path {
41 segments: [
42 PathSegment {
43 ident: "may_dangle",
44 arguments: None,
45 },
46 ],
47 },
f035d41b 48 tokens: TokenStream(``),
60c5eb7d
XL
49 },
50 ],
51 ident: "T",
52 colon_token: Some,
53 bounds: [
54 Lifetime(Lifetime {
55 ident: "a",
56 }),
57 ],
58 eq_token: Some,
59 default: Some(Type::Tuple),
60 }),
61 ],
62 gt_token: Some,
63 where_clause: Some(WhereClause {
64 predicates: [
65 Type(PredicateType {
66 bounded_ty: Type::Path {
67 path: Path {
68 segments: [
69 PathSegment {
70 ident: "T",
71 arguments: None,
72 },
73 ],
74 },
75 },
76 bounds: [
77 Trait(TraitBound {
78 modifier: None,
79 path: Path {
80 segments: [
81 PathSegment {
82 ident: "Debug",
83 arguments: None,
84 },
85 ],
86 },
87 }),
88 ],
89 }),
90 ],
91 }),
92 },
93 data: Data::Struct {
94 fields: Unit,
95 semi_token: Some,
96 },
97 }
e74abb32
XL
98 "###);
99
100 let generics = input.generics;
101 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
102
103 let generated = quote! {
104 impl #impl_generics MyTrait for Test #ty_generics #where_clause {}
105 };
106 let expected = quote! {
107 impl<'a, 'b: 'a, #[may_dangle] T: 'a> MyTrait
108 for Test<'a, 'b, T>
109 where
110 T: Debug
111 {}
112 };
113 assert_eq!(generated.to_string(), expected.to_string());
114
115 let turbofish = ty_generics.as_turbofish();
116 let generated = quote! {
117 Test #turbofish
118 };
119 let expected = quote! {
120 Test::<'a, 'b, T>
121 };
122 assert_eq!(generated.to_string(), expected.to_string());
123}
124
125#[test]
126fn test_ty_param_bound() {
127 let tokens = quote!('a);
128 snapshot!(tokens as TypeParamBound, @r###"
60c5eb7d
XL
129 Lifetime(Lifetime {
130 ident: "a",
131 })
e74abb32
XL
132 "###);
133
134 let tokens = quote!('_);
135 snapshot!(tokens as TypeParamBound, @r###"
60c5eb7d
XL
136 Lifetime(Lifetime {
137 ident: "_",
138 })
e74abb32
XL
139 "###);
140
141 let tokens = quote!(Debug);
142 snapshot!(tokens as TypeParamBound, @r###"
60c5eb7d
XL
143 Trait(TraitBound {
144 modifier: None,
145 path: Path {
146 segments: [
147 PathSegment {
148 ident: "Debug",
149 arguments: None,
150 },
151 ],
152 },
153 })
e74abb32
XL
154 "###);
155
156 let tokens = quote!(?Sized);
157 snapshot!(tokens as TypeParamBound, @r###"
60c5eb7d
XL
158 Trait(TraitBound {
159 modifier: Maybe,
160 path: Path {
161 segments: [
162 PathSegment {
163 ident: "Sized",
164 arguments: None,
165 },
166 ],
167 },
168 })
e74abb32
XL
169 "###);
170}
171
172#[test]
173fn test_fn_precedence_in_where_clause() {
174 // This should parse as two separate bounds, `FnOnce() -> i32` and `Send` - not
175 // `FnOnce() -> (i32 + Send)`.
176 let input = quote! {
177 fn f<G>()
178 where
179 G: FnOnce() -> i32 + Send,
180 {
181 }
182 };
183
184 snapshot!(input as ItemFn, @r###"
60c5eb7d
XL
185 ItemFn {
186 vis: Inherited,
187 sig: Signature {
188 ident: "f",
189 generics: Generics {
190 lt_token: Some,
191 params: [
192 Type(TypeParam {
193 ident: "G",
194 }),
195 ],
196 gt_token: Some,
197 where_clause: Some(WhereClause {
198 predicates: [
199 Type(PredicateType {
200 bounded_ty: Type::Path {
201 path: Path {
202 segments: [
203 PathSegment {
204 ident: "G",
205 arguments: None,
206 },
207 ],
208 },
209 },
210 bounds: [
211 Trait(TraitBound {
212 modifier: None,
213 path: Path {
214 segments: [
215 PathSegment {
216 ident: "FnOnce",
217 arguments: PathArguments::Parenthesized {
218 output: Type(
219 Type::Path {
220 path: Path {
221 segments: [
222 PathSegment {
223 ident: "i32",
224 arguments: None,
225 },
226 ],
227 },
228 },
229 ),
230 },
231 },
232 ],
233 },
234 }),
235 Trait(TraitBound {
236 modifier: None,
237 path: Path {
238 segments: [
239 PathSegment {
240 ident: "Send",
241 arguments: None,
242 },
243 ],
244 },
245 }),
246 ],
247 }),
248 ],
249 }),
250 },
251 output: Default,
252 },
253 block: Block,
254 }
e74abb32
XL
255 "###);
256
257 let where_clause = input.sig.generics.where_clause.as_ref().unwrap();
258 assert_eq!(where_clause.predicates.len(), 1);
259
260 let predicate = match &where_clause.predicates[0] {
261 WherePredicate::Type(pred) => pred,
262 _ => panic!("wrong predicate kind"),
263 };
264
265 assert_eq!(predicate.bounds.len(), 2, "{:#?}", predicate.bounds);
266
267 let first_bound = &predicate.bounds[0];
1b1a35ee 268 assert_eq!(quote!(#first_bound).to_string(), "FnOnce () -> i32");
e74abb32
XL
269
270 let second_bound = &predicate.bounds[1];
271 assert_eq!(quote!(#second_bound).to_string(), "Send");
272}
273
274#[test]
275fn test_where_clause_at_end_of_input() {
276 let input = quote! {
277 where
278 };
279
280 snapshot!(input as WhereClause, @"WhereClause");
281
282 assert_eq!(input.predicates.len(), 0);
283}