]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/types.rs
Apply a few clippy suggestions
[rust.git] / crates / parser / src / grammar / types.rs
1 use super::*;
2
3 pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
4     T!['('],
5     T!['['],
6     T![<],
7     T![!],
8     T![*],
9     T![&],
10     T![_],
11     T![fn],
12     T![unsafe],
13     T![extern],
14     T![for],
15     T![impl],
16     T![dyn],
17 ]));
18
19 const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
20     T![')'],
21     T![,],
22     L_DOLLAR,
23     // test_err struct_field_recover
24     // struct S { f pub g: () }
25     T![pub],
26 ]);
27
28 pub(crate) fn type_(p: &mut Parser) {
29     type_with_bounds_cond(p, true);
30 }
31
32 pub(super) fn type_no_bounds(p: &mut Parser) {
33     type_with_bounds_cond(p, false);
34 }
35
36 fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
37     match p.current() {
38         T!['('] => paren_or_tuple_type(p),
39         T![!] => never_type(p),
40         T![*] => ptr_type(p),
41         T!['['] => array_or_slice_type(p),
42         T![&] => ref_type(p),
43         T![_] => infer_type(p),
44         T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
45         T![for] => for_type(p, allow_bounds),
46         T![impl] => impl_trait_type(p),
47         T![dyn] => dyn_trait_type(p),
48         // Some path types are not allowed to have bounds (no plus)
49         T![<] => path_type_(p, allow_bounds),
50         _ if paths::is_use_path_start(p) => path_or_macro_type_(p, allow_bounds),
51         _ => {
52             p.err_recover("expected type", TYPE_RECOVERY_SET);
53         }
54     }
55 }
56
57 pub(super) fn ascription(p: &mut Parser) {
58     p.expect(T![:]);
59     type_(p)
60 }
61
62 fn paren_or_tuple_type(p: &mut Parser) {
63     assert!(p.at(T!['(']));
64     let m = p.start();
65     p.bump(T!['(']);
66     let mut n_types: u32 = 0;
67     let mut trailing_comma: bool = false;
68     while !p.at(EOF) && !p.at(T![')']) {
69         n_types += 1;
70         type_(p);
71         if p.eat(T![,]) {
72             trailing_comma = true;
73         } else {
74             trailing_comma = false;
75             break;
76         }
77     }
78     p.expect(T![')']);
79
80     let kind = if n_types == 1 && !trailing_comma {
81         // test paren_type
82         // type T = (i32);
83         PAREN_TYPE
84     } else {
85         // test unit_type
86         // type T = ();
87
88         // test singleton_tuple_type
89         // type T = (i32,);
90         TUPLE_TYPE
91     };
92     m.complete(p, kind);
93 }
94
95 // test never_type
96 // type Never = !;
97 fn never_type(p: &mut Parser) {
98     assert!(p.at(T![!]));
99     let m = p.start();
100     p.bump(T![!]);
101     m.complete(p, NEVER_TYPE);
102 }
103
104 fn ptr_type(p: &mut Parser) {
105     assert!(p.at(T![*]));
106     let m = p.start();
107     p.bump(T![*]);
108
109     match p.current() {
110         // test pointer_type_mut
111         // type M = *mut ();
112         // type C = *mut ();
113         T![mut] | T![const] => p.bump_any(),
114         _ => {
115             // test_err pointer_type_no_mutability
116             // type T = *();
117             p.error(
118                 "expected mut or const in raw pointer type \
119                  (use `*mut T` or `*const T` as appropriate)",
120             );
121         }
122     };
123
124     type_no_bounds(p);
125     m.complete(p, PTR_TYPE);
126 }
127
128 fn array_or_slice_type(p: &mut Parser) {
129     assert!(p.at(T!['[']));
130     let m = p.start();
131     p.bump(T!['[']);
132
133     type_(p);
134     let kind = match p.current() {
135         // test slice_type
136         // type T = [()];
137         T![']'] => {
138             p.bump(T![']']);
139             SLICE_TYPE
140         }
141
142         // test array_type
143         // type T = [(); 92];
144         T![;] => {
145             p.bump(T![;]);
146             expressions::expr(p);
147             p.expect(T![']']);
148             ARRAY_TYPE
149         }
150         // test_err array_type_missing_semi
151         // type T = [() 92];
152         _ => {
153             p.error("expected `;` or `]`");
154             SLICE_TYPE
155         }
156     };
157     m.complete(p, kind);
158 }
159
160 // test reference_type;
161 // type A = &();
162 // type B = &'static ();
163 // type C = &mut ();
164 fn ref_type(p: &mut Parser) {
165     assert!(p.at(T![&]));
166     let m = p.start();
167     p.bump(T![&]);
168     if p.at(LIFETIME_IDENT) {
169         lifetime(p);
170     }
171     p.eat(T![mut]);
172     type_no_bounds(p);
173     m.complete(p, REF_TYPE);
174 }
175
176 // test placeholder_type
177 // type Placeholder = _;
178 fn infer_type(p: &mut Parser) {
179     assert!(p.at(T![_]));
180     let m = p.start();
181     p.bump(T![_]);
182     m.complete(p, INFER_TYPE);
183 }
184
185 // test fn_pointer_type
186 // type A = fn();
187 // type B = unsafe fn();
188 // type C = unsafe extern "C" fn();
189 // type D = extern "C" fn ( u8 , ... ) -> u8;
190 fn fn_ptr_type(p: &mut Parser) {
191     let m = p.start();
192     p.eat(T![unsafe]);
193     if p.at(T![extern]) {
194         abi(p);
195     }
196     // test_err fn_pointer_type_missing_fn
197     // type F = unsafe ();
198     if !p.eat(T![fn]) {
199         m.abandon(p);
200         p.error("expected `fn`");
201         return;
202     }
203     if p.at(T!['(']) {
204         params::param_list_fn_ptr(p);
205     } else {
206         p.error("expected parameters")
207     }
208     // test fn_pointer_type_with_ret
209     // type F = fn() -> ();
210     opt_ret_type(p);
211     m.complete(p, FN_PTR_TYPE);
212 }
213
214 pub(super) fn for_binder(p: &mut Parser) {
215     assert!(p.at(T![for]));
216     p.bump(T![for]);
217     if p.at(T![<]) {
218         type_params::opt_generic_param_list(p);
219     } else {
220         p.error("expected `<`");
221     }
222 }
223
224 // test for_type
225 // type A = for<'a> fn() -> ();
226 // type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
227 // type Obj = for<'a> PartialEq<&'a i32>;
228 pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
229     assert!(p.at(T![for]));
230     let m = p.start();
231     for_binder(p);
232     match p.current() {
233         T![fn] | T![unsafe] | T![extern] => {}
234         // OK: legacy trait object format
235         _ if paths::is_use_path_start(p) => {}
236         _ => {
237             p.error("expected a function pointer or path");
238         }
239     }
240     type_no_bounds(p);
241     let completed = m.complete(p, FOR_TYPE);
242
243     // test no_dyn_trait_leading_for
244     // type A = for<'a> Test<'a> + Send;
245     if allow_bounds {
246         opt_type_bounds_as_dyn_trait_type(p, completed);
247     }
248 }
249
250 // test impl_trait_type
251 // type A = impl Iterator<Item=Foo<'a>> + 'a;
252 fn impl_trait_type(p: &mut Parser) {
253     assert!(p.at(T![impl]));
254     let m = p.start();
255     p.bump(T![impl]);
256     type_params::bounds_without_colon(p);
257     m.complete(p, IMPL_TRAIT_TYPE);
258 }
259
260 // test dyn_trait_type
261 // type A = dyn Iterator<Item=Foo<'a>> + 'a;
262 fn dyn_trait_type(p: &mut Parser) {
263     assert!(p.at(T![dyn]));
264     let m = p.start();
265     p.bump(T![dyn]);
266     type_params::bounds_without_colon(p);
267     m.complete(p, DYN_TRAIT_TYPE);
268 }
269
270 // test path_type
271 // type A = Foo;
272 // type B = ::Foo;
273 // type C = self::Foo;
274 // type D = super::Foo;
275 pub(super) fn path_type(p: &mut Parser) {
276     path_type_(p, true)
277 }
278
279 // test macro_call_type
280 // type A = foo!();
281 // type B = crate::foo!();
282 fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
283     assert!(paths::is_path_start(p));
284     let r = p.start();
285     let m = p.start();
286
287     paths::type_path(p);
288
289     let kind = if p.at(T![!]) && !p.at(T![!=]) {
290         items::macro_call_after_excl(p);
291         m.complete(p, MACRO_CALL);
292         MACRO_TYPE
293     } else {
294         m.abandon(p);
295         PATH_TYPE
296     };
297
298     let path = r.complete(p, kind);
299
300     if allow_bounds {
301         opt_type_bounds_as_dyn_trait_type(p, path);
302     }
303 }
304
305 pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
306     assert!(paths::is_path_start(p));
307     let m = p.start();
308     paths::type_path(p);
309
310     // test path_type_with_bounds
311     // fn foo() -> Box<T + 'f> {}
312     // fn foo() -> Box<dyn T + 'f> {}
313     let path = m.complete(p, PATH_TYPE);
314     if allow_bounds {
315         opt_type_bounds_as_dyn_trait_type(p, path);
316     }
317 }
318
319 /// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
320 /// with a TYPE_BOUND_LIST
321 fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
322     assert!(matches!(
323         type_marker.kind(),
324         SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
325     ));
326     if !p.at(T![+]) {
327         return;
328     }
329
330     // First create a TYPE_BOUND from the completed PATH_TYPE
331     let m = type_marker.precede(p).complete(p, TYPE_BOUND);
332
333     // Next setup a marker for the TYPE_BOUND_LIST
334     let m = m.precede(p);
335
336     // This gets consumed here so it gets properly set
337     // in the TYPE_BOUND_LIST
338     p.eat(T![+]);
339
340     // Parse rest of the bounds into the TYPE_BOUND_LIST
341     let m = type_params::bounds_without_colon_m(p, m);
342
343     // Finally precede everything with DYN_TRAIT_TYPE
344     m.precede(p).complete(p, DYN_TRAIT_TYPE);
345 }