@@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
9797 let body = self . hir . mirror ( arm. body . clone ( ) ) ;
9898 let scope = self . declare_bindings ( None , body. span ,
9999 LintLevel :: Inherited ,
100- & arm. patterns [ 0 ] ,
100+ & arm. patterns [ .. ] ,
101101 ArmHasGuard ( arm. guard . is_some ( ) ) ,
102102 Some ( ( Some ( & discriminant_place) , discriminant_span) ) ) ;
103103 ( body, scope. unwrap_or ( self . source_scope ) )
@@ -118,11 +118,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
118118 arms. iter ( )
119119 . enumerate ( )
120120 . flat_map ( |( arm_index, arm) | {
121- arm. patterns . iter ( )
122- . map ( move |pat| ( arm_index, pat, arm. guard . clone ( ) ) )
121+ arm. patterns . iter ( ) . enumerate ( )
122+ . map ( move |( pat_index, pat) | {
123+ ( arm_index, pat_index, pat, arm. guard . clone ( ) )
124+ } )
123125 } )
124126 . zip ( pre_binding_blocks. iter ( ) . zip ( pre_binding_blocks. iter ( ) . skip ( 1 ) ) )
125- . map ( |( ( arm_index, pattern, guard) ,
127+ . map ( |( ( arm_index, pat_index , pattern, guard) ,
126128 ( pre_binding_block, next_candidate_pre_binding_block) ) | {
127129
128130 if let ( true , Some ( borrow_temp) ) = ( tcx. emit_read_for_match ( ) ,
@@ -168,6 +170,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
168170 bindings : vec ! [ ] ,
169171 guard,
170172 arm_index,
173+ pat_index,
171174 pre_binding_block : * pre_binding_block,
172175 next_candidate_pre_binding_block : * next_candidate_pre_binding_block,
173176 }
@@ -277,6 +280,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
277280
278281 // since we don't call `match_candidates`, next fields is unused
279282 arm_index : 0 ,
283+ pat_index : 0 ,
280284 pre_binding_block : block,
281285 next_candidate_pre_binding_block : block
282286 } ;
@@ -324,14 +328,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
324328 mut visibility_scope : Option < SourceScope > ,
325329 scope_span : Span ,
326330 lint_level : LintLevel ,
327- pattern : & Pattern < ' tcx > ,
331+ patterns : & [ Pattern < ' tcx > ] ,
328332 has_guard : ArmHasGuard ,
329333 opt_match_place : Option < ( Option < & Place < ' tcx > > , Span ) > )
330334 -> Option < SourceScope > {
331335 assert ! ( !( visibility_scope. is_some( ) && lint_level. is_explicit( ) ) ,
332336 "can't have both a visibility and a lint scope at the same time" ) ;
333337 let mut scope = self . source_scope ;
334- self . visit_bindings ( pattern, & mut |this, mutability, name, mode, var, span, ty| {
338+ let num_patterns = patterns. len ( ) ;
339+ self . visit_bindings ( & patterns[ 0 ] , & mut |this, mutability, name, mode, var, span, ty| {
335340 if visibility_scope. is_none ( ) {
336341 visibility_scope = Some ( this. new_source_scope ( scope_span,
337342 LintLevel :: Inherited ,
@@ -349,8 +354,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
349354 scope,
350355 } ;
351356 let visibility_scope = visibility_scope. unwrap ( ) ;
352- this. declare_binding ( source_info, visibility_scope, mutability, name, mode, var,
353- ty, has_guard, opt_match_place. map ( |( x, y) | ( x. cloned ( ) , y) ) ) ;
357+ this. declare_binding ( source_info, visibility_scope, mutability, name, mode,
358+ num_patterns, var, ty, has_guard,
359+ opt_match_place. map ( |( x, y) | ( x. cloned ( ) , y) ) ) ;
354360 } ) ;
355361 visibility_scope
356362 }
@@ -453,6 +459,9 @@ pub struct Candidate<'pat, 'tcx:'pat> {
453459 // ...and the blocks for add false edges between candidates
454460 pre_binding_block : BasicBlock ,
455461 next_candidate_pre_binding_block : BasicBlock ,
462+
463+ // This uniquely identifies this candidate *within* the arm.
464+ pat_index : usize ,
456465}
457466
458467#[ derive( Clone , Debug ) ]
@@ -972,7 +981,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
972981 let autoref = self . hir . tcx ( ) . all_pat_vars_are_implicit_refs_within_guards ( ) ;
973982 if let Some ( guard) = candidate. guard {
974983 if autoref {
975- self . bind_matched_candidate_for_guard ( block, & candidate. bindings ) ;
984+ self . bind_matched_candidate_for_guard (
985+ block, candidate. pat_index , & candidate. bindings ) ;
976986 let guard_frame = GuardFrame {
977987 locals : candidate. bindings . iter ( )
978988 . map ( |b| GuardFrameLocal :: new ( b. var_id , b. binding_mode ) )
@@ -1058,9 +1068,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
10581068 // and thus all code/comments assume we are in that context.
10591069 fn bind_matched_candidate_for_guard ( & mut self ,
10601070 block : BasicBlock ,
1071+ pat_index : usize ,
10611072 bindings : & [ Binding < ' tcx > ] ) {
1062- debug ! ( "bind_matched_candidate_for_guard(block={:?}, bindings={:?})" ,
1063- block, bindings) ;
1073+ debug ! ( "bind_matched_candidate_for_guard(block={:?}, pat_index={:?}, bindings={:?})" ,
1074+ block, pat_index , bindings) ;
10641075
10651076 // Assign each of the bindings. Since we are binding for a
10661077 // guard expression, this will never trigger moves out of the
@@ -1099,8 +1110,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
10991110 // used by the arm body itself. This eases
11001111 // observing two-phase borrow restrictions.
11011112 let val_for_guard = self . storage_live_binding (
1102- block, binding. var_id , binding. span , ValWithinGuard ) ;
1103- self . schedule_drop_for_binding ( binding. var_id , binding. span , ValWithinGuard ) ;
1113+ block, binding. var_id , binding. span , ValWithinGuard ( pat_index) ) ;
1114+ self . schedule_drop_for_binding (
1115+ binding. var_id , binding. span , ValWithinGuard ( pat_index) ) ;
11041116
11051117 // rust-lang/rust#27282: We reuse the two-phase
11061118 // borrow infrastructure so that the mutable
@@ -1146,16 +1158,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
11461158
11471159 /// Each binding (`ref mut var`/`ref var`/`mut var`/`var`, where
11481160 /// the bound `var` has type `T` in the arm body) in a pattern
1149- /// maps to *two* locals. The first local is a binding for
1161+ /// maps to `2+N` locals. The first local is a binding for
11501162 /// occurrences of `var` in the guard, which will all have type
1151- /// `&T`. The second local is a binding for occurrences of `var`
1152- /// in the arm body, which will have type `T`.
1163+ /// `&T`. The N locals are bindings for the `T` that is referenced
1164+ /// by the first local; they are not used outside of the
1165+ /// guard. The last local is a binding for occurrences of `var` in
1166+ /// the arm body, which will have type `T`.
1167+ ///
1168+ /// The reason we have N locals rather than just 1 is to
1169+ /// accommodate rust-lang/rust#51348: If the arm has N candidate
1170+ /// patterns, then in general they can correspond to distinct
1171+ /// parts of the matched data, and we want them to be distinct
1172+ /// temps in order to simplify checks performed by our internal
1173+ /// leveraging of two-phase borrows).
11531174 fn declare_binding ( & mut self ,
11541175 source_info : SourceInfo ,
11551176 visibility_scope : SourceScope ,
11561177 mutability : Mutability ,
11571178 name : Name ,
11581179 mode : BindingMode ,
1180+ num_patterns : usize ,
11591181 var_id : NodeId ,
11601182 var_ty : Ty < ' tcx > ,
11611183 has_guard : ArmHasGuard ,
@@ -1189,7 +1211,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
11891211 } ;
11901212 let for_arm_body = self . local_decls . push ( local. clone ( ) ) ;
11911213 let locals = if has_guard. 0 && tcx. all_pat_vars_are_implicit_refs_within_guards ( ) {
1192- let val_for_guard = self . local_decls . push ( local) ;
1214+ let mut vals_for_guard = Vec :: with_capacity ( num_patterns) ;
1215+ for _ in 0 ..num_patterns {
1216+ let val_for_guard_idx = self . local_decls . push ( local. clone ( ) ) ;
1217+ vals_for_guard. push ( val_for_guard_idx) ;
1218+ }
11931219 let ref_for_guard = self . local_decls . push ( LocalDecl :: < ' tcx > {
11941220 mutability,
11951221 ty : tcx. mk_imm_ref ( tcx. types . re_empty , var_ty) ,
@@ -1200,7 +1226,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
12001226 internal : false ,
12011227 is_user_variable : Some ( ClearCrossCrate :: Set ( BindingForm :: RefForGuard ) ) ,
12021228 } ) ;
1203- LocalsForNode :: Three { val_for_guard , ref_for_guard, for_arm_body }
1229+ LocalsForNode :: ForGuard { vals_for_guard , ref_for_guard, for_arm_body }
12041230 } else {
12051231 LocalsForNode :: One ( for_arm_body)
12061232 } ;
0 commit comments