@@ -122,7 +122,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
122
122
return_qualif : Option < Qualif > ,
123
123
qualif : Qualif ,
124
124
const_fn_arg_vars : BitVector ,
125
- local_needs_drop : IndexVec < Local , Option < Span > > ,
126
125
temp_promotion_state : IndexVec < Local , TempState > ,
127
126
promotion_candidates : Vec < Candidate >
128
127
}
@@ -136,19 +135,28 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
136
135
let mut rpo = traversal:: reverse_postorder ( mir) ;
137
136
let temps = promote_consts:: collect_temps ( mir, & mut rpo) ;
138
137
rpo. reset ( ) ;
138
+
139
+ let param_env = tcx. param_env ( def_id) ;
140
+
141
+ let mut temp_qualif = IndexVec :: from_elem ( None , & mir. local_decls ) ;
142
+ for arg in mir. args_iter ( ) {
143
+ let mut qualif = Qualif :: NEEDS_DROP ;
144
+ qualif. restrict ( mir. local_decls [ arg] . ty , tcx, param_env) ;
145
+ temp_qualif[ arg] = Some ( qualif) ;
146
+ }
147
+
139
148
Qualifier {
140
149
mode,
141
150
span : mir. span ,
142
151
def_id,
143
152
mir,
144
153
rpo,
145
154
tcx,
146
- param_env : tcx . param_env ( def_id ) ,
147
- temp_qualif : IndexVec :: from_elem ( None , & mir . local_decls ) ,
155
+ param_env,
156
+ temp_qualif,
148
157
return_qualif : None ,
149
158
qualif : Qualif :: empty ( ) ,
150
159
const_fn_arg_vars : BitVector :: new ( mir. local_decls . len ( ) ) ,
151
- local_needs_drop : IndexVec :: from_elem ( None , & mir. local_decls ) ,
152
160
temp_promotion_state : temps,
153
161
promotion_candidates : vec ! [ ]
154
162
}
@@ -255,15 +263,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
255
263
return ;
256
264
}
257
265
258
- // When initializing a local, record whether the *value* being
259
- // stored in it needs dropping, which it may not, even if its
260
- // type does, e.g. `None::<String>`.
261
- if let Place :: Local ( local) = * dest {
262
- if qualif. intersects ( Qualif :: NEEDS_DROP ) {
263
- self . local_needs_drop [ local] = Some ( self . span ) ;
264
- }
265
- }
266
-
267
266
match * dest {
268
267
Place :: Local ( index) if self . mir . local_kind ( index) == LocalKind :: Temp => {
269
268
debug ! ( "store to temp {:?}" , index) ;
@@ -424,17 +423,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
424
423
& local: & Local ,
425
424
_: PlaceContext < ' tcx > ,
426
425
_: Location ) {
427
- match self . mir . local_kind ( local) {
426
+ let kind = self . mir . local_kind ( local) ;
427
+ match kind {
428
428
LocalKind :: ReturnPointer => {
429
429
self . not_const ( ) ;
430
430
}
431
- LocalKind :: Arg => {
432
- self . add ( Qualif :: FN_ARGUMENT ) ;
433
- }
434
431
LocalKind :: Var => {
435
432
self . add ( Qualif :: NOT_CONST ) ;
436
433
}
434
+ LocalKind :: Arg |
437
435
LocalKind :: Temp => {
436
+ if let LocalKind :: Arg = kind {
437
+ self . add ( Qualif :: FN_ARGUMENT ) ;
438
+ }
439
+
438
440
if !self . temp_promotion_state [ local] . is_promotable ( ) {
439
441
self . add ( Qualif :: NOT_PROMOTABLE ) ;
440
442
}
@@ -529,16 +531,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
529
531
530
532
fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
531
533
match * operand {
532
- Operand :: Copy ( ref place ) |
533
- Operand :: Move ( ref place ) => {
534
+ Operand :: Copy ( _ ) |
535
+ Operand :: Move ( _ ) => {
534
536
self . nest ( |this| {
535
537
this. super_operand ( operand, location) ;
536
538
this. try_consume ( ) ;
537
539
} ) ;
538
540
539
541
// Mark the consumed locals to indicate later drops are noops.
540
- if let Place :: Local ( local) = * place {
541
- self . local_needs_drop [ local] = None ;
542
+ if let Operand :: Move ( Place :: Local ( local) ) = * operand {
543
+ self . temp_qualif [ local] = self . temp_qualif [ local] . map ( |q|
544
+ q - Qualif :: NEEDS_DROP
545
+ ) ;
542
546
}
543
547
}
544
548
Operand :: Constant ( ref constant) => {
@@ -847,9 +851,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
847
851
// HACK(eddyb) Emulate a bit of dataflow analysis,
848
852
// conservatively, that drop elaboration will do.
849
853
let needs_drop = if let Place :: Local ( local) = * place {
850
- self . local_needs_drop [ local]
854
+ if self . temp_qualif [ local] . map_or ( true , |q| q. intersects ( Qualif :: NEEDS_DROP ) ) {
855
+ Some ( self . mir . local_decls [ local] . source_info . span )
856
+ } else {
857
+ None
858
+ }
851
859
} else {
852
- None
860
+ Some ( self . span )
853
861
} ;
854
862
855
863
if let Some ( span) = needs_drop {
0 commit comments