Skip to content

Commit e2c1a93

Browse files
author
Alexander Regueiro
committed
Don't track local_needs_drop separately in qualify_consts (fixes #47351).
1 parent 73ac5d6 commit e2c1a93

File tree

2 files changed

+41
-23
lines changed

2 files changed

+41
-23
lines changed

src/librustc_mir/transform/qualify_consts.rs

+31-23
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
122122
return_qualif: Option<Qualif>,
123123
qualif: Qualif,
124124
const_fn_arg_vars: BitVector,
125-
local_needs_drop: IndexVec<Local, Option<Span>>,
126125
temp_promotion_state: IndexVec<Local, TempState>,
127126
promotion_candidates: Vec<Candidate>
128127
}
@@ -136,19 +135,28 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
136135
let mut rpo = traversal::reverse_postorder(mir);
137136
let temps = promote_consts::collect_temps(mir, &mut rpo);
138137
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+
139148
Qualifier {
140149
mode,
141150
span: mir.span,
142151
def_id,
143152
mir,
144153
rpo,
145154
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,
148157
return_qualif: None,
149158
qualif: Qualif::empty(),
150159
const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
151-
local_needs_drop: IndexVec::from_elem(None, &mir.local_decls),
152160
temp_promotion_state: temps,
153161
promotion_candidates: vec![]
154162
}
@@ -255,15 +263,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
255263
return;
256264
}
257265

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-
267266
match *dest {
268267
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
269268
debug!("store to temp {:?}", index);
@@ -424,17 +423,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
424423
&local: &Local,
425424
_: PlaceContext<'tcx>,
426425
_: Location) {
427-
match self.mir.local_kind(local) {
426+
let kind = self.mir.local_kind(local);
427+
match kind {
428428
LocalKind::ReturnPointer => {
429429
self.not_const();
430430
}
431-
LocalKind::Arg => {
432-
self.add(Qualif::FN_ARGUMENT);
433-
}
434431
LocalKind::Var => {
435432
self.add(Qualif::NOT_CONST);
436433
}
434+
LocalKind::Arg |
437435
LocalKind::Temp => {
436+
if let LocalKind::Arg = kind {
437+
self.add(Qualif::FN_ARGUMENT);
438+
}
439+
438440
if !self.temp_promotion_state[local].is_promotable() {
439441
self.add(Qualif::NOT_PROMOTABLE);
440442
}
@@ -529,16 +531,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
529531

530532
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
531533
match *operand {
532-
Operand::Copy(ref place) |
533-
Operand::Move(ref place) => {
534+
Operand::Copy(_) |
535+
Operand::Move(_) => {
534536
self.nest(|this| {
535537
this.super_operand(operand, location);
536538
this.try_consume();
537539
});
538540

539541
// 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+
);
542546
}
543547
}
544548
Operand::Constant(ref constant) => {
@@ -847,9 +851,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
847851
// HACK(eddyb) Emulate a bit of dataflow analysis,
848852
// conservatively, that drop elaboration will do.
849853
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+
}
851859
} else {
852-
None
860+
Some(self.span)
853861
};
854862

855863
if let Some(span) = needs_drop {

src/test/compile-fail/static-drop-scope.rs

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![feature(const_fn)]
12+
1113
struct WithDtor;
1214

1315
impl Drop for WithDtor {
@@ -28,4 +30,12 @@ static EARLY_DROP_S: i32 = (WithDtor, 0).1;
2830
const EARLY_DROP_C: i32 = (WithDtor, 0).1;
2931
//~^ ERROR destructors cannot be evaluated at compile-time
3032

33+
const fn const_drop<T>(_: T) {}
34+
//~^ ERROR destructors cannot be evaluated at compile-time
35+
36+
const fn const_drop2<T>(x: T) {
37+
(x, ()).1
38+
//~^ ERROR destructors cannot be evaluated at compile-time
39+
}
40+
3141
fn main () {}

0 commit comments

Comments
 (0)