1
+ // ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2
+ // We want to be careful ^^'
3
+
1
4
//! Code related to match expressions. These are sufficiently complex to
2
5
//! warrant their own module and submodules. :) This main module includes the
3
6
//! high-level algorithm, the submodules contain the details.
4
7
//!
5
8
//! This also includes code for pattern bindings in `let` statements and
6
9
//! function parameters.
7
10
11
+ use crate :: build:: expr:: as_place:: PlaceBuilder ;
8
12
use crate :: build:: scope:: DropKind ;
9
13
use crate :: build:: ForGuard :: { self , OutsideGuard , RefWithinGuard } ;
10
14
use crate :: build:: { BlockAnd , BlockAndExtension , Builder } ;
@@ -96,7 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
96
100
let scrutinee_place =
97
101
unpack ! ( block = self . lower_scrutinee( block, scrutinee, scrutinee_span, ) ) ;
98
102
99
- let mut arm_candidates = self . create_match_candidates ( scrutinee_place, & arms) ;
103
+ let mut arm_candidates = self . create_match_candidates ( scrutinee_place. clone ( ) , & arms) ;
100
104
101
105
let match_has_guard = arms. iter ( ) . any ( |arm| arm. guard . is_some ( ) ) ;
102
106
let mut candidates =
@@ -121,8 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
121
125
mut block : BasicBlock ,
122
126
scrutinee : & Expr < ' _ , ' tcx > ,
123
127
scrutinee_span : Span ,
124
- ) -> BlockAnd < Place < ' tcx > > {
125
- let scrutinee_place = unpack ! ( block = self . as_place( block, scrutinee) ) ;
128
+ ) -> BlockAnd < PlaceBuilder < ' tcx > > {
129
+ 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 ) ;
126
132
// Matching on a `scrutinee_place` with an uninhabited type doesn't
127
133
// generate any memory reads by itself, and so if the place "expression"
128
134
// contains unsafe operations like raw pointer dereferences or union
@@ -142,21 +148,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142
148
let source_info = self . source_info ( scrutinee_span) ;
143
149
self . cfg . push_fake_read ( block, source_info, cause_matched_place, scrutinee_place) ;
144
150
145
- block. and ( scrutinee_place )
151
+ block. and ( scrutinee_place_builder )
146
152
}
147
153
148
154
/// Create the initial `Candidate`s for a `match` expression.
149
155
fn create_match_candidates < ' pat > (
150
156
& mut self ,
151
- scrutinee : Place < ' tcx > ,
157
+ scrutinee : PlaceBuilder < ' tcx > ,
152
158
arms : & ' pat [ Arm < ' pat , ' tcx > ] ,
153
159
) -> Vec < ( & ' pat Arm < ' pat , ' tcx > , Candidate < ' pat , ' tcx > ) > {
154
160
// Assemble a list of candidates: there is one candidate per pattern,
155
161
// which means there may be more than one candidate *per arm*.
156
162
arms. iter ( )
157
163
. map ( |arm| {
158
164
let arm_has_guard = arm. guard . is_some ( ) ;
159
- let arm_candidate = Candidate :: new ( scrutinee, & arm. pattern , arm_has_guard) ;
165
+ let arm_candidate = Candidate :: new ( scrutinee. clone ( ) , & arm. pattern , arm_has_guard) ;
160
166
( arm, arm_candidate)
161
167
} )
162
168
. collect ( )
@@ -222,7 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
222
228
fn lower_match_arms (
223
229
& mut self ,
224
230
destination : Place < ' tcx > ,
225
- scrutinee_place : Place < ' tcx > ,
231
+ scrutinee_place : PlaceBuilder < ' tcx > ,
226
232
scrutinee_span : Span ,
227
233
arm_candidates : Vec < ( & ' _ Arm < ' _ , ' tcx > , Candidate < ' _ , ' tcx > ) > ,
228
234
outer_source_info : SourceInfo ,
@@ -241,7 +247,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
241
247
arm. span ,
242
248
& arm. pattern ,
243
249
ArmHasGuard ( arm. guard . is_some ( ) ) ,
244
- Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ,
250
+ Some ( (
251
+ Some (
252
+ & scrutinee_place. clone ( ) . into_place ( this. tcx , this. typeck_results ) ,
253
+ ) ,
254
+ scrutinee_span,
255
+ ) ) ,
245
256
) ;
246
257
247
258
let arm_block = this. bind_pattern (
@@ -446,8 +457,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
446
457
}
447
458
448
459
_ => {
449
- let place = unpack ! ( block = self . as_place( block, initializer) ) ;
450
- self . place_into_pattern ( block, irrefutable_pat, place, true )
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
+ let place_builder = unpack ! ( block = self . as_place_builder( block, initializer) ) ;
470
+ self . place_into_pattern ( block, irrefutable_pat, place_builder, true )
451
471
}
452
472
}
453
473
}
@@ -456,9 +476,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
456
476
& mut self ,
457
477
block : BasicBlock ,
458
478
irrefutable_pat : Pat < ' tcx > ,
459
- initializer : Place < ' tcx > ,
479
+ initializer : PlaceBuilder < ' tcx > ,
460
480
set_match_place : bool ,
461
481
) -> BlockAnd < ( ) > {
482
+ let place = initializer. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
462
483
let mut candidate = Candidate :: new ( initializer, & irrefutable_pat, false ) ;
463
484
464
485
let fake_borrow_temps =
@@ -478,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
478
499
VarBindingForm { opt_match_place : Some ( ( ref mut match_place, _) ) , .. } ,
479
500
) ) ) ) = self . local_decls [ local] . local_info
480
501
{
481
- * match_place = Some ( initializer ) ;
502
+ * match_place = Some ( place ) ;
482
503
} else {
483
504
bug ! ( "Let binding to non-user variable." )
484
505
}
@@ -717,7 +738,7 @@ struct Candidate<'pat, 'tcx> {
717
738
}
718
739
719
740
impl < ' tcx , ' pat > Candidate < ' pat , ' tcx > {
720
- fn new ( place : Place < ' tcx > , pattern : & ' pat Pat < ' tcx > , has_guard : bool ) -> Self {
741
+ fn new ( place : PlaceBuilder < ' tcx > , pattern : & ' pat Pat < ' tcx > , has_guard : bool ) -> Self {
721
742
Candidate {
722
743
span : pattern. span ,
723
744
has_guard,
@@ -791,7 +812,7 @@ struct Ascription<'tcx> {
791
812
#[ derive( Clone , Debug ) ]
792
813
crate struct MatchPair < ' pat , ' tcx > {
793
814
// this place...
794
- place : Place < ' tcx > ,
815
+ place : PlaceBuilder < ' tcx > ,
795
816
796
817
// ... must match this pattern.
797
818
pattern : & ' pat Pat < ' tcx > ,
@@ -1198,7 +1219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1198
1219
& mut otherwise,
1199
1220
pats,
1200
1221
or_span,
1201
- place,
1222
+ place. clone ( ) ,
1202
1223
fake_borrows,
1203
1224
) ;
1204
1225
} ) ;
@@ -1224,12 +1245,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1224
1245
otherwise : & mut Option < BasicBlock > ,
1225
1246
pats : & ' pat [ Pat < ' tcx > ] ,
1226
1247
or_span : Span ,
1227
- place : Place < ' tcx > ,
1248
+ place : PlaceBuilder < ' tcx > ,
1228
1249
fake_borrows : & mut Option < FxHashSet < Place < ' tcx > > > ,
1229
1250
) {
1230
1251
debug ! ( "test_or_pattern:\n candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1231
- let mut or_candidates: Vec < _ > =
1232
- pats. iter ( ) . map ( |pat| Candidate :: new ( place, pat, candidate. has_guard ) ) . collect ( ) ;
1252
+ let mut or_candidates: Vec < _ > = pats
1253
+ . iter ( )
1254
+ . map ( |pat| Candidate :: new ( place. clone ( ) , pat, candidate. has_guard ) )
1255
+ . collect ( ) ;
1233
1256
let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1234
1257
let otherwise = if candidate. otherwise_block . is_some ( ) {
1235
1258
& mut candidate. otherwise_block
@@ -1412,7 +1435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1412
1435
// extract the match-pair from the highest priority candidate
1413
1436
let match_pair = & candidates. first ( ) . unwrap ( ) . match_pairs [ 0 ] ;
1414
1437
let mut test = self . test ( match_pair) ;
1415
- let match_place = match_pair. place ;
1438
+ let match_place = match_pair. place . clone ( ) ;
1416
1439
1417
1440
// most of the time, the test to perform is simply a function
1418
1441
// of the main candidate; but for a test like SwitchInt, we
@@ -1428,7 +1451,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1428
1451
}
1429
1452
TestKind :: Switch { adt_def : _, ref mut variants } => {
1430
1453
for candidate in candidates. iter ( ) {
1431
- if !self . add_variants_to_switch ( & match_place, candidate, variants) {
1454
+ if !self . add_variants_to_switch ( & match_place. clone ( ) , candidate, variants) {
1432
1455
break ;
1433
1456
}
1434
1457
}
@@ -1438,7 +1461,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1438
1461
1439
1462
// Insert a Shallow borrow of any places that is switched on.
1440
1463
if let Some ( fb) = fake_borrows {
1441
- fb. insert ( match_place) ;
1464
+ fb. insert ( match_place. clone ( ) . into_place ( self . tcx , self . typeck_results ) ) ;
1442
1465
}
1443
1466
1444
1467
// perform the test, branching to one of N blocks. For each of
@@ -1456,7 +1479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1456
1479
// encounter a candidate where the test is not relevant; at
1457
1480
// that point, we stop sorting.
1458
1481
while let Some ( candidate) = candidates. first_mut ( ) {
1459
- if let Some ( idx) = self . sort_candidate ( & match_place, & test, candidate) {
1482
+ if let Some ( idx) = self . sort_candidate ( & match_place. clone ( ) , & test, candidate) {
1460
1483
let ( candidate, rest) = candidates. split_first_mut ( ) . unwrap ( ) ;
1461
1484
target_candidates[ idx] . push ( candidate) ;
1462
1485
candidates = rest;
@@ -1519,7 +1542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1519
1542
target_blocks
1520
1543
} ;
1521
1544
1522
- self . perform_test ( block, match_place, & test, make_target_blocks) ;
1545
+ self . perform_test ( block, match_place. clone ( ) , & test, make_target_blocks) ;
1523
1546
}
1524
1547
1525
1548
/// Determine the fake borrows that are needed from a set of places that
@@ -1753,11 +1776,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1753
1776
}
1754
1777
Guard :: IfLet ( pat, scrutinee) => {
1755
1778
let scrutinee_span = scrutinee. span ;
1756
- let scrutinee_place =
1757
- unpack ! ( block = self . lower_scrutinee( block, scrutinee, scrutinee_span) ) ;
1758
- let mut guard_candidate = Candidate :: new ( scrutinee_place, & pat, false ) ;
1779
+ let scrutinee_place = unpack ! (
1780
+ block = self . lower_scrutinee( block, scrutinee. clone( ) , scrutinee_span)
1781
+ ) ;
1782
+ let mut guard_candidate = Candidate :: new ( scrutinee_place. clone ( ) , & pat, false ) ;
1759
1783
let wildcard = Pat :: wildcard_from_ty ( pat. ty ) ;
1760
- let mut otherwise_candidate = Candidate :: new ( scrutinee_place, & wildcard, false ) ;
1784
+ let mut otherwise_candidate =
1785
+ Candidate :: new ( scrutinee_place. clone ( ) , & wildcard, false ) ;
1761
1786
let fake_borrow_temps = self . lower_match_tree (
1762
1787
block,
1763
1788
pat. span ,
@@ -1769,7 +1794,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1769
1794
pat. span . to ( arm_span. unwrap ( ) ) ,
1770
1795
pat,
1771
1796
ArmHasGuard ( false ) ,
1772
- Some ( ( Some ( & scrutinee_place) , scrutinee. span ) ) ,
1797
+ Some ( (
1798
+ Some ( & scrutinee_place. clone ( ) . into_place ( tcx, self . typeck_results ) ) ,
1799
+ scrutinee. span ,
1800
+ ) ) ,
1773
1801
) ;
1774
1802
let post_guard_block = self . bind_pattern (
1775
1803
self . source_info ( pat. span ) ,
0 commit comments