Skip to main content

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