parser/grammar/
types.rs

1use super::*;
2
3pub(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    T![Self],
18    LIFETIME_IDENT,
19]));
20
21pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
22    T![')'],
23    T![>],
24    T![,],
25    // test_err struct_field_recover
26    // struct S { f pub g: () }
27    T![pub],
28]);
29
30pub(crate) fn type_(p: &mut Parser<'_>) {
31    type_with_bounds_cond(p, true);
32}
33
34pub(super) fn type_no_bounds(p: &mut Parser<'_>) {
35    type_with_bounds_cond(p, false);
36}
37
38fn 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_bounds(p, allow_bounds),
52        T![ident] if !p.edition().at_least_2018() && is_dyn_weak(p) => dyn_trait_type_weak(p),
53        _ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
54        LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
55        _ => {
56            p.err_recover("expected type", TYPE_RECOVERY_SET);
57        }
58    }
59}
60
61pub(crate) fn is_dyn_weak(p: &Parser<'_>) -> bool {
62    const WEAK_DYN_PATH_FIRST: TokenSet = TokenSet::new(&[
63        IDENT,
64        T![self],
65        T![super],
66        T![crate],
67        T![Self],
68        T![lifetime_ident],
69        T![?],
70        T![for],
71        T!['('],
72    ]);
73
74    p.at_contextual_kw(T![dyn]) && {
75        let la = p.nth(1);
76        WEAK_DYN_PATH_FIRST.contains(la) && (la != T![:] || la != T![<])
77    }
78}
79
80pub(super) fn ascription(p: &mut Parser<'_>) {
81    assert!(p.at(T![:]));
82    p.bump(T![:]);
83    if p.at(T![=]) {
84        // recover from `let x: = expr;`, `const X: = expr;` and similar
85        // hopefully no type starts with `=`
86        p.error("missing type");
87        return;
88    }
89    type_(p);
90}
91
92fn paren_or_tuple_type(p: &mut Parser<'_>) {
93    assert!(p.at(T!['(']));
94    let m = p.start();
95    p.bump(T!['(']);
96    let mut n_types: u32 = 0;
97    let mut trailing_comma: bool = false;
98    while !p.at(EOF) && !p.at(T![')']) {
99        n_types += 1;
100        type_(p);
101        if p.eat(T![,]) {
102            trailing_comma = true;
103        } else {
104            trailing_comma = false;
105            break;
106        }
107    }
108    p.expect(T![')']);
109
110    let kind = if n_types == 1 && !trailing_comma {
111        // test paren_type
112        // type T = (i32);
113        PAREN_TYPE
114    } else {
115        // test unit_type
116        // type T = ();
117
118        // test singleton_tuple_type
119        // type T = (i32,);
120        TUPLE_TYPE
121    };
122    m.complete(p, kind);
123}
124
125// test never_type
126// type Never = !;
127fn never_type(p: &mut Parser<'_>) {
128    assert!(p.at(T![!]));
129    let m = p.start();
130    p.bump(T![!]);
131    m.complete(p, NEVER_TYPE);
132}
133
134fn ptr_type(p: &mut Parser<'_>) {
135    assert!(p.at(T![*]));
136    let m = p.start();
137    p.bump(T![*]);
138
139    match p.current() {
140        // test pointer_type_mut
141        // type M = *mut ();
142        // type C = *mut ();
143        T![mut] | T![const] => p.bump_any(),
144        _ => {
145            // test_err pointer_type_no_mutability
146            // type T = *();
147            p.error(
148                "expected mut or const in raw pointer type \
149                 (use `*mut T` or `*const T` as appropriate)",
150            );
151        }
152    };
153
154    type_no_bounds(p);
155    m.complete(p, PTR_TYPE);
156}
157
158fn array_or_slice_type(p: &mut Parser<'_>) {
159    assert!(p.at(T!['[']));
160    let m = p.start();
161    p.bump(T!['[']);
162
163    type_(p);
164    let kind = match p.current() {
165        // test slice_type
166        // type T = [()];
167        T![']'] => {
168            p.bump(T![']']);
169            SLICE_TYPE
170        }
171
172        // test array_type
173        // type T = [(); 92];
174        T![;] => {
175            p.bump(T![;]);
176            let m = p.start();
177            expressions::expr(p);
178            m.complete(p, CONST_ARG);
179            p.expect(T![']']);
180            ARRAY_TYPE
181        }
182        // test_err array_type_missing_semi
183        // type T = [() 92];
184        _ => {
185            p.error("expected `;` or `]`");
186            SLICE_TYPE
187        }
188    };
189    m.complete(p, kind);
190}
191
192// test reference_type
193// type A = &();
194// type B = &'static ();
195// type C = &mut ();
196fn ref_type(p: &mut Parser<'_>) {
197    assert!(p.at(T![&]));
198    let m = p.start();
199    p.bump(T![&]);
200    if p.at(LIFETIME_IDENT) {
201        lifetime(p);
202    }
203    p.eat(T![mut]);
204    type_no_bounds(p);
205    m.complete(p, REF_TYPE);
206}
207
208// test placeholder_type
209// type Placeholder = _;
210fn infer_type(p: &mut Parser<'_>) {
211    assert!(p.at(T![_]));
212    let m = p.start();
213    p.bump(T![_]);
214    m.complete(p, INFER_TYPE);
215}
216
217// test fn_pointer_type
218// type A = fn();
219// type B = unsafe fn();
220// type C = unsafe extern "C" fn();
221// type D = extern "C" fn ( u8 , ... ) -> u8;
222fn fn_ptr_type(p: &mut Parser<'_>) {
223    let m = p.start();
224    p.eat(T![unsafe]);
225    if p.at(T![extern]) {
226        abi(p);
227    }
228    // test_err fn_pointer_type_missing_fn
229    // type F = unsafe ();
230    if !p.eat(T![fn]) {
231        m.abandon(p);
232        p.error("expected `fn`");
233        return;
234    }
235    if p.at(T!['(']) {
236        params::param_list_fn_ptr(p);
237    } else {
238        p.error("expected parameters");
239    }
240    // test fn_pointer_type_with_ret
241    // type F = fn() -> ();
242    opt_ret_type(p);
243    m.complete(p, FN_PTR_TYPE);
244}
245
246pub(super) fn for_binder(p: &mut Parser<'_>) {
247    assert!(p.at(T![for]));
248    p.bump(T![for]);
249    if p.at(T![<]) {
250        generic_params::opt_generic_param_list(p);
251    } else {
252        p.error("expected `<`");
253    }
254}
255
256// test for_type
257// type A = for<'a> fn() -> ();
258// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
259// type Obj = for<'a> PartialEq<&'a i32>;
260pub(super) fn for_type(p: &mut Parser<'_>, allow_bounds: bool) {
261    assert!(p.at(T![for]));
262    let m = p.start();
263    for_binder(p);
264    match p.current() {
265        T![fn] | T![unsafe] | T![extern] => {}
266        // OK: legacy trait object format
267        _ if paths::is_use_path_start(p) => {}
268        _ => {
269            p.error("expected a function pointer or path");
270        }
271    }
272    type_no_bounds(p);
273    let completed = m.complete(p, FOR_TYPE);
274
275    // test no_dyn_trait_leading_for
276    // type A = for<'a> Test<'a> + Send;
277    if allow_bounds {
278        opt_type_bounds_as_dyn_trait_type(p, completed);
279    }
280}
281
282// test impl_trait_type
283// type A = impl Iterator<Item=Foo<'a>> + 'a;
284fn impl_trait_type(p: &mut Parser<'_>) {
285    assert!(p.at(T![impl]));
286    let m = p.start();
287    p.bump(T![impl]);
288    generic_params::bounds_without_colon(p);
289    m.complete(p, IMPL_TRAIT_TYPE);
290}
291
292// test dyn_trait_type
293// type A = dyn Iterator<Item=Foo<'a>> + 'a;
294fn dyn_trait_type(p: &mut Parser<'_>) {
295    assert!(p.at(T![dyn]));
296    let m = p.start();
297    p.bump(T![dyn]);
298    generic_params::bounds_without_colon(p);
299    m.complete(p, DYN_TRAIT_TYPE);
300}
301
302// test dyn_trait_type_weak 2015
303// type DynPlain = dyn Path;
304// type DynRef = &dyn Path;
305// type DynLt = dyn 'a + Path;
306// type DynQuestion = dyn ?Path;
307// type DynFor = dyn for<'a> Path;
308// type DynParen = dyn(Path);
309// type Path = dyn::Path;
310// type Generic = dyn<Path>;
311fn dyn_trait_type_weak(p: &mut Parser<'_>) {
312    assert!(p.at_contextual_kw(T![dyn]));
313    let m = p.start();
314    p.bump_remap(T![dyn]);
315    generic_params::bounds_without_colon(p);
316    m.complete(p, DYN_TRAIT_TYPE);
317}
318
319// test bare_dyn_types_with_leading_lifetime
320// type A = 'static + Trait;
321// type B = S<'static + Trait>;
322fn bare_dyn_trait_type(p: &mut Parser<'_>) {
323    let m = p.start();
324    generic_params::bounds_without_colon(p);
325    m.complete(p, DYN_TRAIT_TYPE);
326}
327
328// test path_type
329// type A = Foo;
330// type B = ::Foo;
331// type C = self::Foo;
332// type D = super::Foo;
333pub(super) fn path_type(p: &mut Parser<'_>) {
334    path_type_bounds(p, true);
335}
336
337// test macro_call_type
338// type A = foo!();
339// type B = crate::foo!();
340fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
341    assert!(paths::is_path_start(p));
342    let r = p.start();
343    let m = p.start();
344
345    paths::type_path(p);
346
347    let kind = if p.at(T![!]) && !p.at(T![!=]) {
348        items::macro_call_after_excl(p);
349        m.complete(p, MACRO_CALL);
350        MACRO_TYPE
351    } else {
352        m.abandon(p);
353        PATH_TYPE
354    };
355
356    let path = r.complete(p, kind);
357
358    if allow_bounds {
359        opt_type_bounds_as_dyn_trait_type(p, path);
360    }
361}
362
363pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
364    assert!(paths::is_path_start(p));
365    let m = p.start();
366    paths::type_path(p);
367
368    // test path_type_with_bounds
369    // fn foo() -> Box<T + 'f> {}
370    // fn foo() -> Box<dyn T + 'f> {}
371    let path = m.complete(p, PATH_TYPE);
372    if allow_bounds {
373        opt_type_bounds_as_dyn_trait_type(p, path);
374    }
375}
376
377/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
378/// with a TYPE_BOUND_LIST
379pub(super) fn opt_type_bounds_as_dyn_trait_type(
380    p: &mut Parser<'_>,
381    type_marker: CompletedMarker,
382) -> CompletedMarker {
383    assert!(matches!(
384        type_marker.kind(),
385        SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
386    ));
387    if !p.at(T![+]) {
388        return type_marker;
389    }
390
391    // First create a TYPE_BOUND from the completed PATH_TYPE
392    let m = type_marker.precede(p).complete(p, TYPE_BOUND);
393
394    // Next setup a marker for the TYPE_BOUND_LIST
395    let m = m.precede(p);
396
397    // This gets consumed here so it gets properly set
398    // in the TYPE_BOUND_LIST
399    p.eat(T![+]);
400
401    // Parse rest of the bounds into the TYPE_BOUND_LIST
402    let m = generic_params::bounds_without_colon_m(p, m);
403
404    // Finally precede everything with DYN_TRAIT_TYPE
405    m.precede(p).complete(p, DYN_TRAIT_TYPE)
406}