diff options
-rw-r--r-- | src/parser/grammar/items/traits.rs | 42 | ||||
-rw-r--r-- | tests/data/parser/inline/0008_unsafe_impl.txt | 10 | ||||
-rw-r--r-- | tests/data/parser/inline/0010_unsafe_default_impl.txt | 10 | ||||
-rw-r--r-- | tests/data/parser/inline/0046_default_impl.txt | 10 | ||||
-rw-r--r-- | tests/data/parser/inline/0047_impl_item.txt | 10 | ||||
-rw-r--r-- | tests/data/parser/inline/0048_impl_item_neg.rs | 1 | ||||
-rw-r--r-- | tests/data/parser/inline/0048_impl_item_neg.txt | 22 |
7 files changed, 92 insertions, 13 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) { | |||
14 | pub(super) fn impl_item(p: &mut Parser) { | 14 | pub(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 | |||
36 | fn 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 | } | ||
diff --git a/tests/data/parser/inline/0008_unsafe_impl.txt b/tests/data/parser/inline/0008_unsafe_impl.txt index a88a447cb..d21782b45 100644 --- a/tests/data/parser/inline/0008_unsafe_impl.txt +++ b/tests/data/parser/inline/0008_unsafe_impl.txt | |||
@@ -3,9 +3,13 @@ FILE@[0; 19) | |||
3 | UNSAFE_KW@[0; 6) | 3 | UNSAFE_KW@[0; 6) |
4 | WHITESPACE@[6; 7) | 4 | WHITESPACE@[6; 7) |
5 | IMPL_KW@[7; 11) | 5 | IMPL_KW@[7; 11) |
6 | WHITESPACE@[11; 12) | 6 | PATH_TYPE@[11; 16) |
7 | IDENT@[12; 15) "Foo" | 7 | PATH@[11; 16) |
8 | WHITESPACE@[15; 16) | 8 | PATH_SEGMENT@[11; 16) |
9 | NAME_REF@[11; 16) | ||
10 | WHITESPACE@[11; 12) | ||
11 | IDENT@[12; 15) "Foo" | ||
12 | WHITESPACE@[15; 16) | ||
9 | L_CURLY@[16; 17) | 13 | L_CURLY@[16; 17) |
10 | R_CURLY@[17; 18) | 14 | R_CURLY@[17; 18) |
11 | WHITESPACE@[18; 19) | 15 | WHITESPACE@[18; 19) |
diff --git a/tests/data/parser/inline/0010_unsafe_default_impl.txt b/tests/data/parser/inline/0010_unsafe_default_impl.txt index 7450381cb..a89008c8a 100644 --- a/tests/data/parser/inline/0010_unsafe_default_impl.txt +++ b/tests/data/parser/inline/0010_unsafe_default_impl.txt | |||
@@ -5,9 +5,13 @@ FILE@[0; 27) | |||
5 | DEFAULT_KW@[7; 14) | 5 | DEFAULT_KW@[7; 14) |
6 | WHITESPACE@[14; 15) | 6 | WHITESPACE@[14; 15) |
7 | IMPL_KW@[15; 19) | 7 | IMPL_KW@[15; 19) |
8 | WHITESPACE@[19; 20) | 8 | PATH_TYPE@[19; 24) |
9 | IDENT@[20; 23) "Foo" | 9 | PATH@[19; 24) |
10 | WHITESPACE@[23; 24) | 10 | PATH_SEGMENT@[19; 24) |
11 | NAME_REF@[19; 24) | ||
12 | WHITESPACE@[19; 20) | ||
13 | IDENT@[20; 23) "Foo" | ||
14 | WHITESPACE@[23; 24) | ||
11 | L_CURLY@[24; 25) | 15 | L_CURLY@[24; 25) |
12 | R_CURLY@[25; 26) | 16 | R_CURLY@[25; 26) |
13 | WHITESPACE@[26; 27) | 17 | WHITESPACE@[26; 27) |
diff --git a/tests/data/parser/inline/0046_default_impl.txt b/tests/data/parser/inline/0046_default_impl.txt index bc17bcaff..3718aea3b 100644 --- a/tests/data/parser/inline/0046_default_impl.txt +++ b/tests/data/parser/inline/0046_default_impl.txt | |||
@@ -3,9 +3,13 @@ FILE@[0; 20) | |||
3 | DEFAULT_KW@[0; 7) | 3 | DEFAULT_KW@[0; 7) |
4 | WHITESPACE@[7; 8) | 4 | WHITESPACE@[7; 8) |
5 | IMPL_KW@[8; 12) | 5 | IMPL_KW@[8; 12) |
6 | WHITESPACE@[12; 13) | 6 | PATH_TYPE@[12; 17) |
7 | IDENT@[13; 16) "Foo" | 7 | PATH@[12; 17) |
8 | WHITESPACE@[16; 17) | 8 | PATH_SEGMENT@[12; 17) |
9 | NAME_REF@[12; 17) | ||
10 | WHITESPACE@[12; 13) | ||
11 | IDENT@[13; 16) "Foo" | ||
12 | WHITESPACE@[16; 17) | ||
9 | L_CURLY@[17; 18) | 13 | L_CURLY@[17; 18) |
10 | R_CURLY@[18; 19) | 14 | R_CURLY@[18; 19) |
11 | WHITESPACE@[19; 20) | 15 | WHITESPACE@[19; 20) |
diff --git a/tests/data/parser/inline/0047_impl_item.txt b/tests/data/parser/inline/0047_impl_item.txt index a7f3155e1..90f11e8a2 100644 --- a/tests/data/parser/inline/0047_impl_item.txt +++ b/tests/data/parser/inline/0047_impl_item.txt | |||
@@ -1,9 +1,13 @@ | |||
1 | FILE@[0; 12) | 1 | FILE@[0; 12) |
2 | IMPL_ITEM@[0; 12) | 2 | IMPL_ITEM@[0; 12) |
3 | IMPL_KW@[0; 4) | 3 | IMPL_KW@[0; 4) |
4 | WHITESPACE@[4; 5) | 4 | PATH_TYPE@[4; 9) |
5 | IDENT@[5; 8) "Foo" | 5 | PATH@[4; 9) |
6 | WHITESPACE@[8; 9) | 6 | PATH_SEGMENT@[4; 9) |
7 | NAME_REF@[4; 9) | ||
8 | WHITESPACE@[4; 5) | ||
9 | IDENT@[5; 8) "Foo" | ||
10 | WHITESPACE@[8; 9) | ||
7 | L_CURLY@[9; 10) | 11 | L_CURLY@[9; 10) |
8 | R_CURLY@[10; 11) | 12 | R_CURLY@[10; 11) |
9 | WHITESPACE@[11; 12) | 13 | WHITESPACE@[11; 12) |
diff --git a/tests/data/parser/inline/0048_impl_item_neg.rs b/tests/data/parser/inline/0048_impl_item_neg.rs new file mode 100644 index 000000000..b7527c870 --- /dev/null +++ b/tests/data/parser/inline/0048_impl_item_neg.rs | |||
@@ -0,0 +1 @@ | |||
impl !Send for X {} | |||
diff --git a/tests/data/parser/inline/0048_impl_item_neg.txt b/tests/data/parser/inline/0048_impl_item_neg.txt new file mode 100644 index 000000000..1b7581434 --- /dev/null +++ b/tests/data/parser/inline/0048_impl_item_neg.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | FILE@[0; 20) | ||
2 | IMPL_ITEM@[0; 20) | ||
3 | IMPL_KW@[0; 4) | ||
4 | WHITESPACE@[4; 5) | ||
5 | EXCL@[5; 6) | ||
6 | PATH_TYPE@[6; 11) | ||
7 | PATH@[6; 11) | ||
8 | PATH_SEGMENT@[6; 11) | ||
9 | NAME_REF@[6; 11) | ||
10 | IDENT@[6; 10) "Send" | ||
11 | WHITESPACE@[10; 11) | ||
12 | FOR_KW@[11; 14) | ||
13 | PATH_TYPE@[14; 17) | ||
14 | PATH@[14; 17) | ||
15 | PATH_SEGMENT@[14; 17) | ||
16 | NAME_REF@[14; 17) | ||
17 | WHITESPACE@[14; 15) | ||
18 | IDENT@[15; 16) "X" | ||
19 | WHITESPACE@[16; 17) | ||
20 | L_CURLY@[17; 18) | ||
21 | R_CURLY@[18; 19) | ||
22 | WHITESPACE@[19; 20) | ||