aboutsummaryrefslogtreecommitdiff
path: root/src/grammar/items/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar/items/traits.rs')
-rw-r--r--src/grammar/items/traits.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/grammar/items/traits.rs b/src/grammar/items/traits.rs
new file mode 100644
index 000000000..bda13e565
--- /dev/null
+++ b/src/grammar/items/traits.rs
@@ -0,0 +1,77 @@
1use super::*;
2
3// test trait_item
4// trait T<U>: Hash + Clone where U: Copy {}
5pub(super) fn trait_item(p: &mut Parser) {
6 assert!(p.at(TRAIT_KW));
7 p.bump();
8 name(p);
9 type_params::type_param_list(p);
10 if p.at(COLON) {
11 type_params::bounds(p);
12 }
13 type_params::where_clause(p);
14 p.expect(L_CURLY);
15 p.expect(R_CURLY);
16}
17
18// test impl_item
19// impl Foo {}
20pub(super) fn impl_item(p: &mut Parser) {
21 assert!(p.at(IMPL_KW));
22 p.bump();
23 if choose_type_params_over_qpath(p) {
24 type_params::type_param_list(p);
25 }
26
27 // TODO: never type
28 // impl ! {}
29
30 // test impl_item_neg
31 // impl !Send for X {}
32 p.eat(EXCL);
33 types::type_(p);
34 if p.eat(FOR_KW) {
35 types::type_(p);
36 }
37 type_params::where_clause(p);
38 p.expect(L_CURLY);
39
40 // test impl_item_items
41 // impl F {
42 // type A = i32;
43 // const B: i32 = 92;
44 // fn foo() {}
45 // fn bar(&self) {}
46 // }
47 while !p.at(EOF) && !p.at(R_CURLY) {
48 item(p);
49 }
50 p.expect(R_CURLY);
51}
52
53fn choose_type_params_over_qpath(p: &Parser) -> bool {
54 // There's an ambiguity between generic parameters and qualified paths in impls.
55 // If we see `<` it may start both, so we have to inspect some following tokens.
56 // The following combinations can only start generics,
57 // but not qualified paths (with one exception):
58 // `<` `>` - empty generic parameters
59 // `<` `#` - generic parameters with attributes
60 // `<` (LIFETIME|IDENT) `>` - single generic parameter
61 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
62 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
63 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
64 // The only truly ambiguous case is
65 // `<` IDENT `>` `::` IDENT ...
66 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
67 // because this is what almost always expected in practice, qualified paths in impls
68 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
69 if !p.at(L_ANGLE) {
70 return false;
71 }
72 if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
73 return true;
74 }
75 (p.nth(1) == LIFETIME || p.nth(1) == IDENT)
76 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
77}