@@ -35,42 +35,49 @@ use std::convert::TryFrom;
35
35
use std:: mem;
36
36
37
37
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
38
- pub ( crate ) fn then_else_blocks (
38
+ pub ( crate ) fn then_else_break (
39
39
& mut self ,
40
40
mut block : BasicBlock ,
41
41
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 < ( ) > {
45
46
let this = self ;
46
47
let expr_span = expr. span ;
47
48
48
49
match expr. kind {
49
50
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
+ } )
60
61
}
61
62
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)
64
64
}
65
65
_ => {
66
+ // TODO `as_temp`?
66
67
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) ) ;
68
70
let operand = Operand :: Move ( Place :: from ( place) ) ;
71
+
69
72
let then_block = this. cfg . start_new_block ( ) ;
70
73
let else_block = this. cfg . start_new_block ( ) ;
71
74
let term = TerminatorKind :: if_ ( this. tcx , operand, then_block, else_block) ;
75
+
76
+ let source_info = this. source_info ( expr_span) ;
72
77
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 ( )
74
81
}
75
82
}
76
83
}
@@ -302,6 +309,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
302
309
303
310
let arm_source_info = self . source_info ( arm. span ) ;
304
311
let arm_scope = ( arm. scope , arm_source_info) ;
312
+ let match_scope = self . local_scope ( ) ;
305
313
self . in_scope ( arm_scope, arm. lint_level , |this| {
306
314
// `try_upvars_resolved` may fail if it is unable to resolve the given
307
315
// `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -340,6 +348,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
340
348
scrutinee_span,
341
349
Some ( arm. span ) ,
342
350
Some ( arm. scope ) ,
351
+ Some ( match_scope) ,
343
352
) ;
344
353
345
354
if let Some ( source_scope) = scope {
@@ -384,6 +393,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
384
393
scrutinee_span : Span ,
385
394
arm_span : Option < Span > ,
386
395
arm_scope : Option < region:: Scope > ,
396
+ match_scope : Option < region:: Scope > ,
387
397
) -> BasicBlock {
388
398
if candidate. subcandidates . is_empty ( ) {
389
399
// Avoid generating another `BasicBlock` when we only have one
@@ -395,6 +405,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
395
405
fake_borrow_temps,
396
406
scrutinee_span,
397
407
arm_span,
408
+ match_scope,
398
409
true ,
399
410
)
400
411
} else {
@@ -431,6 +442,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
431
442
& fake_borrow_temps,
432
443
scrutinee_span,
433
444
arm_span,
445
+ match_scope,
434
446
schedule_drops,
435
447
) ;
436
448
if arm_scope. is_none ( ) {
@@ -616,6 +628,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
616
628
irrefutable_pat. span ,
617
629
None ,
618
630
None ,
631
+ None ,
619
632
)
620
633
. unit ( )
621
634
}
@@ -1742,13 +1755,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1742
1755
// Pat binding - used for `let` and function parameters as well.
1743
1756
1744
1757
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
1745
- pub fn lower_let (
1758
+ crate fn lower_let_else (
1746
1759
& mut self ,
1747
1760
mut block : BasicBlock ,
1748
1761
expr : & Expr < ' tcx > ,
1749
1762
pat : & Pat < ' tcx > ,
1763
+ else_target : region:: Scope ,
1750
1764
span : Span ,
1751
- ) -> ( BasicBlock , BasicBlock ) {
1765
+ ) -> BlockAnd < ( ) > {
1752
1766
let expr_span = expr. span ;
1753
1767
let expr_place_builder = unpack ! ( block = self . lower_scrutinee( block, expr, expr_span) ) ;
1754
1768
let mut guard_candidate = Candidate :: new ( expr_place_builder. clone ( ) , & pat, false ) ;
@@ -1769,6 +1783,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1769
1783
expr_place = expr_builder. into_place ( self . tcx , self . typeck_results ) ;
1770
1784
opt_expr_place = Some ( ( Some ( & expr_place) , expr_span) ) ;
1771
1785
}
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
+
1772
1789
self . declare_bindings ( None , pat. span . to ( span) , pat, ArmHasGuard ( false ) , opt_expr_place) ;
1773
1790
let post_guard_block = self . bind_pattern (
1774
1791
self . source_info ( pat. span ) ,
@@ -1778,9 +1795,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1778
1795
expr. span ,
1779
1796
None ,
1780
1797
None ,
1798
+ None ,
1781
1799
) ;
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 ( )
1784
1802
}
1785
1803
1786
1804
/// Initializes each of the bindings from the candidate by
@@ -1799,6 +1817,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1799
1817
fake_borrows : & Vec < ( Place < ' tcx > , Local ) > ,
1800
1818
scrutinee_span : Span ,
1801
1819
arm_span : Option < Span > ,
1820
+ match_scope : Option < region:: Scope > ,
1802
1821
schedule_drops : bool ,
1803
1822
) -> BasicBlock {
1804
1823
debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
@@ -1929,17 +1948,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1929
1948
self . cfg . push_assign ( block, scrutinee_source_info, Place :: from ( temp) , borrow) ;
1930
1949
}
1931
1950
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
+
1943
1970
let source_info = self . source_info ( guard_span) ;
1944
1971
let guard_end = self . source_info ( tcx. sess . source_map ( ) . end_point ( guard_span) ) ;
1945
1972
let guard_frame = self . guard_context . pop ( ) . unwrap ( ) ;
@@ -1955,10 +1982,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1955
1982
self . cfg . terminate ( unreachable, source_info, TerminatorKind :: Unreachable ) ;
1956
1983
unreachable
1957
1984
} ) ;
1958
- let outside_scope = self . cfg . start_new_block ( ) ;
1959
- self . exit_top_scope ( otherwise_post_guard_block, outside_scope, source_info) ;
1960
1985
self . false_edges (
1961
- outside_scope ,
1986
+ otherwise_post_guard_block ,
1962
1987
otherwise_block,
1963
1988
candidate. next_candidate_pre_binding_block ,
1964
1989
source_info,
0 commit comments