@@ -294,17 +294,22 @@ impl<'a> Parser<'a> {
294
294
let ( pat, colon) =
295
295
self . parse_pat_before_ty ( None , RecoverComma :: Yes , PatternLocation :: LetBinding ) ?;
296
296
297
- let ( err, ty) = if colon {
297
+ let ( err, ty, colon_sp ) = if colon {
298
298
// Save the state of the parser before parsing type normally, in case there is a `:`
299
299
// instead of an `=` typo.
300
300
let parser_snapshot_before_type = self . clone ( ) ;
301
301
let colon_sp = self . prev_token . span ;
302
302
match self . parse_ty ( ) {
303
- Ok ( ty) => ( None , Some ( ty) ) ,
303
+ Ok ( ty) => ( None , Some ( ty) , Some ( colon_sp ) ) ,
304
304
Err ( mut err) => {
305
- if let Ok ( snip) = self . span_to_snippet ( pat. span ) {
306
- err. span_label ( pat. span , format ! ( "while parsing the type for `{snip}`" ) ) ;
307
- }
305
+ err. span_label (
306
+ colon_sp,
307
+ format ! (
308
+ "while parsing the type for {}" ,
309
+ pat. descr( )
310
+ . map_or_else( || "the binding" . to_string( ) , |n| format!( "`{n}`" ) )
311
+ ) ,
312
+ ) ;
308
313
// we use noexpect here because we don't actually expect Eq to be here
309
314
// but we are still checking for it in order to be able to handle it if
310
315
// it is there
@@ -317,11 +322,11 @@ impl<'a> Parser<'a> {
317
322
mem:: replace ( self , parser_snapshot_before_type) ;
318
323
Some ( ( parser_snapshot_after_type, colon_sp, err) )
319
324
} ;
320
- ( err, None )
325
+ ( err, None , Some ( colon_sp ) )
321
326
}
322
327
}
323
328
} else {
324
- ( None , None )
329
+ ( None , None , None )
325
330
} ;
326
331
let init = match ( self . parse_initializer ( err. is_some ( ) ) , err) {
327
332
( Ok ( init) , None ) => {
@@ -380,7 +385,16 @@ impl<'a> Parser<'a> {
380
385
}
381
386
} ;
382
387
let hi = if self . token == token:: Semi { self . token . span } else { self . prev_token . span } ;
383
- Ok ( P ( ast:: Local { ty, pat, kind, id : DUMMY_NODE_ID , span : lo. to ( hi) , attrs, tokens : None } ) )
388
+ Ok ( P ( ast:: Local {
389
+ ty,
390
+ pat,
391
+ kind,
392
+ id : DUMMY_NODE_ID ,
393
+ span : lo. to ( hi) ,
394
+ colon_sp,
395
+ attrs,
396
+ tokens : None ,
397
+ } ) )
384
398
}
385
399
386
400
fn check_let_else_init_bool_expr ( & self , init : & ast:: Expr ) {
@@ -750,15 +764,55 @@ impl<'a> Parser<'a> {
750
764
}
751
765
}
752
766
StmtKind :: Expr ( _) | StmtKind :: MacCall ( _) => { }
753
- StmtKind :: Local ( local) if let Err ( e) = self . expect_semi ( ) => {
767
+ StmtKind :: Local ( local) if let Err ( mut e) = self . expect_semi ( ) => {
754
768
// We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
755
769
match & mut local. kind {
756
770
LocalKind :: Init ( expr) | LocalKind :: InitElse ( expr, _) => {
757
771
self . check_mistyped_turbofish_with_multiple_type_params ( e, expr) ?;
758
772
// We found `foo<bar, baz>`, have we fully recovered?
759
773
self . expect_semi ( ) ?;
760
774
}
761
- LocalKind :: Decl => return Err ( e) ,
775
+ LocalKind :: Decl => {
776
+ if let Some ( colon_sp) = local. colon_sp {
777
+ e. span_label (
778
+ colon_sp,
779
+ format ! (
780
+ "while parsing the type for {}" ,
781
+ local. pat. descr( ) . map_or_else(
782
+ || "the binding" . to_string( ) ,
783
+ |n| format!( "`{n}`" )
784
+ )
785
+ ) ,
786
+ ) ;
787
+ let suggest_eq = if self . token . kind == token:: Dot
788
+ && let _ = self . bump ( )
789
+ && let mut snapshot = self . create_snapshot_for_diagnostic ( )
790
+ && let Ok ( _) = snapshot. parse_dot_suffix_expr (
791
+ colon_sp,
792
+ self . mk_expr_err (
793
+ colon_sp,
794
+ self . dcx ( ) . delayed_bug ( "error during `:` -> `=` recovery" ) ,
795
+ ) ,
796
+ ) {
797
+ true
798
+ } else if let Some ( op) = self . check_assoc_op ( )
799
+ && op. node . can_continue_expr_unambiguously ( )
800
+ {
801
+ true
802
+ } else {
803
+ false
804
+ } ;
805
+ if suggest_eq {
806
+ e. span_suggestion_short (
807
+ colon_sp,
808
+ "use `=` if you meant to assign" ,
809
+ "=" ,
810
+ Applicability :: MaybeIncorrect ,
811
+ ) ;
812
+ }
813
+ }
814
+ return Err ( e) ;
815
+ }
762
816
}
763
817
eat_semi = false ;
764
818
}
0 commit comments