aboutsummaryrefslogtreecommitdiff
path: root/crates/parser/src/grammar/items/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser/src/grammar/items/traits.rs')
-rw-r--r--crates/parser/src/grammar/items/traits.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs
new file mode 100644
index 000000000..8394020da
--- /dev/null
+++ b/crates/parser/src/grammar/items/traits.rs
@@ -0,0 +1,131 @@
1//! FIXME: write short doc here
2
3use 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 {}
8pub(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 {}
36pub(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// }
68pub(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> {}
93fn 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) `>` - single generic parameter
102 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
103 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
104 // `<` (LIFETIME|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 || 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 {}
125pub(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}