@@ -35,42 +35,49 @@ use std::convert::TryFrom;
3535use std:: mem;
3636
3737impl < ' a , ' tcx > Builder < ' a , ' tcx > {
38- pub ( crate ) fn then_else_blocks (
38+ pub ( crate ) fn then_else_break (
3939 & mut self ,
4040 mut block : BasicBlock ,
4141 expr : & Expr < ' tcx > ,
42- scope : region:: Scope ,
43- source_info : SourceInfo ,
44- ) -> ( BasicBlock , BasicBlock ) {
42+ temp_scope : region:: Scope ,
43+ break_scope : region:: Scope ,
44+ variable_scope_span : Span ,
45+ ) -> BlockAnd < ( ) > {
4546 let this = self ;
4647 let expr_span = expr. span ;
4748
4849 match expr. kind {
4950 ExprKind :: Scope { region_scope, lint_level, value } => {
50- let region_scope = ( region_scope, source_info) ;
51- let then_block ;
52- let else_block = unpack ! (
53- then_block = this . in_scope ( region_scope , lint_level , |this| {
54- let ( then_block , else_block ) =
55- this . then_else_blocks ( block , & this . thir [ value ] , scope , source_info ) ;
56- then_block . and ( else_block )
57- } )
58- ) ;
59- ( then_block , else_block )
51+ let region_scope = ( region_scope, this . source_info ( expr_span ) ) ;
52+ this . in_scope ( region_scope , lint_level , |this| {
53+ this . then_else_break (
54+ block ,
55+ & this . thir [ value ] ,
56+ temp_scope ,
57+ break_scope ,
58+ variable_scope_span ,
59+ )
60+ } )
6061 }
6162 ExprKind :: Let { expr, ref pat } => {
62- // FIXME: Use correct span.
63- this. lower_let ( block, & this. thir [ expr] , pat, expr_span)
63+ this. lower_let_else ( block, & this. thir [ expr] , pat, break_scope, variable_scope_span)
6464 }
6565 _ => {
66+ // TODO `as_temp`?
6667 let mutability = Mutability :: Mut ;
67- let place = unpack ! ( block = this. as_temp( block, Some ( scope) , expr, mutability) ) ;
68+ let place =
69+ unpack ! ( block = this. as_temp( block, Some ( temp_scope) , expr, mutability) ) ;
6870 let operand = Operand :: Move ( Place :: from ( place) ) ;
71+
6972 let then_block = this. cfg . start_new_block ( ) ;
7073 let else_block = this. cfg . start_new_block ( ) ;
7174 let term = TerminatorKind :: if_ ( this. tcx , operand, then_block, else_block) ;
75+
76+ let source_info = this. source_info ( expr_span) ;
7277 this. cfg . terminate ( block, source_info, term) ;
73- ( then_block, else_block)
78+ this. break_for_else ( else_block, break_scope, source_info) ;
79+
80+ then_block. unit ( )
7481 }
7582 }
7683 }
@@ -302,6 +309,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
302309
303310 let arm_source_info = self . source_info ( arm. span ) ;
304311 let arm_scope = ( arm. scope , arm_source_info) ;
312+ let match_scope = self . local_scope ( ) ;
305313 self . in_scope ( arm_scope, arm. lint_level , |this| {
306314 // `try_upvars_resolved` may fail if it is unable to resolve the given
307315 // `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -340,6 +348,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
340348 scrutinee_span,
341349 Some ( arm. span ) ,
342350 Some ( arm. scope ) ,
351+ Some ( match_scope) ,
343352 ) ;
344353
345354 if let Some ( source_scope) = scope {
@@ -384,6 +393,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
384393 scrutinee_span : Span ,
385394 arm_span : Option < Span > ,
386395 arm_scope : Option < region:: Scope > ,
396+ match_scope : Option < region:: Scope > ,
387397 ) -> BasicBlock {
388398 if candidate. subcandidates . is_empty ( ) {
389399 // Avoid generating another `BasicBlock` when we only have one
@@ -395,6 +405,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
395405 fake_borrow_temps,
396406 scrutinee_span,
397407 arm_span,
408+ match_scope,
398409 true ,
399410 )
400411 } else {
@@ -431,6 +442,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
431442 & fake_borrow_temps,
432443 scrutinee_span,
433444 arm_span,
445+ match_scope,
434446 schedule_drops,
435447 ) ;
436448 if arm_scope. is_none ( ) {
@@ -616,6 +628,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
616628 irrefutable_pat. span ,
617629 None ,
618630 None ,
631+ None ,
619632 )
620633 . unit ( )
621634 }
@@ -1742,13 +1755,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17421755// Pat binding - used for `let` and function parameters as well.
17431756
17441757impl < ' a , ' tcx > Builder < ' a , ' tcx > {
1745- pub fn lower_let (
1758+ crate fn lower_let_else (
17461759 & mut self ,
17471760 mut block : BasicBlock ,
17481761 expr : & Expr < ' tcx > ,
17491762 pat : & Pat < ' tcx > ,
1763+ else_target : region:: Scope ,
17501764 span : Span ,
1751- ) -> ( BasicBlock , BasicBlock ) {
1765+ ) -> BlockAnd < ( ) > {
17521766 let expr_span = expr. span ;
17531767 let expr_place_builder = unpack ! ( block = self . lower_scrutinee( block, expr, expr_span) ) ;
17541768 let mut guard_candidate = Candidate :: new ( expr_place_builder. clone ( ) , & pat, false ) ;
@@ -1769,6 +1783,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17691783 expr_place = expr_builder. into_place ( self . tcx , self . typeck_results ) ;
17701784 opt_expr_place = Some ( ( Some ( & expr_place) , expr_span) ) ;
17711785 }
1786+ let otherwise_post_guard_block = otherwise_candidate. pre_binding_block . unwrap ( ) ;
1787+ self . break_for_else ( otherwise_post_guard_block, else_target, self . source_info ( expr_span) ) ;
1788+
17721789 self . declare_bindings ( None , pat. span . to ( span) , pat, ArmHasGuard ( false ) , opt_expr_place) ;
17731790 let post_guard_block = self . bind_pattern (
17741791 self . source_info ( pat. span ) ,
@@ -1778,9 +1795,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17781795 expr. span ,
17791796 None ,
17801797 None ,
1798+ None ,
17811799 ) ;
1782- let otherwise_post_guard_block = otherwise_candidate . pre_binding_block . unwrap ( ) ;
1783- ( post_guard_block, otherwise_post_guard_block )
1800+
1801+ post_guard_block. unit ( )
17841802 }
17851803
17861804 /// Initializes each of the bindings from the candidate by
@@ -1799,6 +1817,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17991817 fake_borrows : & Vec < ( Place < ' tcx > , Local ) > ,
18001818 scrutinee_span : Span ,
18011819 arm_span : Option < Span > ,
1820+ match_scope : Option < region:: Scope > ,
18021821 schedule_drops : bool ,
18031822 ) -> BasicBlock {
18041823 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
@@ -1929,17 +1948,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19291948 self . cfg . push_assign ( block, scrutinee_source_info, Place :: from ( temp) , borrow) ;
19301949 }
19311950
1932- let ( guard_span, ( post_guard_block, otherwise_post_guard_block) ) = match * guard {
1933- Guard :: If ( e) => {
1934- let e = & self . thir [ e] ;
1935- let source_info = self . source_info ( e. span ) ;
1936- ( e. span , self . test_bool ( block, e, source_info) )
1937- }
1938- Guard :: IfLet ( ref pat, scrutinee) => {
1939- let s = & self . thir [ scrutinee] ;
1940- ( s. span , self . lower_let ( block, s, pat, arm_span. unwrap ( ) ) )
1941- }
1942- } ;
1951+ let arm_span = arm_span. unwrap ( ) ;
1952+ let arm_scope = self . local_scope ( ) ;
1953+ let match_scope = match_scope. unwrap ( ) ;
1954+ let mut guard_span = rustc_span:: DUMMY_SP ;
1955+
1956+ let ( post_guard_block, otherwise_post_guard_block) =
1957+ self . in_if_then_scope ( match_scope, |this| match * guard {
1958+ Guard :: If ( e) => {
1959+ let e = & this. thir [ e] ;
1960+ guard_span = e. span ;
1961+ this. then_else_break ( block, e, arm_scope, match_scope, arm_span)
1962+ }
1963+ Guard :: IfLet ( ref pat, scrutinee) => {
1964+ let s = & this. thir [ scrutinee] ;
1965+ guard_span = s. span ;
1966+ this. lower_let_else ( block, s, pat, match_scope, arm_span)
1967+ }
1968+ } ) ;
1969+
19431970 let source_info = self . source_info ( guard_span) ;
19441971 let guard_end = self . source_info ( tcx. sess . source_map ( ) . end_point ( guard_span) ) ;
19451972 let guard_frame = self . guard_context . pop ( ) . unwrap ( ) ;
@@ -1955,10 +1982,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19551982 self . cfg . terminate ( unreachable, source_info, TerminatorKind :: Unreachable ) ;
19561983 unreachable
19571984 } ) ;
1958- let outside_scope = self . cfg . start_new_block ( ) ;
1959- self . exit_top_scope ( otherwise_post_guard_block, outside_scope, source_info) ;
19601985 self . false_edges (
1961- outside_scope ,
1986+ otherwise_post_guard_block ,
19621987 otherwise_block,
19631988 candidate. next_candidate_pre_binding_block ,
19641989 source_info,
0 commit comments