Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ impl<'a> Parser<'a> {
let and_span = self.prev_token.span;
let mut opt_lifetime =
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() {
// 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.
Expand All @@ -417,6 +417,26 @@ impl<'a> Parser<'a> {

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()?;
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/parser/recover-ref-dyn-mut.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions src/test/ui/parser/recover-ref-dyn-mut.stderr
Original file line number Diff line number Diff line change
@@ -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`.