@@ -97,6 +97,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
9797                    ExprKind :: Let ( ref  pat,  ref  scrutinee)  => { 
9898                        self . lower_expr_if_let ( e. span ,  pat,  scrutinee,  then,  else_opt. as_deref ( ) ) 
9999                    } 
100+                     ExprKind :: Paren ( ref  paren)  => match  paren. peel_parens ( ) . kind  { 
101+                         ExprKind :: Let ( ref  pat,  ref  scrutinee)  => { 
102+                             // A user has written `if (let Some(x) = foo) {`, we want to avoid 
103+                             // confusing them with mentions of nightly features. 
104+                             // If this logic is changed, you will also likely need to touch 
105+                             // `unused::UnusedParens::check_expr`. 
106+                             self . if_let_expr_with_parens ( cond,  & paren. peel_parens ( ) ) ; 
107+                             self . lower_expr_if_let ( 
108+                                 e. span , 
109+                                 pat, 
110+                                 scrutinee, 
111+                                 then, 
112+                                 else_opt. as_deref ( ) , 
113+                             ) 
114+                         } 
115+                         _ => self . lower_expr_if ( cond,  then,  else_opt. as_deref ( ) ) , 
116+                     } , 
100117                    _ => self . lower_expr_if ( cond,  then,  else_opt. as_deref ( ) ) , 
101118                } , 
102119                ExprKind :: While ( ref  cond,  ref  body,  opt_label)  => self 
@@ -346,6 +363,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
346363        hir:: ExprKind :: Call ( f,  self . lower_exprs ( & real_args) ) 
347364    } 
348365
366+     fn  if_let_expr_with_parens ( & mut  self ,  cond :  & Expr ,  paren :  & Expr )  { 
367+         let  start = cond. span . until ( paren. span ) ; 
368+         let  end = paren. span . shrink_to_hi ( ) . until ( cond. span . shrink_to_hi ( ) ) ; 
369+         self . sess 
370+             . struct_span_err ( 
371+                 vec ! [ start,  end] , 
372+                 "invalid parentheses around `let` expression in `if let`" , 
373+             ) 
374+             . multipart_suggestion ( 
375+                 "`if let` needs to be written without parentheses" , 
376+                 vec ! [ ( start,  String :: new( ) ) ,  ( end,  String :: new( ) ) ] , 
377+                 rustc_errors:: Applicability :: MachineApplicable , 
378+             ) 
379+             . emit ( ) ; 
380+         // Ideally, we'd remove the feature gating of a `let` expression since we are already 
381+         // complaining about it here, but `feature_gate::check_crate` has already run by now: 
382+         // self.sess.parse_sess.gated_spans.ungate_last(sym::let_chains, paren.span); 
383+     } 
384+ 
349385    /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into: 
350386     /// ```rust 
351387     /// match scrutinee { pats => true, _ => false } 
@@ -356,8 +392,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
356392        if  self . sess . opts . unstable_features . is_nightly_build ( )  { 
357393            self . sess 
358394                . struct_span_err ( span,  "`let` expressions are not supported here" ) 
359-                 . note ( "only supported directly in conditions of `if`- and `while`-expressions" ) 
360-                 . note ( "as well as when nested within `&&` and parenthesis in those conditions" ) 
395+                 . note ( 
396+                     "only supported directly without parentheses in conditions of `if`- and \  
397+                       `while`-expressions, as well as in `let` chains within parentheses", 
398+                 ) 
361399                . emit ( ) ; 
362400        }  else  { 
363401            self . sess 
0 commit comments