@@ -393,7 +393,7 @@ impl<'a> Parser<'a> {
393
393
let and_span = self . prev_token . span ;
394
394
let mut opt_lifetime =
395
395
if self . check_lifetime ( ) { Some ( self . expect_lifetime ( ) ) } else { None } ;
396
- let mutbl = self . parse_mutability ( ) ;
396
+ let mut mutbl = self . parse_mutability ( ) ;
397
397
if self . token . is_lifetime ( ) && mutbl == Mutability :: Mut && opt_lifetime. is_none ( ) {
398
398
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
399
399
// it to be followed by a plus, but we disallow plus in the pointee type.
@@ -417,6 +417,26 @@ impl<'a> Parser<'a> {
417
417
418
418
opt_lifetime = Some ( self . expect_lifetime ( ) ) ;
419
419
}
420
+ } else if self . token . is_keyword ( kw:: Dyn )
421
+ && mutbl == Mutability :: Not
422
+ && self . look_ahead ( 1 , |t| t. is_keyword ( kw:: Mut ) )
423
+ {
424
+ // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
425
+ let span = and_span. to ( self . look_ahead ( 1 , |t| t. span ) ) ;
426
+ let mut err = self . struct_span_err ( span, "`mut` must precede `dyn`" ) ;
427
+ err. span_suggestion (
428
+ span,
429
+ "place `mut` before `dyn`" ,
430
+ "&mut dyn" . to_string ( ) ,
431
+ Applicability :: MachineApplicable ,
432
+ ) ;
433
+ err. emit ( ) ;
434
+
435
+ // Recovery
436
+ mutbl = Mutability :: Mut ;
437
+ let ( dyn_tok, dyn_tok_sp) = ( self . token . clone ( ) , self . token_spacing ) ;
438
+ self . bump ( ) ;
439
+ self . bump_with ( ( dyn_tok, dyn_tok_sp) ) ;
420
440
}
421
441
let ty = self . parse_ty_no_plus ( ) ?;
422
442
Ok ( TyKind :: Rptr ( opt_lifetime, MutTy { ty, mutbl } ) )
0 commit comments