Recover from &dyn mut ...
parse errors
This commit is contained in:
parent
ce331ee6ee
commit
c692896ba2
3 changed files with 45 additions and 1 deletions
|
@ -393,7 +393,7 @@ impl<'a> Parser<'a> {
|
||||||
let and_span = self.prev_token.span;
|
let and_span = self.prev_token.span;
|
||||||
let mut opt_lifetime =
|
let mut opt_lifetime =
|
||||||
if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
|
if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
|
||||||
let mutbl = self.parse_mutability();
|
let mut mutbl = self.parse_mutability();
|
||||||
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
|
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
|
||||||
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
|
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
|
||||||
// it to be followed by a plus, but we disallow plus in the pointee type.
|
// it to be followed by a plus, but we disallow plus in the pointee type.
|
||||||
|
@ -417,6 +417,26 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
opt_lifetime = Some(self.expect_lifetime());
|
opt_lifetime = Some(self.expect_lifetime());
|
||||||
}
|
}
|
||||||
|
} else if self.token.is_keyword(kw::Dyn)
|
||||||
|
&& mutbl == Mutability::Not
|
||||||
|
&& self.look_ahead(1, |t| t.is_keyword(kw::Mut))
|
||||||
|
{
|
||||||
|
// We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
|
||||||
|
let span = and_span.to(self.look_ahead(1, |t| t.span));
|
||||||
|
let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
|
||||||
|
err.span_suggestion(
|
||||||
|
span,
|
||||||
|
"place `mut` before `dyn`",
|
||||||
|
"&mut dyn".to_string(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
|
||||||
|
// Recovery
|
||||||
|
mutbl = Mutability::Mut;
|
||||||
|
let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
|
||||||
|
self.bump();
|
||||||
|
self.bump_with((dyn_tok, dyn_tok_sp));
|
||||||
}
|
}
|
||||||
let ty = self.parse_ty_no_plus()?;
|
let ty = self.parse_ty_no_plus()?;
|
||||||
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
|
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
|
||||||
|
|
9
src/test/ui/parser/recover-ref-dyn-mut.rs
Normal file
9
src/test/ui/parser/recover-ref-dyn-mut.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Test that the parser detects `&dyn mut`, offers a help message, and
|
||||||
|
// recovers.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let r: &dyn mut Trait;
|
||||||
|
//~^ ERROR: `mut` must precede `dyn`
|
||||||
|
//~| HELP: place `mut` before `dyn`
|
||||||
|
//~| ERROR: cannot find trait `Trait` in this scope [E0405]
|
||||||
|
}
|
15
src/test/ui/parser/recover-ref-dyn-mut.stderr
Normal file
15
src/test/ui/parser/recover-ref-dyn-mut.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error: `mut` must precede `dyn`
|
||||||
|
--> $DIR/recover-ref-dyn-mut.rs:5:12
|
||||||
|
|
|
||||||
|
LL | let r: &dyn mut Trait;
|
||||||
|
| ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn`
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `Trait` in this scope
|
||||||
|
--> $DIR/recover-ref-dyn-mut.rs:5:21
|
||||||
|
|
|
||||||
|
LL | let r: &dyn mut Trait;
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0405`.
|
Loading…
Add table
Add a link
Reference in a new issue