@@ -50,7 +50,7 @@ pub(crate) struct LowerIfCondArgs {
5050 pub ( crate ) variable_source_info : SourceInfo ,
5151 /// Determines how bindings should be handled when lowering `let` expressions.
5252 ///
53- /// Forwarded to [`Builder::lower_let_expr `] when lowering [`ExprKind::Let`].
53+ /// Forwarded to [`Builder::lower_fallible_let `] when lowering [`ExprKind::Let`].
5454 pub ( crate ) declare_let_bindings : DeclareLetBindings ,
5555}
5656
@@ -62,9 +62,9 @@ impl LowerIfCondArgs {
6262 }
6363}
6464
65- /// Should lowering a `let` expression also declare its bindings?
65+ /// Should lowering a `let` also declare its bindings?
6666///
67- /// Used by [`Builder::lower_let_expr`] when lowering [`ExprKind::Let `].
67+ /// Used by [`Builder::lower_fallible_let `].
6868#[ derive( Clone , Copy ) ]
6969pub ( crate ) enum DeclareLetBindings {
7070 /// Yes, declare `let` bindings as normal for `if` conditions.
@@ -169,10 +169,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
169169 } )
170170 }
171171 ExprKind :: ValueExpr { source } => this. lower_if_condition ( block, source, args) ,
172- ExprKind :: Let { expr , ref pat } => this. lower_let_expr (
172+ ExprKind :: Let { ref pat, expr } => this. lower_fallible_let (
173173 block,
174- expr,
175174 pat,
175+ expr,
176176 Some ( args. variable_source_info . scope ) ,
177177 args. variable_source_info . span ,
178178 args. declare_let_bindings ,
@@ -2309,65 +2309,72 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23092309// Pat binding - used for `let` and function parameters as well.
23102310
23112311impl < ' a , ' tcx > Builder < ' a , ' tcx > {
2312- /// Lowers a `let` expression that appears in a suitable context
2313- /// (e.g. an `if` condition or match guard).
2314- ///
2315- /// Also used for lowering let-else statements, since they have similar
2316- /// needs despite not actually using `let` expressions.
2312+ /// Lowers a fallible `let`, which is one of:
2313+ /// - A let-expression inside an `if` condition or match guard.
2314+ /// - A let-else statement.
23172315 ///
2318- /// Use [`DeclareLetBindings`] to control whether the `let` bindings are
2319- /// declared or not.
2316+ /// (Strictly speaking, the underlying pattern might actually be infallible.
2317+ /// What matters here is that it is _allowed_ to be fallible.)
23202318 ///
23212319 /// Must be called within a [`Builder::in_if_then_scope`], to indicate where
23222320 /// to break to if the `let` fails to match.
2323- pub ( crate ) fn lower_let_expr (
2321+ pub ( crate ) fn lower_fallible_let (
23242322 & mut self ,
23252323 mut block : BasicBlock ,
2326- expr_id : ExprId ,
23272324 pat : & Pat < ' tcx > ,
2325+ scrutinee_id : ExprId ,
23282326 source_scope : Option < SourceScope > ,
23292327 scope_span : Span ,
2328+ // Controls whether bindings are declared or not, as requested by the caller.
23302329 declare_let_bindings : DeclareLetBindings ,
23312330 ) -> BlockAnd < ( ) > {
2332- let expr_span = self . thir [ expr_id] . span ;
2333- let scrutinee = unpack ! ( block = self . lower_scrutinee( block, expr_id) ) ;
2331+ let scrutinee_span = self . thir [ scrutinee_id] . span ;
2332+ let scrutinee_place_builder = unpack ! ( block = self . lower_scrutinee( block, scrutinee_id) ) ;
2333+
2334+ // Lower the scrutinee and pattern as though they were desugared to a `match`.
23342335 let built_tree = self . lower_match_tree (
23352336 block,
2336- expr_span ,
2337- & scrutinee ,
2337+ scrutinee_span ,
2338+ & scrutinee_place_builder ,
23382339 pat. span ,
23392340 vec ! [ ( pat, HasMatchGuard :: No ) ] ,
23402341 Exhaustive :: No ,
23412342 ) ;
2342- let [ branch] = built_tree. branches . try_into ( ) . unwrap ( ) ;
2343+ let [ true_branch] = built_tree. branches . try_into ( ) . unwrap ( ) ;
2344+ let false_block = built_tree. otherwise_block ;
23432345
23442346 // If pattern-matching failed, break out of the enclosing if-then scope.
2345- self . break_from_if_then_scope ( built_tree . otherwise_block , self . source_info ( expr_span ) ) ;
2347+ self . break_from_if_then_scope ( false_block , self . source_info ( scrutinee_span ) ) ;
23462348
23472349 match declare_let_bindings {
23482350 DeclareLetBindings :: Yes => {
2349- let expr_place = scrutinee. try_to_place ( self ) ;
2350- let opt_expr_place = expr_place. as_ref ( ) . map ( |place| ( Some ( place) , expr_span) ) ;
2351+ let scrutinee_place;
2352+ let opt_match_place = try {
2353+ scrutinee_place = scrutinee_place_builder. try_to_place ( self ) ?;
2354+ ( Some ( & scrutinee_place) , scrutinee_span)
2355+ } ;
23512356 self . declare_bindings (
23522357 source_scope,
23532358 pat. span . to ( scope_span) ,
23542359 pat,
23552360 None ,
2356- opt_expr_place ,
2361+ opt_match_place ,
23572362 ) ;
23582363 }
23592364 DeclareLetBindings :: No => { } // Caller is responsible for bindings.
2360- DeclareLetBindings :: LetNotPermitted => {
2361- self . tcx . dcx ( ) . span_bug ( expr_span, "let expression not expected in this context" )
2362- }
2365+ DeclareLetBindings :: LetNotPermitted => self
2366+ . tcx
2367+ . dcx ( )
2368+ . span_bug ( scrutinee_span, "let expression not expected in this context" ) ,
23632369 }
23642370
2365- let success = self . bind_pattern ( self . source_info ( pat. span ) , branch, & [ ] , expr_span, None ) ;
2371+ let true_block =
2372+ self . bind_pattern ( self . source_info ( pat. span ) , true_branch, & [ ] , scrutinee_span, None ) ;
23662373
23672374 // If branch coverage is enabled, record this branch.
2368- self . visit_coverage_conditional_let ( pat, success , built_tree . otherwise_block ) ;
2375+ self . visit_coverage_conditional_let ( pat, true_block , false_block ) ;
23692376
2370- success . unit ( )
2377+ true_block . unit ( )
23712378 }
23722379
23732380 /// Initializes each of the bindings from the candidate by
0 commit comments