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}