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