1- // ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2- // We want to be careful ^^'
3-
41//! Code related to match expressions. These are sufficiently complex to
52//! warrant their own module and submodules. :) This main module includes the
63//! high-level algorithm, the submodules contain the details.
@@ -100,7 +97,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10097 let scrutinee_place =
10198 unpack ! ( block = self . lower_scrutinee( block, scrutinee, scrutinee_span, ) ) ;
10299
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 ( ) ) ;
104102
105103 let match_has_guard = arms. iter ( ) . any ( |arm| arm. guard . is_some ( ) ) ;
106104 let mut candidates =
@@ -127,8 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127125 scrutinee_span : Span ,
128126 ) -> BlockAnd < PlaceBuilder < ' tcx > > {
129127 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 ) ;
132128 // Matching on a `scrutinee_place` with an uninhabited type doesn't
133129 // generate any memory reads by itself, and so if the place "expression"
134130 // contains unsafe operations like raw pointer dereferences or union
@@ -146,7 +142,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146142 // check safety.
147143 let cause_matched_place = FakeReadCause :: ForMatchedPlace ;
148144 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+ }
150153
151154 block. and ( scrutinee_place_builder)
152155 }
@@ -228,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
228231 fn lower_match_arms (
229232 & mut self ,
230233 destination : Place < ' tcx > ,
231- scrutinee_place : PlaceBuilder < ' tcx > ,
234+ scrutinee_place_builder : PlaceBuilder < ' tcx > ,
232235 scrutinee_span : Span ,
233236 arm_candidates : Vec < ( & ' _ Arm < ' _ , ' tcx > , Candidate < ' _ , ' tcx > ) > ,
234237 outer_source_info : SourceInfo ,
@@ -242,17 +245,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
242245 let arm_source_info = self . source_info ( arm. span ) ;
243246 let arm_scope = ( arm. scope , arm_source_info) ;
244247 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+ }
245259 let scope = this. declare_bindings (
246260 None ,
247261 arm. span ,
248262 & arm. pattern ,
249263 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,
256265 ) ;
257266
258267 let arm_block = this. bind_pattern (
@@ -457,15 +466,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
457466 }
458467
459468 _ => {
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`
469469 let place_builder = unpack ! ( block = self . as_place_builder( block, initializer) ) ;
470470 self . place_into_pattern ( block, irrefutable_pat, place_builder, true )
471471 }
@@ -479,12 +479,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
479479 initializer : PlaceBuilder < ' tcx > ,
480480 set_match_place : bool ,
481481 ) -> 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 ) ;
485483 let fake_borrow_temps =
486484 self . lower_match_tree ( block, irrefutable_pat. span , false , & mut [ & mut candidate] ) ;
487-
488485 // For matches and function arguments, the place that is being matched
489486 // can be set when creating the variables. But the place for
490487 // let PATTERN = ... might not even exist until we do the assignment.
@@ -499,7 +496,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
499496 VarBindingForm { opt_match_place : Some ( ( ref mut match_place, _) ) , .. } ,
500497 ) ) ) ) = self . local_decls [ local] . local_info
501498 {
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+ }
503507 } else {
504508 bug ! ( "Let binding to non-user variable." )
505509 }
@@ -1461,7 +1465,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14611465
14621466 // Insert a Shallow borrow of any places that is switched on.
14631467 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+ }
14651475 }
14661476
14671477 // perform the test, branching to one of N blocks. For each of
@@ -1776,28 +1786,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17761786 }
17771787 Guard :: IfLet ( pat, scrutinee) => {
17781788 let scrutinee_span = scrutinee. span ;
1779- let scrutinee_place = unpack ! (
1789+ let scrutinee_place_builder = unpack ! (
17801790 block = self . lower_scrutinee( block, scrutinee. clone( ) , scrutinee_span)
17811791 ) ;
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 ) ;
17831794 let wildcard = Pat :: wildcard_from_ty ( pat. ty ) ;
17841795 let mut otherwise_candidate =
1785- Candidate :: new ( scrutinee_place . clone ( ) , & wildcard, false ) ;
1796+ Candidate :: new ( scrutinee_place_builder . clone ( ) , & wildcard, false ) ;
17861797 let fake_borrow_temps = self . lower_match_tree (
17871798 block,
17881799 pat. span ,
17891800 false ,
17901801 & mut [ & mut guard_candidate, & mut otherwise_candidate] ,
17911802 ) ;
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+ }
17921813 self . declare_bindings (
17931814 None ,
17941815 pat. span . to ( arm_span. unwrap ( ) ) ,
17951816 pat,
17961817 ArmHasGuard ( false ) ,
1797- Some ( (
1798- Some ( & scrutinee_place. clone ( ) . into_place ( tcx, self . typeck_results ) ) ,
1799- scrutinee. span ,
1800- ) ) ,
1818+ opt_scrutinee_place,
18011819 ) ;
18021820 let post_guard_block = self . bind_pattern (
18031821 self . source_info ( pat. span ) ,
0 commit comments