Skip to content

Commit

Permalink
Rollup merge of rust-lang#47306 - alexreg:dataflow-analysis, r=eddyb
Browse files Browse the repository at this point in the history
Don't track local_needs_drop separately in qualify_consts.

None
  • Loading branch information
kennytm committed Jan 12, 2018
2 parents f4ff4c0 + e2c1a93 commit df8f2c6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
54 changes: 31 additions & 23 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
return_qualif: Option<Qualif>,
qualif: Qualif,
const_fn_arg_vars: BitVector,
local_needs_drop: IndexVec<Local, Option<Span>>,
temp_promotion_state: IndexVec<Local, TempState>,
promotion_candidates: Vec<Candidate>
}
Expand All @@ -136,19 +135,28 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
let mut rpo = traversal::reverse_postorder(mir);
let temps = promote_consts::collect_temps(mir, &mut rpo);
rpo.reset();

let param_env = tcx.param_env(def_id);

let mut temp_qualif = IndexVec::from_elem(None, &mir.local_decls);
for arg in mir.args_iter() {
let mut qualif = Qualif::NEEDS_DROP;
qualif.restrict(mir.local_decls[arg].ty, tcx, param_env);
temp_qualif[arg] = Some(qualif);
}

Qualifier {
mode,
span: mir.span,
def_id,
mir,
rpo,
tcx,
param_env: tcx.param_env(def_id),
temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
param_env,
temp_qualif,
return_qualif: None,
qualif: Qualif::empty(),
const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
local_needs_drop: IndexVec::from_elem(None, &mir.local_decls),
temp_promotion_state: temps,
promotion_candidates: vec![]
}
Expand Down Expand Up @@ -255,15 +263,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
return;
}

// When initializing a local, record whether the *value* being
// stored in it needs dropping, which it may not, even if its
// type does, e.g. `None::<String>`.
if let Place::Local(local) = *dest {
if qualif.intersects(Qualif::NEEDS_DROP) {
self.local_needs_drop[local] = Some(self.span);
}
}

match *dest {
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
debug!("store to temp {:?}", index);
Expand Down Expand Up @@ -424,17 +423,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
&local: &Local,
_: PlaceContext<'tcx>,
_: Location) {
match self.mir.local_kind(local) {
let kind = self.mir.local_kind(local);
match kind {
LocalKind::ReturnPointer => {
self.not_const();
}
LocalKind::Arg => {
self.add(Qualif::FN_ARGUMENT);
}
LocalKind::Var => {
self.add(Qualif::NOT_CONST);
}
LocalKind::Arg |
LocalKind::Temp => {
if let LocalKind::Arg = kind {
self.add(Qualif::FN_ARGUMENT);
}

if !self.temp_promotion_state[local].is_promotable() {
self.add(Qualif::NOT_PROMOTABLE);
}
Expand Down Expand Up @@ -529,16 +531,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {

fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
match *operand {
Operand::Copy(ref place) |
Operand::Move(ref place) => {
Operand::Copy(_) |
Operand::Move(_) => {
self.nest(|this| {
this.super_operand(operand, location);
this.try_consume();
});

// Mark the consumed locals to indicate later drops are noops.
if let Place::Local(local) = *place {
self.local_needs_drop[local] = None;
if let Operand::Move(Place::Local(local)) = *operand {
self.temp_qualif[local] = self.temp_qualif[local].map(|q|
q - Qualif::NEEDS_DROP
);
}
}
Operand::Constant(ref constant) => {
Expand Down Expand Up @@ -847,9 +851,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
// HACK(eddyb) Emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
let needs_drop = if let Place::Local(local) = *place {
self.local_needs_drop[local]
if self.temp_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
Some(self.mir.local_decls[local].source_info.span)
} else {
None
}
} else {
None
Some(self.span)
};

if let Some(span) = needs_drop {
Expand Down
10 changes: 10 additions & 0 deletions src/test/compile-fail/static-drop-scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(const_fn)]

struct WithDtor;

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

const fn const_drop<T>(_: T) {}
//~^ ERROR destructors cannot be evaluated at compile-time

const fn const_drop2<T>(x: T) {
(x, ()).1
//~^ ERROR destructors cannot be evaluated at compile-time
}

fn main () {}

0 comments on commit df8f2c6

Please sign in to comment.