Skip to content

Commit 13c8c32

Browse files
authored
Rollup merge of rust-lang#89029 - notriddle:notriddle/issue-89013, r=estebank
feat(rustc_parse): recover from pre-RFC-2000 const generics syntax Fixes rust-lang#89013
2 parents a91818a + 105b60f commit 13c8c32

File tree

11 files changed

+180
-6
lines changed

11 files changed

+180
-6
lines changed

compiler/rustc_hir/src/hir.rs

+10
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,16 @@ impl GenericArgs<'_> {
384384
self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_)))
385385
}
386386

387+
pub fn has_err(&self) -> bool {
388+
self.args.iter().any(|arg| match arg {
389+
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
390+
_ => false,
391+
}) || self.bindings.iter().any(|arg| match arg.kind {
392+
TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err),
393+
_ => false,
394+
})
395+
}
396+
387397
#[inline]
388398
pub fn num_type_params(&self) -> usize {
389399
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()

compiler/rustc_parse/src/parser/path.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -495,20 +495,28 @@ 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-
self.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`")
499-
.span_suggestion(
498+
let mut err = self
499+
.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`");
500+
if matches!(self.token.kind, token::Comma | token::Gt) {
501+
err.span_suggestion(
500502
self.sess.source_map().next_point(eq).to(before_next),
501503
"to constrain the associated type, add a type after `=`",
502504
" TheType".to_string(),
503505
Applicability::HasPlaceholders,
504-
)
505-
.span_suggestion(
506+
);
507+
err.span_suggestion(
506508
eq.to(before_next),
507509
&format!("remove the `=` if `{}` is a type", ident),
508510
String::new(),
509511
Applicability::MaybeIncorrect,
510512
)
511-
.emit();
513+
} else {
514+
err.span_label(
515+
self.token.span,
516+
&format!("expected type, found {}", super::token_descr(&self.token)),
517+
)
518+
};
519+
return Err(err);
512520
}
513521
}
514522
Ok(self.mk_ty(span, ast::TyKind::Err))
@@ -572,6 +580,25 @@ impl<'a> Parser<'a> {
572580
return self.recover_const_arg(start, err).map(Some);
573581
}
574582
}
583+
} else if self.eat_keyword_noexpect(kw::Const) {
584+
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
585+
let mut err = self.struct_span_err(
586+
start,
587+
"expected lifetime, type, or constant, found keyword `const`",
588+
);
589+
if self.check_const_arg() {
590+
err.span_suggestion_verbose(
591+
start.until(self.token.span),
592+
"the `const` keyword is only needed in the definition of the type",
593+
String::new(),
594+
Applicability::MaybeIncorrect,
595+
);
596+
err.emit();
597+
GenericArg::Const(self.parse_const_arg()?)
598+
} else {
599+
let after_kw_const = self.token.span;
600+
return self.recover_const_arg(after_kw_const, err).map(Some);
601+
}
575602
} else {
576603
return Ok(None);
577604
};

compiler/rustc_typeck/src/astconv/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
600600
def_id,
601601
)
602602
.diagnostic()
603-
.emit();
603+
.emit_unless(gen_args.has_err());
604604

605605
false
606606
};
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,14 @@
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+
help: the `const` keyword is only needed in the definition of the type
8+
|
9+
LL - impl Foo<const 3> for Bar {
10+
LL + impl Foo<3> for Bar {
11+
|
12+
13+
error: aborting due to previous error
14+
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 = 3> for Bar {
10+
//~^ ERROR cannot constrain an associated constant to a value
11+
//~| ERROR associated type bindings are not allowed here
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,18 @@
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[E0229]: associated type bindings are not allowed here
11+
--> $DIR/issue-89013-no-kw.rs:9:10
12+
|
13+
LL | impl Foo<N = 3> for Bar {
14+
| ^^^^^ associated type not allowed here
15+
16+
error: aborting due to 2 previous errors
17+
18+
For more information about this error, try `rustc --explain E0229`.
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<N = type 3> for Bar {
10+
//~^ERROR missing type to the right of `=`
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: 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+
| ^---- expected type, found keyword `type`
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 = 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 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,30 @@
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+
help: the `const` keyword is only needed in the definition of the type
8+
|
9+
LL - impl Foo<N = const 3> for Bar {
10+
LL + impl Foo<N = 3> for Bar {
11+
|
12+
13+
error: cannot constrain an associated constant to a value
14+
--> $DIR/issue-89013.rs:9:10
15+
|
16+
LL | impl Foo<N = const 3> for Bar {
17+
| -^^^^^^^^^-
18+
| | |
19+
| | ...cannot be constrained to this value
20+
| this associated constant...
21+
22+
error[E0229]: associated type bindings are not allowed here
23+
--> $DIR/issue-89013.rs:9:10
24+
|
25+
LL | impl Foo<N = const 3> for Bar {
26+
| ^^^^^^^^^^^ associated type not allowed here
27+
28+
error: aborting due to 3 previous errors
29+
30+
For more information about this error, try `rustc --explain E0229`.

0 commit comments

Comments
 (0)