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