@@ -67,40 +67,7 @@ impl LoweringContext<'_> {
67
67
let ohs = P ( self . lower_expr ( ohs) ) ;
68
68
hir:: ExprKind :: AddrOf ( m, ohs)
69
69
}
70
- ExprKind :: Let ( ref pats, ref scrutinee) => {
71
- // If we got here, the `let` expression is not allowed.
72
- self . sess
73
- . struct_span_err ( e. span , "`let` expressions are not supported here" )
74
- . note ( "only supported directly in conditions of `if`- and `while`-expressions" )
75
- . note ( "as well as when nested within `&&` and parenthesis in those conditions" )
76
- . emit ( ) ;
77
-
78
- // For better recovery, we emit:
79
- // ```
80
- // match scrutinee { pats => true, _ => false }
81
- // ```
82
- // While this doesn't fully match the user's intent, it has key advantages:
83
- // 1. We can avoid using `abort_if_errors`.
84
- // 2. We can typeck both `pats` and `scrutinee`.
85
- // 3. `pats` is allowed to be refutable.
86
- // 4. The return type of the block is `bool` which seems like what the user wanted.
87
- let scrutinee = self . lower_expr ( scrutinee) ;
88
- let then_arm = {
89
- let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
90
- let expr = self . expr_bool ( e. span , true ) ;
91
- self . arm ( pats, P ( expr) )
92
- } ;
93
- let else_arm = {
94
- let pats = hir_vec ! [ self . pat_wild( e. span) ] ;
95
- let expr = self . expr_bool ( e. span , false ) ;
96
- self . arm ( pats, P ( expr) )
97
- } ;
98
- hir:: ExprKind :: Match (
99
- P ( scrutinee) ,
100
- vec ! [ then_arm, else_arm] . into ( ) ,
101
- hir:: MatchSource :: Normal ,
102
- )
103
- }
70
+ ExprKind :: Let ( ref pats, ref scrutinee) => self . lower_expr_let ( e. span , pats, scrutinee) ,
104
71
ExprKind :: If ( ref cond, ref then, ref else_opt) => {
105
72
self . lower_expr_if ( e. span , cond, then, else_opt. as_deref ( ) )
106
73
}
@@ -240,6 +207,50 @@ impl LoweringContext<'_> {
240
207
}
241
208
}
242
209
210
+ /// Emit an error and lower `ast::ExprKind::Let(pats, scrutinee)` into:
211
+ /// ```rust
212
+ /// match scrutinee { pats => true, _ => false }
213
+ /// ```
214
+ fn lower_expr_let (
215
+ & mut self ,
216
+ span : Span ,
217
+ pats : & [ AstP < Pat > ] ,
218
+ scrutinee : & Expr
219
+ ) -> hir:: ExprKind {
220
+ // If we got here, the `let` expression is not allowed.
221
+ self . sess
222
+ . struct_span_err ( span, "`let` expressions are not supported here" )
223
+ . note ( "only supported directly in conditions of `if`- and `while`-expressions" )
224
+ . note ( "as well as when nested within `&&` and parenthesis in those conditions" )
225
+ . emit ( ) ;
226
+
227
+ // For better recovery, we emit:
228
+ // ```
229
+ // match scrutinee { pats => true, _ => false }
230
+ // ```
231
+ // While this doesn't fully match the user's intent, it has key advantages:
232
+ // 1. We can avoid using `abort_if_errors`.
233
+ // 2. We can typeck both `pats` and `scrutinee`.
234
+ // 3. `pats` is allowed to be refutable.
235
+ // 4. The return type of the block is `bool` which seems like what the user wanted.
236
+ let scrutinee = self . lower_expr ( scrutinee) ;
237
+ let then_arm = {
238
+ let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
239
+ let expr = self . expr_bool ( span, true ) ;
240
+ self . arm ( pats, P ( expr) )
241
+ } ;
242
+ let else_arm = {
243
+ let pats = hir_vec ! [ self . pat_wild( span) ] ;
244
+ let expr = self . expr_bool ( span, false ) ;
245
+ self . arm ( pats, P ( expr) )
246
+ } ;
247
+ hir:: ExprKind :: Match (
248
+ P ( scrutinee) ,
249
+ vec ! [ then_arm, else_arm] . into ( ) ,
250
+ hir:: MatchSource :: Normal ,
251
+ )
252
+ }
253
+
243
254
fn lower_expr_if (
244
255
& mut self ,
245
256
span : Span ,
0 commit comments