parser/grammar/items/
traits.rs

1use super::*;
2
3// test trait_item
4// trait T { fn new() -> Self; }
5pub(super) fn trait_(p: &mut Parser<'_>, m: Marker) {
6    p.bump(T![trait]);
7    name_r(p, ITEM_RECOVERY_SET);
8
9    // test trait_item_generic_params
10    // trait X<U: Debug + Display> {}
11    generic_params::opt_generic_param_list(p);
12
13    if p.eat(T![=]) {
14        // test trait_alias
15        // trait Z<U> = T<U>;
16        generic_params::bounds_without_colon(p);
17
18        // test trait_alias_where_clause
19        // trait Z<U> = T<U> where U: Copy;
20        // trait Z<U> = where Self: T<U>;
21        generic_params::opt_where_clause(p);
22        p.expect(T![;]);
23        m.complete(p, TRAIT);
24        return;
25    }
26
27    if p.at(T![:]) {
28        // test trait_item_bounds
29        // trait T: Hash + Clone {}
30        generic_params::bounds(p);
31    }
32
33    // test trait_item_where_clause
34    // trait T where Self: Copy {}
35    generic_params::opt_where_clause(p);
36
37    if p.at(T!['{']) {
38        assoc_item_list(p);
39    } else {
40        p.error("expected `{`");
41    }
42    m.complete(p, TRAIT);
43}
44
45// test impl_item
46// impl S {}
47pub(super) fn impl_(p: &mut Parser<'_>, m: Marker) {
48    p.bump(T![impl]);
49    if p.at(T![<]) && not_a_qualified_path(p) {
50        generic_params::opt_generic_param_list(p);
51    }
52
53    // test impl_item_const
54    // impl const Send for S {}
55    p.eat(T![const]);
56
57    // test impl_item_never_type
58    // impl ! {}
59    if p.at(T![!]) && !p.nth_at(1, T!['{']) {
60        // test impl_item_neg
61        // impl !Send for S {}
62        p.eat(T![!]);
63    }
64    impl_type(p);
65    if p.eat(T![for]) {
66        impl_type(p);
67    }
68    generic_params::opt_where_clause(p);
69    if p.at(T!['{']) {
70        assoc_item_list(p);
71    } else {
72        p.error("expected `{`");
73    }
74    m.complete(p, IMPL);
75}
76
77// test assoc_item_list
78// impl F {
79//     type A = i32;
80//     const B: i32 = 92;
81//     fn foo() {}
82//     fn bar(&self) {}
83// }
84pub(crate) fn assoc_item_list(p: &mut Parser<'_>) {
85    assert!(p.at(T!['{']));
86
87    let m = p.start();
88    p.bump(T!['{']);
89    // test assoc_item_list_inner_attrs
90    // impl S { #![attr] }
91    attributes::inner_attrs(p);
92
93    while !p.at(EOF) && !p.at(T!['}']) {
94        if p.at(T!['{']) {
95            error_block(p, "expected an item");
96            continue;
97        }
98        item_or_macro(p, true, false);
99    }
100    p.expect(T!['}']);
101    m.complete(p, ASSOC_ITEM_LIST);
102}
103
104// test impl_type_params
105// impl<const N: u32> Bar<N> {}
106fn not_a_qualified_path(p: &Parser<'_>) -> bool {
107    // There's an ambiguity between generic parameters and qualified paths in impls.
108    // If we see `<` it may start both, so we have to inspect some following tokens.
109    // The following combinations can only start generics,
110    // but not qualified paths (with one exception):
111    //     `<` `>` - empty generic parameters
112    //     `<` `#` - generic parameters with attributes
113    //     `<` `const` - const generic parameters
114    //     `<` (LIFETIME_IDENT|IDENT) `>` - single generic parameter
115    //     `<` (LIFETIME_IDENT|IDENT) `,` - first generic parameter in a list
116    //     `<` (LIFETIME_IDENT|IDENT) `:` - generic parameter with bounds
117    //     `<` (LIFETIME_IDENT|IDENT) `=` - generic parameter with a default
118    // The only truly ambiguous case is
119    //     `<` IDENT `>` `::` IDENT ...
120    // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
121    // because this is what almost always expected in practice, qualified paths in impls
122    // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
123    if [T![#], T![>], T![const]].contains(&p.nth(1)) {
124        return true;
125    }
126    ([LIFETIME_IDENT, IDENT].contains(&p.nth(1)))
127        && ([T![>], T![,], T![:], T![=]].contains(&p.nth(2)))
128}
129
130// test_err impl_type
131// impl Type {}
132// impl Trait1 for T {}
133// impl impl NotType {}
134// impl Trait2 for impl NotType {}
135pub(crate) fn impl_type(p: &mut Parser<'_>) {
136    if p.at(T![impl]) {
137        p.error("expected trait or type");
138        return;
139    }
140    types::type_(p);
141}