@@ -475,6 +475,7 @@ impl<'a> Parser<'a> {
475475 }
476476
477477 fn error_block_no_opening_brace_msg ( & mut self , msg : Cow < ' static , str > ) -> Diag < ' a > {
478+ let prev = self . prev_token . span ;
478479 let sp = self . token . span ;
479480 let mut e = self . dcx ( ) . struct_span_err ( sp, msg) ;
480481 let do_not_suggest_help = self . token . is_keyword ( kw:: In ) || self . token == token:: Colon ;
@@ -514,8 +515,97 @@ impl<'a> Parser<'a> {
514515 } else {
515516 stmt. span
516517 } ;
518+ self . suggest_fixes_misparsed_for_loop_head (
519+ & mut e,
520+ prev. between ( sp) ,
521+ stmt_span,
522+ & stmt. kind ,
523+ ) ;
524+ }
525+ Err ( e) => {
526+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
527+ e. cancel ( ) ;
528+ }
529+ _ => { }
530+ }
531+ e. span_label ( sp, "expected `{`" ) ;
532+ e
533+ }
534+
535+ fn suggest_fixes_misparsed_for_loop_head (
536+ & self ,
537+ e : & mut Diag < ' _ > ,
538+ between : Span ,
539+ stmt_span : Span ,
540+ stmt_kind : & StmtKind ,
541+ ) {
542+ match ( & self . token . kind , & stmt_kind) {
543+ ( token:: OpenDelim ( Delimiter :: Brace ) , StmtKind :: Expr ( expr) )
544+ if let ExprKind :: Call ( ..) = expr. kind =>
545+ {
546+ // for _ in x y() {}
547+ e. span_suggestion_verbose (
548+ between,
549+ "you might have meant to write a method call" ,
550+ "." . to_string ( ) ,
551+ Applicability :: MaybeIncorrect ,
552+ ) ;
553+ }
554+ ( token:: OpenDelim ( Delimiter :: Brace ) , StmtKind :: Expr ( expr) )
555+ if let ExprKind :: Field ( ..) = expr. kind =>
556+ {
557+ // for _ in x y.z {}
558+ e. span_suggestion_verbose (
559+ between,
560+ "you might have meant to write a field access" ,
561+ "." . to_string ( ) ,
562+ Applicability :: MaybeIncorrect ,
563+ ) ;
564+ }
565+ ( token:: CloseDelim ( Delimiter :: Brace ) , StmtKind :: Expr ( expr) )
566+ if let ExprKind :: Struct ( expr) = & expr. kind
567+ && let None = expr. qself
568+ && expr. path . segments . len ( ) == 1 =>
569+ {
570+ // This is specific to "mistyped `if` condition followed by empty body"
571+ //
572+ // for _ in x y {}
573+ e. span_suggestion_verbose (
574+ between,
575+ "you might have meant to write a field access" ,
576+ "." . to_string ( ) ,
577+ Applicability :: MaybeIncorrect ,
578+ ) ;
579+ }
580+ ( token:: OpenDelim ( Delimiter :: Brace ) , StmtKind :: Expr ( expr) )
581+ if let ExprKind :: Lit ( lit) = expr. kind
582+ && let None = lit. suffix
583+ && let token:: LitKind :: Integer | token:: LitKind :: Float = lit. kind =>
584+ {
585+ // for _ in x 0 {}
586+ // for _ in x 0.0 {}
587+ e. span_suggestion_verbose (
588+ between,
589+ format ! ( "you might have meant to write a field access" ) ,
590+ "." . to_string ( ) ,
591+ Applicability :: MaybeIncorrect ,
592+ ) ;
593+ }
594+ ( token:: OpenDelim ( Delimiter :: Brace ) , StmtKind :: Expr ( expr) )
595+ if let ExprKind :: Loop ( ..)
596+ | ExprKind :: If ( ..)
597+ | ExprKind :: While ( ..)
598+ | ExprKind :: Match ( ..)
599+ | ExprKind :: ForLoop { .. }
600+ | ExprKind :: TryBlock ( ..)
601+ | ExprKind :: Ret ( ..)
602+ | ExprKind :: Closure ( ..)
603+ | ExprKind :: Struct ( ..)
604+ | ExprKind :: Try ( ..) = expr. kind =>
605+ {
606+ // These are more likely to have been meant as a block body.
517607 e. multipart_suggestion (
518- "try placing this code inside a block" ,
608+ "you might have meant to write this as part of a block" ,
519609 vec ! [
520610 ( stmt_span. shrink_to_lo( ) , "{ " . to_string( ) ) ,
521611 ( stmt_span. shrink_to_hi( ) , " }" . to_string( ) ) ,
@@ -524,14 +614,19 @@ impl<'a> Parser<'a> {
524614 Applicability :: MaybeIncorrect ,
525615 ) ;
526616 }
527- Err ( e) => {
528- self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
529- e. cancel ( ) ;
617+ ( token:: OpenDelim ( Delimiter :: Brace ) , _) => { }
618+ ( _, _) => {
619+ e. multipart_suggestion (
620+ "you might have meant to write this as part of a block" ,
621+ vec ! [
622+ ( stmt_span. shrink_to_lo( ) , "{ " . to_string( ) ) ,
623+ ( stmt_span. shrink_to_hi( ) , " }" . to_string( ) ) ,
624+ ] ,
625+ // Speculative; has been misleading in the past (#46836).
626+ Applicability :: MaybeIncorrect ,
627+ ) ;
530628 }
531- _ => { }
532629 }
533- e. span_label ( sp, "expected `{`" ) ;
534- e
535630 }
536631
537632 fn error_block_no_opening_brace < T > ( & mut self ) -> PResult < ' a , T > {
0 commit comments