1
- // ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2
- // We want to be careful ^^'
3
-
4
1
//! Code related to match expressions. These are sufficiently complex to
5
2
//! warrant their own module and submodules. :) This main module includes the
6
3
//! high-level algorithm, the submodules contain the details.
@@ -100,7 +97,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
100
97
let scrutinee_place =
101
98
unpack ! ( block = self . lower_scrutinee( block, scrutinee, scrutinee_span, ) ) ;
102
99
103
- let mut arm_candidates = self . create_match_candidates ( scrutinee_place. clone ( ) , & arms) ;
100
+ let mut arm_candidates =
101
+ self . create_match_candidates ( scrutinee_place. clone ( ) , & arms. clone ( ) ) ;
104
102
105
103
let match_has_guard = arms. iter ( ) . any ( |arm| arm. guard . is_some ( ) ) ;
106
104
let mut candidates =
@@ -127,8 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127
125
scrutinee_span : Span ,
128
126
) -> BlockAnd < PlaceBuilder < ' tcx > > {
129
127
let scrutinee_place_builder = unpack ! ( block = self . as_place_builder( block, scrutinee) ) ;
130
- let scrutinee_place =
131
- scrutinee_place_builder. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
132
128
// Matching on a `scrutinee_place` with an uninhabited type doesn't
133
129
// generate any memory reads by itself, and so if the place "expression"
134
130
// contains unsafe operations like raw pointer dereferences or union
@@ -146,7 +142,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146
142
// check safety.
147
143
let cause_matched_place = FakeReadCause :: ForMatchedPlace ;
148
144
let source_info = self . source_info ( scrutinee_span) ;
149
- self . cfg . push_fake_read ( block, source_info, cause_matched_place, scrutinee_place) ;
145
+
146
+ if let Ok ( scrutinee_builder) =
147
+ scrutinee_place_builder. clone ( ) . try_upvars_resolved ( self . tcx , self . typeck_results )
148
+ {
149
+ let scrutinee_place =
150
+ scrutinee_builder. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
151
+ self . cfg . push_fake_read ( block, source_info, cause_matched_place, scrutinee_place) ;
152
+ }
150
153
151
154
block. and ( scrutinee_place_builder)
152
155
}
@@ -228,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
228
231
fn lower_match_arms (
229
232
& mut self ,
230
233
destination : Place < ' tcx > ,
231
- scrutinee_place : PlaceBuilder < ' tcx > ,
234
+ scrutinee_place_builder : PlaceBuilder < ' tcx > ,
232
235
scrutinee_span : Span ,
233
236
arm_candidates : Vec < ( & ' _ Arm < ' _ , ' tcx > , Candidate < ' _ , ' tcx > ) > ,
234
237
outer_source_info : SourceInfo ,
@@ -242,17 +245,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
242
245
let arm_source_info = self . source_info ( arm. span ) ;
243
246
let arm_scope = ( arm. scope , arm_source_info) ;
244
247
self . in_scope ( arm_scope, arm. lint_level , |this| {
248
+ let body = arm. body . clone ( ) ;
249
+ let mut opt_scrutinee_place: Option < ( Option < & Place < ' tcx > > , Span ) > = None ;
250
+ let scrutinee_place: Place < ' tcx > ;
251
+ if let Ok ( scrutinee_builder) = scrutinee_place_builder
252
+ . clone ( )
253
+ . try_upvars_resolved ( this. tcx , this. typeck_results )
254
+ {
255
+ scrutinee_place =
256
+ scrutinee_builder. clone ( ) . into_place ( this. tcx , this. typeck_results ) ;
257
+ opt_scrutinee_place = Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ;
258
+ }
245
259
let scope = this. declare_bindings (
246
260
None ,
247
261
arm. span ,
248
262
& arm. pattern ,
249
263
ArmHasGuard ( arm. guard . is_some ( ) ) ,
250
- Some ( (
251
- Some (
252
- & scrutinee_place. clone ( ) . into_place ( this. tcx , this. typeck_results ) ,
253
- ) ,
254
- scrutinee_span,
255
- ) ) ,
264
+ opt_scrutinee_place,
256
265
) ;
257
266
258
267
let arm_block = this. bind_pattern (
@@ -457,15 +466,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
457
466
}
458
467
459
468
_ => {
460
- // Converts the destruct pattern into a place
461
- //
462
- // We don't want to convert to a place right away
463
- // because in case of such pattern inside a closure, the projections matching a
464
- // captured place might have not been applied.
465
- // [FIXME] Need to find where this is happening and make the necessary changes there once
466
- // Candidate is modified
467
- //
468
- // We want to use a place builder; Maybe use `as_place_builder`
469
469
let place_builder = unpack ! ( block = self . as_place_builder( block, initializer) ) ;
470
470
self . place_into_pattern ( block, irrefutable_pat, place_builder, true )
471
471
}
@@ -479,12 +479,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
479
479
initializer : PlaceBuilder < ' tcx > ,
480
480
set_match_place : bool ,
481
481
) -> BlockAnd < ( ) > {
482
- let place = initializer. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
483
- let mut candidate = Candidate :: new ( initializer, & irrefutable_pat, false ) ;
484
-
482
+ let mut candidate = Candidate :: new ( initializer. clone ( ) , & irrefutable_pat, false ) ;
485
483
let fake_borrow_temps =
486
484
self . lower_match_tree ( block, irrefutable_pat. span , false , & mut [ & mut candidate] ) ;
487
-
488
485
// For matches and function arguments, the place that is being matched
489
486
// can be set when creating the variables. But the place for
490
487
// let PATTERN = ... might not even exist until we do the assignment.
@@ -499,7 +496,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
499
496
VarBindingForm { opt_match_place : Some ( ( ref mut match_place, _) ) , .. } ,
500
497
) ) ) ) = self . local_decls [ local] . local_info
501
498
{
502
- * match_place = Some ( place) ;
499
+ if let Ok ( match_pair_resolved) =
500
+ initializer. clone ( ) . try_upvars_resolved ( self . tcx , self . typeck_results )
501
+ {
502
+ let place = match_pair_resolved
503
+ . clone ( )
504
+ . into_place ( self . tcx , self . typeck_results ) ;
505
+ * match_place = Some ( place) ;
506
+ }
503
507
} else {
504
508
bug ! ( "Let binding to non-user variable." )
505
509
}
@@ -1461,7 +1465,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1461
1465
1462
1466
// Insert a Shallow borrow of any places that is switched on.
1463
1467
if let Some ( fb) = fake_borrows {
1464
- fb. insert ( match_place. clone ( ) . into_place ( self . tcx , self . typeck_results ) ) ;
1468
+ if let Ok ( match_place_resolved) =
1469
+ match_place. clone ( ) . try_upvars_resolved ( self . tcx , self . typeck_results )
1470
+ {
1471
+ let resolved_place =
1472
+ match_place_resolved. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
1473
+ fb. insert ( resolved_place) ;
1474
+ }
1465
1475
}
1466
1476
1467
1477
// perform the test, branching to one of N blocks. For each of
@@ -1776,28 +1786,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1776
1786
}
1777
1787
Guard :: IfLet ( pat, scrutinee) => {
1778
1788
let scrutinee_span = scrutinee. span ;
1779
- let scrutinee_place = unpack ! (
1789
+ let scrutinee_place_builder = unpack ! (
1780
1790
block = self . lower_scrutinee( block, scrutinee. clone( ) , scrutinee_span)
1781
1791
) ;
1782
- let mut guard_candidate = Candidate :: new ( scrutinee_place. clone ( ) , & pat, false ) ;
1792
+ let mut guard_candidate =
1793
+ Candidate :: new ( scrutinee_place_builder. clone ( ) , & pat, false ) ;
1783
1794
let wildcard = Pat :: wildcard_from_ty ( pat. ty ) ;
1784
1795
let mut otherwise_candidate =
1785
- Candidate :: new ( scrutinee_place . clone ( ) , & wildcard, false ) ;
1796
+ Candidate :: new ( scrutinee_place_builder . clone ( ) , & wildcard, false ) ;
1786
1797
let fake_borrow_temps = self . lower_match_tree (
1787
1798
block,
1788
1799
pat. span ,
1789
1800
false ,
1790
1801
& mut [ & mut guard_candidate, & mut otherwise_candidate] ,
1791
1802
) ;
1803
+ let mut opt_scrutinee_place: Option < ( Option < & Place < ' tcx > > , Span ) > = None ;
1804
+ let scrutinee_place: Place < ' tcx > ;
1805
+ if let Ok ( scrutinee_builder) = scrutinee_place_builder
1806
+ . clone ( )
1807
+ . try_upvars_resolved ( self . tcx , self . typeck_results )
1808
+ {
1809
+ scrutinee_place =
1810
+ scrutinee_builder. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
1811
+ opt_scrutinee_place = Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ;
1812
+ }
1792
1813
self . declare_bindings (
1793
1814
None ,
1794
1815
pat. span . to ( arm_span. unwrap ( ) ) ,
1795
1816
pat,
1796
1817
ArmHasGuard ( false ) ,
1797
- Some ( (
1798
- Some ( & scrutinee_place. clone ( ) . into_place ( tcx, self . typeck_results ) ) ,
1799
- scrutinee. span ,
1800
- ) ) ,
1818
+ opt_scrutinee_place,
1801
1819
) ;
1802
1820
let post_guard_block = self . bind_pattern (
1803
1821
self . source_info ( pat. span ) ,
0 commit comments