@@ -120,12 +120,21 @@ impl<'a> AstValidator<'a> {
120120            let  err = "`let` expressions are not supported here" ; 
121121            let  mut  diag = sess. struct_span_err ( expr. span ,  err) ; 
122122            diag. note ( "only supported directly in conditions of `if` and `while` expressions" ) ; 
123-             diag. note ( "as well as when nested within `&&` and parentheses in those conditions" ) ; 
124-             if  let  ForbiddenLetReason :: ForbiddenWithOr ( span)  = forbidden_let_reason { 
125-                 diag. span_note ( 
126-                     span, 
127-                     "`||` operators are not currently supported in let chain expressions" , 
128-                 ) ; 
123+             match  forbidden_let_reason { 
124+                 ForbiddenLetReason :: GenericForbidden  => { } 
125+                 ForbiddenLetReason :: NotSupportedOr ( span)  => { 
126+                     diag. span_note ( 
127+                         span, 
128+                         "`||` operators are not supported in let chain expressions" , 
129+                     ) ; 
130+                 } 
131+                 ForbiddenLetReason :: NotSupportedParentheses ( span)  => { 
132+                     diag. span_note ( 
133+                         span, 
134+                         "`let`s wrapped in parentheses are not supported in a context with let \  
135+ , 
136+                     ) ; 
137+                 } 
129138            } 
130139            diag. emit ( ) ; 
131140        }  else  { 
@@ -1009,9 +1018,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10091018        self . with_let_management ( Some ( ForbiddenLetReason :: GenericForbidden ) ,  |this,  forbidden_let_reason| { 
10101019            match  & expr. kind  { 
10111020                ExprKind :: Binary ( Spanned  {  node :  BinOpKind :: Or ,  span } ,  lhs,  rhs)  => { 
1012-                     let  forbidden_let_reason  = Some ( ForbiddenLetReason :: ForbiddenWithOr ( * span) ) ; 
1013-                     this. with_let_management ( forbidden_let_reason ,  |this,  _| this. visit_expr ( lhs) ) ; 
1014-                     this. with_let_management ( forbidden_let_reason ,  |this,  _| this. visit_expr ( rhs) ) ; 
1021+                     let  local_reason  = Some ( ForbiddenLetReason :: NotSupportedOr ( * span) ) ; 
1022+                     this. with_let_management ( local_reason ,  |this,  _| this. visit_expr ( lhs) ) ; 
1023+                     this. with_let_management ( local_reason ,  |this,  _| this. visit_expr ( rhs) ) ; 
10151024                } 
10161025                ExprKind :: If ( cond,  then,  opt_else)  => { 
10171026                    this. visit_block ( then) ; 
@@ -1036,7 +1045,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10361045                        } 
10371046                    } 
10381047                } 
1039-                 ExprKind :: Paren ( _)  | ExprKind :: Binary ( Spanned  {  node :  BinOpKind :: And ,  .. } ,  ..)  => { 
1048+                 ExprKind :: Paren ( local_expr)  => { 
1049+                     fn  has_let_expr ( expr :  & Expr )  -> bool  { 
1050+                         match  expr. kind  { 
1051+                             ExprKind :: Binary ( _,  ref  lhs,  ref  rhs)  => has_let_expr ( lhs)  || has_let_expr ( rhs) , 
1052+                             ExprKind :: Let ( ..)  => true , 
1053+                             _ => false , 
1054+                         } 
1055+                     } 
1056+                     let  local_reason = if  has_let_expr ( local_expr)  { 
1057+                         Some ( ForbiddenLetReason :: NotSupportedParentheses ( local_expr. span ) ) 
1058+                     } 
1059+                     else  { 
1060+                         forbidden_let_reason
1061+                     } ; 
1062+                     this. with_let_management ( local_reason,  |this,  _| this. visit_expr ( local_expr) ) ; 
1063+                 } 
1064+                 ExprKind :: Binary ( Spanned  {  node :  BinOpKind :: And ,  .. } ,  ..)  => { 
10401065                    this. with_let_management ( forbidden_let_reason,  |this,  _| visit:: walk_expr ( this,  expr) ) ; 
10411066                    return ; 
10421067                } 
@@ -1810,8 +1835,13 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
18101835/// Used to forbid `let` expressions in certain syntactic locations. 
18111836#[ derive( Clone ,  Copy ) ]  
18121837enum  ForbiddenLetReason  { 
1813-     /// A let chain with the `||` operator 
1814- ForbiddenWithOr ( Span ) , 
18151838    /// `let` is not valid and the source environment is not important 
18161839GenericForbidden , 
1840+     /// A let chain with the `||` operator 
1841+ NotSupportedOr ( Span ) , 
1842+     /// A let chain with invalid parentheses 
1843+ /// 
1844+ /// For exemple, `let 1 = 1 && (expr && expr)` is allowed 
1845+ /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not 
1846+ NotSupportedParentheses ( Span ) , 
18171847} 
0 commit comments