aboutsummaryrefslogtreecommitdiff
path: root/src/parser/grammar/items/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/grammar/items/traits.rs')
-rw-r--r--src/parser/grammar/items/traits.rs42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/parser/grammar/items/traits.rs b/src/parser/grammar/items/traits.rs
index 7fd011ffd..c7450b761 100644
--- a/src/parser/grammar/items/traits.rs
+++ b/src/parser/grammar/items/traits.rs
@@ -14,7 +14,47 @@ pub(super) fn trait_item(p: &mut Parser) {
14pub(super) fn impl_item(p: &mut Parser) { 14pub(super) fn impl_item(p: &mut Parser) {
15 assert!(p.at(IMPL_KW)); 15 assert!(p.at(IMPL_KW));
16 p.bump(); 16 p.bump();
17 p.expect(IDENT); 17 if choose_type_params_over_qpath(p) {
18 type_params::list(p);
19 }
20
21 // TODO: never type
22 // impl ! {}
23
24 // test impl_item_neg
25 // impl !Send for X {}
26 p.eat(EXCL);
27 types::type_(p);
28 if p.eat(FOR_KW) {
29 types::type_(p);
30 }
31 type_params::where_clause(p);
18 p.expect(L_CURLY); 32 p.expect(L_CURLY);
19 p.expect(R_CURLY); 33 p.expect(R_CURLY);
20} 34}
35
36fn choose_type_params_over_qpath(p: &Parser) -> bool {
37 // There's an ambiguity between generic parameters and qualified paths in impls.
38 // If we see `<` it may start both, so we have to inspect some following tokens.
39 // The following combinations can only start generics,
40 // but not qualified paths (with one exception):
41 // `<` `>` - empty generic parameters
42 // `<` `#` - generic parameters with attributes
43 // `<` (LIFETIME|IDENT) `>` - single generic parameter
44 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
45 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
46 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
47 // The only truly ambiguous case is
48 // `<` IDENT `>` `::` IDENT ...
49 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
50 // because this is what almost always expected in practice, qualified paths in impls
51 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
52 if !p.at(L_ANGLE) {
53 return false;
54 }
55 if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
56 return true;
57 }
58 (p.nth(1) == LIFETIME || p.nth(1) == IDENT)
59 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
60}