diff options
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 22 | ||||
| -rw-r--r-- | src/test/ui/parser/kw-in-trait-bounds.rs | 47 | ||||
| -rw-r--r-- | src/test/ui/parser/kw-in-trait-bounds.stderr | 171 | ||||
| -rw-r--r-- | src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr | 6 |
5 files changed, 244 insertions, 4 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 76b710095d7..4a2cf74905b 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -640,7 +640,13 @@ impl<'a> Parser<'a> { let mut bounds = Vec::new(); let mut negative_bounds = Vec::new(); - while self.can_begin_bound() || self.token.is_keyword(kw::Dyn) { + while self.can_begin_bound() + // Continue even if we find a keyword. + // This is necessary for error recover on, for example, `impl fn()`. + // + // The only keyword that can go after generic bounds is `where`, so stop if it's it. + || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)) + { if self.token.is_keyword(kw::Dyn) { // Account for `&dyn Trait + dyn Other`. self.struct_span_err(self.token.span, "invalid `dyn` keyword") @@ -804,6 +810,20 @@ impl<'a> Parser<'a> { let span = tilde.to(self.prev_token.span); self.sess.gated_spans.gate(sym::const_trait_impl, span); Some(span) + } else if self.eat_keyword(kw::Const) { + let span = self.prev_token.span; + self.sess.gated_spans.gate(sym::const_trait_impl, span); + + self.struct_span_err(span, "const bounds must start with `~`") + .span_suggestion( + span.shrink_to_lo(), + "add `~`", + "~", + Applicability::MachineApplicable, + ) + .emit(); + + Some(span) } else { None }; diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs new file mode 100644 index 00000000000..fa037e5937d --- /dev/null +++ b/src/test/ui/parser/kw-in-trait-bounds.rs @@ -0,0 +1,47 @@ +// edition:2018 + +fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| ERROR cannot find trait `r#fn` in this scope +//~| ERROR cannot find trait `r#fn` in this scope +//~| ERROR cannot find trait `r#fn` in this scope +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP escape `fn` to use it as an identifier +//~| HELP escape `fn` to use it as an identifier +//~| HELP escape `fn` to use it as an identifier +where +G: fn(), + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR cannot find trait `r#fn` in this scope + //~| HELP a trait with a similar name exists + //~| HELP escape `fn` to use it as an identifier +{} + +fn _g<A: struct, B>(_: impl struct, _: &dyn struct) +//~^ ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +where + B: struct, + //~^ ERROR expected identifier, found keyword `struct` + //~| ERROR cannot find trait `r#struct` in this scope + //~| HELP a trait with a similar name exists + //~| HELP escape `struct` to use it as an identifier +{} + +trait Struct {} + +fn main() {} diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr new file mode 100644 index 00000000000..28196c7ce2d --- /dev/null +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -0,0 +1,171 @@ +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:10 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:27 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:41 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:17:4 + | +LL | G: fn(), + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | G: r#fn(), + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:10 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:29 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:45 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:38:8 + | +LL | B: struct, + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | B: r#struct, + | ++ + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:10 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args>: FnMut<Args> { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:17:4 + | +LL | G: fn(), + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args>: FnMut<Args> { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:27 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args>: FnMut<Args> { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:41 + | +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn<Args>: FnMut<Args> { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:10 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:38:8 + | +LL | B: struct, + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:29 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:45 + | +LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs index e8b26154549..d63381b5f2c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs @@ -3,4 +3,4 @@ #![feature(const_trait_impl)] struct S<T: const Tr>; -//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path +//~^ ERROR const bounds must start with `~` diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr index b6b77ac4a2f..31300354a57 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr @@ -1,8 +1,10 @@ -error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const` +error: const bounds must start with `~` --> $DIR/without-tilde.rs:5:13 | LL | struct S<T: const Tr>; - | ^^^^^ expected one of 10 possible tokens + | -^^^^ + | | + | help: add `~`: `~` error: aborting due to previous error |
