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