@@ -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+ chains",
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
18161839 GenericForbidden ,
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