Skip to content

Commit d8e9db0

Browse files
committed
feat(rustc_parse): recover from pre-RFC-2000 const generics syntax
Fixes #89013
1 parent 2b5ddf3 commit d8e9db0

File tree

9 files changed

+197
-1
lines changed

9 files changed

+197
-1
lines changed

compiler/rustc_parse/src/parser/path.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -495,11 +495,16 @@ impl<'a> Parser<'a> {
495495
None => {
496496
let after_eq = eq.shrink_to_hi();
497497
let before_next = self.token.span.shrink_to_lo();
498+
let the_type_placeholder = if matches!(self.token.kind, token::Comma | token::Gt) {
499+
" TheType"
500+
} else {
501+
" TheType "
502+
};
498503
self.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`")
499504
.span_suggestion(
500505
self.sess.source_map().next_point(eq).to(before_next),
501506
"to constrain the associated type, add a type after `=`",
502-
" TheType".to_string(),
507+
the_type_placeholder.to_string(),
503508
Applicability::HasPlaceholders,
504509
)
505510
.span_suggestion(
@@ -572,6 +577,19 @@ impl<'a> Parser<'a> {
572577
return self.recover_const_arg(start, err).map(Some);
573578
}
574579
}
580+
} else if self.eat_keyword_noexpect(kw::Const) {
581+
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
582+
let mut err = self.struct_span_err(
583+
start,
584+
"expected lifetime, type, or constant, found keyword `const`",
585+
);
586+
if self.check_const_arg() {
587+
err.emit();
588+
GenericArg::Const(self.parse_const_arg()?)
589+
} else {
590+
let after_kw_const = self.token.span;
591+
return self.recover_const_arg(after_kw_const, err).map(Some);
592+
}
575593
} else {
576594
return Ok(None);
577595
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait Foo<const N: usize> {
2+
fn do_x(&self) -> [u8; N];
3+
}
4+
5+
struct Bar;
6+
7+
const T: usize = 42;
8+
9+
impl Foo<const 3> for Bar {
10+
//~^ERROR expected lifetime, type, or constant, found keyword `const`
11+
fn do_x(&self) -> [u8; 3] {
12+
[0u8; 3]
13+
}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected lifetime, type, or constant, found keyword `const`
2+
--> $DIR/issue-89013-no-assoc.rs:9:10
3+
|
4+
LL | impl Foo<const 3> for Bar {
5+
| ^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
trait Foo<const N: usize> {
2+
fn do_x(&self) -> [u8; N];
3+
}
4+
5+
struct Bar;
6+
7+
const T: usize = 42;
8+
9+
impl Foo<N = 3> for Bar {
10+
//~^ERROR cannot constrain an associated constant to a value
11+
//~^^ERROR this trait takes 1 generic argument but 0 generic arguments
12+
//~^^^ERROR associated type bindings are not allowed here
13+
fn do_x(&self) -> [u8; 3] {
14+
[0u8; 3]
15+
}
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: cannot constrain an associated constant to a value
2+
--> $DIR/issue-89013-no-kw.rs:9:10
3+
|
4+
LL | impl Foo<N = 3> for Bar {
5+
| -^^^-
6+
| | |
7+
| | ...cannot be constrained to this value
8+
| this associated constant...
9+
10+
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
11+
--> $DIR/issue-89013-no-kw.rs:9:6
12+
|
13+
LL | impl Foo<N = 3> for Bar {
14+
| ^^^ expected 1 generic argument
15+
|
16+
note: trait defined here, with 1 generic parameter: `N`
17+
--> $DIR/issue-89013-no-kw.rs:1:7
18+
|
19+
LL | trait Foo<const N: usize> {
20+
| ^^^ -
21+
help: add missing generic argument
22+
|
23+
LL | impl Foo<N, N = 3> for Bar {
24+
| ++
25+
26+
error[E0229]: associated type bindings are not allowed here
27+
--> $DIR/issue-89013-no-kw.rs:9:10
28+
|
29+
LL | impl Foo<N = 3> for Bar {
30+
| ^^^^^ associated type not allowed here
31+
32+
error: aborting due to 3 previous errors
33+
34+
Some errors have detailed explanations: E0107, E0229.
35+
For more information about an error, try `rustc --explain E0107`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait Foo<const N: usize> {
2+
fn do_x(&self) -> [u8; N];
3+
}
4+
5+
struct Bar;
6+
7+
const T: usize = 42;
8+
9+
impl Foo<N = type 3> for Bar {
10+
//~^ERROR missing type to the right of `=`
11+
//~^^ERROR found keyword `type`
12+
fn do_x(&self) -> [u8; 3] {
13+
[0u8; 3]
14+
}
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: missing type to the right of `=`
2+
--> $DIR/issue-89013-type.rs:9:13
3+
|
4+
LL | impl Foo<N = type 3> for Bar {
5+
| ^
6+
|
7+
help: to constrain the associated type, add a type after `=`
8+
|
9+
LL | impl Foo<N = TheType type 3> for Bar {
10+
| +++++++
11+
help: remove the `=` if `N` is a type
12+
|
13+
LL - impl Foo<N = type 3> for Bar {
14+
LL + impl Foo<N type 3> for Bar {
15+
|
16+
17+
error: expected one of `,`, `>`, a const expression, lifetime, or type, found keyword `type`
18+
--> $DIR/issue-89013-type.rs:9:14
19+
|
20+
LL | impl Foo<N = type 3> for Bar {
21+
| ^^^^ expected one of `,`, `>`, a const expression, lifetime, or type
22+
23+
error: aborting due to 2 previous errors
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait Foo<const N: usize> {
2+
fn do_x(&self) -> [u8; N];
3+
}
4+
5+
struct Bar;
6+
7+
const T: usize = 42;
8+
9+
impl Foo<N = const 3> for Bar {
10+
//~^ERROR expected lifetime, type, or constant, found keyword `const`
11+
//~^^ERROR cannot constrain an associated constant to a value
12+
//~^^^ERROR this trait takes 1 generic argument but 0 generic arguments
13+
//~^^^^ERROR associated type bindings are not allowed here
14+
fn do_x(&self) -> [u8; 3] {
15+
[0u8; 3]
16+
}
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error: expected lifetime, type, or constant, found keyword `const`
2+
--> $DIR/issue-89013.rs:9:14
3+
|
4+
LL | impl Foo<N = const 3> for Bar {
5+
| ^^^^^
6+
7+
error: cannot constrain an associated constant to a value
8+
--> $DIR/issue-89013.rs:9:10
9+
|
10+
LL | impl Foo<N = const 3> for Bar {
11+
| -^^^^^^^^^-
12+
| | |
13+
| | ...cannot be constrained to this value
14+
| this associated constant...
15+
16+
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
17+
--> $DIR/issue-89013.rs:9:6
18+
|
19+
LL | impl Foo<N = const 3> for Bar {
20+
| ^^^ expected 1 generic argument
21+
|
22+
note: trait defined here, with 1 generic parameter: `N`
23+
--> $DIR/issue-89013.rs:1:7
24+
|
25+
LL | trait Foo<const N: usize> {
26+
| ^^^ -
27+
help: add missing generic argument
28+
|
29+
LL | impl Foo<N, N = const 3> for Bar {
30+
| ++
31+
32+
error[E0229]: associated type bindings are not allowed here
33+
--> $DIR/issue-89013.rs:9:10
34+
|
35+
LL | impl Foo<N = const 3> for Bar {
36+
| ^^^^^^^^^^^ associated type not allowed here
37+
38+
error: aborting due to 4 previous errors
39+
40+
Some errors have detailed explanations: E0107, E0229.
41+
For more information about an error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)