@@ -96,11 +96,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9696 let mut arm_candidates = self . create_match_candidates ( & scrutinee_place, & arms) ;
9797
9898 let match_has_guard = arms. iter ( ) . any ( |arm| arm. guard . is_some ( ) ) ;
99- let candidates =
99+ let mut candidates =
100100 arm_candidates. iter_mut ( ) . map ( |( _, candidate) | candidate) . collect :: < Vec < _ > > ( ) ;
101101
102102 let fake_borrow_temps =
103- self . lower_match_tree ( block, scrutinee_span, match_has_guard, candidates) ;
103+ self . lower_match_tree ( block, scrutinee_span, match_has_guard, & mut candidates) ;
104104
105105 self . lower_match_arms (
106106 & destination,
@@ -181,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
181181 block : BasicBlock ,
182182 scrutinee_span : Span ,
183183 match_has_guard : bool ,
184- mut candidates : Vec < & mut Candidate < ' pat , ' tcx > > ,
184+ candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
185185 ) -> Vec < ( Place < ' tcx > , Local ) > {
186186 // The set of places that we are creating fake borrows of. If there are
187187 // no match guards then we don't need any fake borrows, so don't track
@@ -192,13 +192,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
192192
193193 // This will generate code to test scrutinee_place and
194194 // branch to the appropriate arm block
195- self . match_candidates (
196- scrutinee_span,
197- block,
198- & mut otherwise,
199- & mut candidates,
200- & mut fake_borrows,
201- ) ;
195+ self . match_candidates ( scrutinee_span, block, & mut otherwise, candidates, & mut fake_borrows) ;
202196
203197 if let Some ( otherwise_block) = otherwise {
204198 let source_info = self . source_info ( scrutinee_span) ;
@@ -207,7 +201,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
207201
208202 let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
209203
210- for candidate in candidates. into_iter ( ) {
204+ for candidate in candidates {
211205 candidate. visit_leaves ( |leaf_candidate| {
212206 if let Some ( ref mut prev) = previous_candidate {
213207 prev. next_candidate_pre_binding_block = leaf_candidate. pre_binding_block ;
@@ -263,7 +257,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
263257 arm. guard . as_ref ( ) . map ( |g| ( g, match_scope) ) ,
264258 & fake_borrow_temps,
265259 scrutinee_span,
266- arm. scope ,
260+ Some ( arm. scope ) ,
267261 ) ;
268262
269263 if let Some ( source_scope) = scope {
@@ -297,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
297291 guard : Option < ( & Guard < ' tcx > , region:: Scope ) > ,
298292 fake_borrow_temps : & Vec < ( Place < ' tcx > , Local ) > ,
299293 scrutinee_span : Span ,
300- arm_scope : region:: Scope ,
294+ arm_scope : Option < region:: Scope > ,
301295 ) -> BasicBlock {
302296 if candidate. subcandidates . is_empty ( ) {
303297 // Avoid generating another `BasicBlock` when we only have one
@@ -308,25 +302,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
308302 guard,
309303 fake_borrow_temps,
310304 scrutinee_span,
305+ true ,
311306 )
312307 } else {
313308 let target_block = self . cfg . start_new_block ( ) ;
314-
309+ let mut schedule_drops = true ;
315310 // We keep a stack of all of the bindings and type asciptions
316311 // from the the parent candidates that we visit, that also need to
317312 // be bound for each candidate.
318313 traverse_candidate (
319314 candidate,
320315 & mut Vec :: new ( ) ,
321316 & mut |leaf_candidate, parent_bindings| {
322- self . clear_top_scope ( arm_scope) ;
317+ if let Some ( arm_scope) = arm_scope {
318+ // Avoid scheduling drops multiple times by unscheduling drops.
319+ self . clear_top_scope ( arm_scope) ;
320+ }
323321 let binding_end = self . bind_and_guard_matched_candidate (
324322 leaf_candidate,
325323 parent_bindings,
326324 guard,
327325 & fake_borrow_temps,
328326 scrutinee_span,
327+ schedule_drops,
329328 ) ;
329+ if arm_scope. is_none ( ) {
330+ // If we aren't in a match, then our bindings may not be
331+ // the only thing in the top scope, so only schedule
332+ // them to drop for the first pattern instead.
333+ schedule_drops = false ;
334+ }
330335 self . cfg . goto ( binding_end, outer_source_info, target_block) ;
331336 } ,
332337 |inner_candidate, parent_bindings| {
@@ -460,51 +465,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
460465 subcandidates : vec ! [ ] ,
461466 } ;
462467
463- // Simplify the candidate. Since the pattern is irrefutable, this should
464- // always convert all match-pairs into bindings.
465- self . simplify_candidate ( & mut candidate) ;
466-
467- if !candidate. match_pairs . is_empty ( ) {
468- // ICE if no other errors have been emitted. This used to be a hard error that wouldn't
469- // be reached because `hair::pattern::check_match::check_match` wouldn't have let the
470- // compiler continue. In our tests this is only ever hit by
471- // `ui/consts/const-match-check.rs` with `--cfg eval1`, and that file already generates
472- // a different error before hand.
473- self . hir . tcx ( ) . sess . delay_span_bug (
474- candidate. match_pairs [ 0 ] . pattern . span ,
475- & format ! (
476- "match pairs {:?} remaining after simplifying irrefutable pattern" ,
477- candidate. match_pairs,
478- ) ,
479- ) ;
480- }
468+ let fake_borrow_temps =
469+ self . lower_match_tree ( block, irrefutable_pat. span , false , & mut [ & mut candidate] ) ;
481470
482471 // for matches and function arguments, the place that is being matched
483472 // can be set when creating the variables. But the place for
484473 // let PATTERN = ... might not even exist until we do the assignment.
485474 // so we set it here instead
486475 if set_match_place {
487- for binding in & candidate. bindings {
488- let local = self . var_local_id ( binding. var_id , OutsideGuard ) ;
489-
490- if let LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
491- opt_match_place : Some ( ( ref mut match_place, _) ) ,
492- ..
493- } ) ) ) = self . local_decls [ local] . local_info
494- {
495- * match_place = Some ( * initializer) ;
496- } else {
497- bug ! ( "Let binding to non-user variable." )
476+ let mut candidate_ref = & candidate;
477+ while let Some ( next) = {
478+ for binding in & candidate_ref. bindings {
479+ let local = self . var_local_id ( binding. var_id , OutsideGuard ) ;
480+
481+ if let LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var (
482+ VarBindingForm { opt_match_place : Some ( ( ref mut match_place, _) ) , .. } ,
483+ ) ) ) = self . local_decls [ local] . local_info
484+ {
485+ * match_place = Some ( * initializer) ;
486+ } else {
487+ bug ! ( "Let binding to non-user variable." )
488+ }
498489 }
490+ candidate_ref. subcandidates . get ( 0 )
491+ } {
492+ candidate_ref = next;
499493 }
500494 }
501495
502- self . ascribe_types ( block, & candidate. ascriptions ) ;
503-
504- // now apply the bindings, which will also declare the variables
505- self . bind_matched_candidate_for_arm_body ( block, & candidate. bindings ) ;
506-
507- block. unit ( )
496+ self . bind_pattern (
497+ self . source_info ( irrefutable_pat. span ) ,
498+ candidate,
499+ None ,
500+ & fake_borrow_temps,
501+ irrefutable_pat. span ,
502+ None ,
503+ )
504+ . unit ( )
508505 }
509506
510507 /// Declares the bindings of the given patterns and returns the visibility
@@ -1486,6 +1483,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14861483 guard : Option < ( & Guard < ' tcx > , region:: Scope ) > ,
14871484 fake_borrows : & Vec < ( Place < ' tcx > , Local ) > ,
14881485 scrutinee_span : Span ,
1486+ schedule_drops : bool ,
14891487 ) -> BasicBlock {
14901488 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
14911489
@@ -1692,7 +1690,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16921690 let cause = FakeReadCause :: ForGuardBinding ;
16931691 self . cfg . push_fake_read ( post_guard_block, guard_end, cause, Place :: from ( local_id) ) ;
16941692 }
1695- self . bind_matched_candidate_for_arm_body ( post_guard_block, by_value_bindings) ;
1693+ assert ! ( schedule_drops, "patterns with guards must schedule drops" ) ;
1694+ self . bind_matched_candidate_for_arm_body ( post_guard_block, true , by_value_bindings) ;
16961695
16971696 post_guard_block
16981697 } else {
@@ -1701,6 +1700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17011700 // that we have to inspect before we bind them.)
17021701 self . bind_matched_candidate_for_arm_body (
17031702 block,
1703+ schedule_drops,
17041704 parent_bindings
17051705 . iter ( )
17061706 . flat_map ( |( bindings, _) | bindings)
@@ -1793,6 +1793,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17931793 fn bind_matched_candidate_for_arm_body < ' b > (
17941794 & mut self ,
17951795 block : BasicBlock ,
1796+ schedule_drops : bool ,
17961797 bindings : impl IntoIterator < Item = & ' b Binding < ' tcx > > ,
17971798 ) where
17981799 ' tcx : ' b ,
@@ -1805,7 +1806,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18051806 let source_info = self . source_info ( binding. span ) ;
18061807 let local =
18071808 self . storage_live_binding ( block, binding. var_id , binding. span , OutsideGuard ) ;
1808- self . schedule_drop_for_binding ( binding. var_id , binding. span , OutsideGuard ) ;
1809+ if schedule_drops {
1810+ self . schedule_drop_for_binding ( binding. var_id , binding. span , OutsideGuard ) ;
1811+ }
18091812 let rvalue = match binding. binding_mode {
18101813 BindingMode :: ByValue => {
18111814 Rvalue :: Use ( self . consume_by_copy_or_move ( binding. source . clone ( ) ) )
0 commit comments