aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser/grammar/items/traits.rs42
-rw-r--r--tests/data/parser/inline/0008_unsafe_impl.txt10
-rw-r--r--tests/data/parser/inline/0010_unsafe_default_impl.txt10
-rw-r--r--tests/data/parser/inline/0046_default_impl.txt10
-rw-r--r--tests/data/parser/inline/0047_impl_item.txt10
-rw-r--r--tests/data/parser/inline/0048_impl_item_neg.rs1
-rw-r--r--tests/data/parser/inline/0048_impl_item_neg.txt22
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) {
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}
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 @@
1FILE@[0; 12) 1FILE@[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 @@
1FILE@[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)