diff options
Diffstat (limited to 'src/grammar/items/traits.rs')
-rw-r--r-- | src/grammar/items/traits.rs | 77 |
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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | // test trait_item | ||
4 | // trait T<U>: Hash + Clone where U: Copy {} | ||
5 | pub(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 {} | ||
20 | pub(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 | |||
53 | fn 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 | } | ||