]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / parser / src / grammar / items / traits.rs
1 use super::*;
2
3 // test trait_item
4 // trait T { fn new() -> Self; }
5 pub(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_ALIAS);
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 {}
47 pub(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 // FIXME: never type
58 // impl ! {}
59
60 // test impl_item_neg
61 // impl !Send for S {}
62 p.eat(T![!]);
63 impl_type(p);
64 if p.eat(T![for]) {
65 impl_type(p);
66 }
67 generic_params::opt_where_clause(p);
68 if p.at(T!['{']) {
69 assoc_item_list(p);
70 } else {
71 p.error("expected `{`");
72 }
73 m.complete(p, IMPL);
74 }
75
76 // test assoc_item_list
77 // impl F {
78 // type A = i32;
79 // const B: i32 = 92;
80 // fn foo() {}
81 // fn bar(&self) {}
82 // }
83 pub(crate) fn assoc_item_list(p: &mut Parser<'_>) {
84 assert!(p.at(T!['{']));
85
86 let m = p.start();
87 p.bump(T!['{']);
88 // test assoc_item_list_inner_attrs
89 // impl S { #![attr] }
90 attributes::inner_attrs(p);
91
92 while !p.at(EOF) && !p.at(T!['}']) {
93 if p.at(T!['{']) {
94 error_block(p, "expected an item");
95 continue;
96 }
97 item_or_macro(p, true);
98 }
99 p.expect(T!['}']);
100 m.complete(p, ASSOC_ITEM_LIST);
101 }
102
103 // test impl_type_params
104 // impl<const N: u32> Bar<N> {}
105 fn not_a_qualified_path(p: &Parser<'_>) -> bool {
106 // There's an ambiguity between generic parameters and qualified paths in impls.
107 // If we see `<` it may start both, so we have to inspect some following tokens.
108 // The following combinations can only start generics,
109 // but not qualified paths (with one exception):
110 // `<` `>` - empty generic parameters
111 // `<` `#` - generic parameters with attributes
112 // `<` `const` - const generic parameters
113 // `<` (LIFETIME_IDENT|IDENT) `>` - single generic parameter
114 // `<` (LIFETIME_IDENT|IDENT) `,` - first generic parameter in a list
115 // `<` (LIFETIME_IDENT|IDENT) `:` - generic parameter with bounds
116 // `<` (LIFETIME_IDENT|IDENT) `=` - generic parameter with a default
117 // The only truly ambiguous case is
118 // `<` IDENT `>` `::` IDENT ...
119 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
120 // because this is what almost always expected in practice, qualified paths in impls
121 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
122 if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == T![const] {
123 return true;
124 }
125 (p.nth(1) == LIFETIME_IDENT || p.nth(1) == IDENT)
126 && (p.nth(2) == T![>] || p.nth(2) == T![,] || p.nth(2) == T![:] || p.nth(2) == T![=])
127 }
128
129 // test_err impl_type
130 // impl Type {}
131 // impl Trait1 for T {}
132 // impl impl NotType {}
133 // impl Trait2 for impl NotType {}
134 pub(crate) fn impl_type(p: &mut Parser<'_>) {
135 if p.at(T![impl]) {
136 p.error("expected trait or type");
137 return;
138 }
139 types::type_(p);
140 }