1+ // ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2+ // We want to be careful ^^'
3+
14//! Code related to match expressions. These are sufficiently complex to
25//! warrant their own module and submodules. :) This main module includes the
36//! high-level algorithm, the submodules contain the details.
47//!
58//! This also includes code for pattern bindings in `let` statements and
69//! function parameters.
710
11+ use crate :: build:: expr:: as_place:: PlaceBuilder ;
812use crate :: build:: scope:: DropKind ;
913use crate :: build:: ForGuard :: { self , OutsideGuard , RefWithinGuard } ;
1014use crate :: build:: { BlockAnd , BlockAndExtension , Builder } ;
@@ -96,7 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
96100 let scrutinee_place =
97101 unpack ! ( block = self . lower_scrutinee( block, scrutinee, scrutinee_span, ) ) ;
98102
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) ;
100104
101105 let match_has_guard = arms. iter ( ) . any ( |arm| arm. guard . is_some ( ) ) ;
102106 let mut candidates =
@@ -121,8 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
121125 mut block : BasicBlock ,
122126 scrutinee : & Expr < ' _ , ' tcx > ,
123127 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 ) ;
126132 // Matching on a `scrutinee_place` with an uninhabited type doesn't
127133 // generate any memory reads by itself, and so if the place "expression"
128134 // contains unsafe operations like raw pointer dereferences or union
@@ -142,21 +148,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142148 let source_info = self . source_info ( scrutinee_span) ;
143149 self . cfg . push_fake_read ( block, source_info, cause_matched_place, scrutinee_place) ;
144150
145- block. and ( scrutinee_place )
151+ block. and ( scrutinee_place_builder )
146152 }
147153
148154 /// Create the initial `Candidate`s for a `match` expression.
149155 fn create_match_candidates < ' pat > (
150156 & mut self ,
151- scrutinee : Place < ' tcx > ,
157+ scrutinee : PlaceBuilder < ' tcx > ,
152158 arms : & ' pat [ Arm < ' pat , ' tcx > ] ,
153159 ) -> Vec < ( & ' pat Arm < ' pat , ' tcx > , Candidate < ' pat , ' tcx > ) > {
154160 // Assemble a list of candidates: there is one candidate per pattern,
155161 // which means there may be more than one candidate *per arm*.
156162 arms. iter ( )
157163 . map ( |arm| {
158164 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) ;
160166 ( arm, arm_candidate)
161167 } )
162168 . collect ( )
@@ -222,7 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
222228 fn lower_match_arms (
223229 & mut self ,
224230 destination : Place < ' tcx > ,
225- scrutinee_place : Place < ' tcx > ,
231+ scrutinee_place : PlaceBuilder < ' tcx > ,
226232 scrutinee_span : Span ,
227233 arm_candidates : Vec < ( & ' _ Arm < ' _ , ' tcx > , Candidate < ' _ , ' tcx > ) > ,
228234 outer_source_info : SourceInfo ,
@@ -241,7 +247,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
241247 arm. span ,
242248 & arm. pattern ,
243249 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+ ) ) ,
245256 ) ;
246257
247258 let arm_block = this. bind_pattern (
@@ -446,8 +457,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
446457 }
447458
448459 _ => {
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 )
451471 }
452472 }
453473 }
@@ -456,9 +476,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
456476 & mut self ,
457477 block : BasicBlock ,
458478 irrefutable_pat : Pat < ' tcx > ,
459- initializer : Place < ' tcx > ,
479+ initializer : PlaceBuilder < ' tcx > ,
460480 set_match_place : bool ,
461481 ) -> BlockAnd < ( ) > {
482+ let place = initializer. clone ( ) . into_place ( self . tcx , self . typeck_results ) ;
462483 let mut candidate = Candidate :: new ( initializer, & irrefutable_pat, false ) ;
463484
464485 let fake_borrow_temps =
@@ -478,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
478499 VarBindingForm { opt_match_place : Some ( ( ref mut match_place, _) ) , .. } ,
479500 ) ) ) ) = self . local_decls [ local] . local_info
480501 {
481- * match_place = Some ( initializer ) ;
502+ * match_place = Some ( place ) ;
482503 } else {
483504 bug ! ( "Let binding to non-user variable." )
484505 }
@@ -717,7 +738,7 @@ struct Candidate<'pat, 'tcx> {
717738}
718739
719740impl < ' 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 {
721742 Candidate {
722743 span : pattern. span ,
723744 has_guard,
@@ -791,7 +812,7 @@ struct Ascription<'tcx> {
791812#[ derive( Clone , Debug ) ]
792813crate struct MatchPair < ' pat , ' tcx > {
793814 // this place...
794- place : Place < ' tcx > ,
815+ place : PlaceBuilder < ' tcx > ,
795816
796817 // ... must match this pattern.
797818 pattern : & ' pat Pat < ' tcx > ,
@@ -1198,7 +1219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11981219 & mut otherwise,
11991220 pats,
12001221 or_span,
1201- place,
1222+ place. clone ( ) ,
12021223 fake_borrows,
12031224 ) ;
12041225 } ) ;
@@ -1224,12 +1245,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12241245 otherwise : & mut Option < BasicBlock > ,
12251246 pats : & ' pat [ Pat < ' tcx > ] ,
12261247 or_span : Span ,
1227- place : Place < ' tcx > ,
1248+ place : PlaceBuilder < ' tcx > ,
12281249 fake_borrows : & mut Option < FxHashSet < Place < ' tcx > > > ,
12291250 ) {
12301251 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 ( ) ;
12331256 let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
12341257 let otherwise = if candidate. otherwise_block . is_some ( ) {
12351258 & mut candidate. otherwise_block
@@ -1412,7 +1435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14121435 // extract the match-pair from the highest priority candidate
14131436 let match_pair = & candidates. first ( ) . unwrap ( ) . match_pairs [ 0 ] ;
14141437 let mut test = self . test ( match_pair) ;
1415- let match_place = match_pair. place ;
1438+ let match_place = match_pair. place . clone ( ) ;
14161439
14171440 // most of the time, the test to perform is simply a function
14181441 // of the main candidate; but for a test like SwitchInt, we
@@ -1428,7 +1451,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14281451 }
14291452 TestKind :: Switch { adt_def : _, ref mut variants } => {
14301453 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) {
14321455 break ;
14331456 }
14341457 }
@@ -1438,7 +1461,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14381461
14391462 // Insert a Shallow borrow of any places that is switched on.
14401463 if let Some ( fb) = fake_borrows {
1441- fb. insert ( match_place) ;
1464+ fb. insert ( match_place. clone ( ) . into_place ( self . tcx , self . typeck_results ) ) ;
14421465 }
14431466
14441467 // perform the test, branching to one of N blocks. For each of
@@ -1456,7 +1479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14561479 // encounter a candidate where the test is not relevant; at
14571480 // that point, we stop sorting.
14581481 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) {
14601483 let ( candidate, rest) = candidates. split_first_mut ( ) . unwrap ( ) ;
14611484 target_candidates[ idx] . push ( candidate) ;
14621485 candidates = rest;
@@ -1519,7 +1542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15191542 target_blocks
15201543 } ;
15211544
1522- self . perform_test ( block, match_place, & test, make_target_blocks) ;
1545+ self . perform_test ( block, match_place. clone ( ) , & test, make_target_blocks) ;
15231546 }
15241547
15251548 /// Determine the fake borrows that are needed from a set of places that
@@ -1753,11 +1776,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17531776 }
17541777 Guard :: IfLet ( pat, scrutinee) => {
17551778 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 ) ;
17591783 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 ) ;
17611786 let fake_borrow_temps = self . lower_match_tree (
17621787 block,
17631788 pat. span ,
@@ -1769,7 +1794,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17691794 pat. span . to ( arm_span. unwrap ( ) ) ,
17701795 pat,
17711796 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+ ) ) ,
17731801 ) ;
17741802 let post_guard_block = self . bind_pattern (
17751803 self . source_info ( pat. span ) ,
0 commit comments