Skip to content

Commit

Permalink
Auto merge of #33622 - arielb1:elaborate-drops, r=nikomatsakis
Browse files Browse the repository at this point in the history
[MIR] non-zeroing drop

This enables non-zeroing drop through stack flags for MIR.

Fixes #30380.
Fixes #5016.
  • Loading branch information
bors committed Jun 5, 2016
2 parents ccfaaa7 + 063f882 commit f97c411
Show file tree
Hide file tree
Showing 42 changed files with 2,101 additions and 318 deletions.
18 changes: 18 additions & 0 deletions src/librustc/infer/mod.rs
Expand Up @@ -624,6 +624,24 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
value.trans_normalize(&infcx)
})
}

pub fn normalize_associated_type_in_env<T>(
self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
) -> T
where T: TransNormalize<'tcx>
{
debug!("normalize_associated_type_in_env(t={:?})", value);

let value = self.erase_regions(value);

if !value.has_projection_types() {
return value;
}

self.infer_ctxt(None, Some(env.clone()), ProjectionMode::Any).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/cstore.rs
Expand Up @@ -163,6 +163,7 @@ pub trait CrateStore<'tcx> {
-> ty::TypeScheme<'tcx>;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
fn item_name(&self, def: DefId) -> ast::Name;
fn opt_item_name(&self, def: DefId) -> Option<ast::Name>;
fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
Expand Down Expand Up @@ -345,6 +346,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
bug!("visible_parent_map")
}
fn item_name(&self, def: DefId) -> ast::Name { bug!("item_name") }
fn opt_item_name(&self, def: DefId) -> Option<ast::Name> { bug!("opt_item_name") }
fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
Expand Down
43 changes: 34 additions & 9 deletions src/librustc/mir/repr.rs
Expand Up @@ -330,11 +330,19 @@ pub enum TerminatorKind<'tcx> {

/// Drop the Lvalue
Drop {
value: Lvalue<'tcx>,
location: Lvalue<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>
},

/// Drop the Lvalue and assign the new value over it
DropAndReplace {
location: Lvalue<'tcx>,
value: Operand<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>,
},

/// Block ends with a call of a converging function
Call {
/// The function that’s being called
Expand Down Expand Up @@ -373,8 +381,14 @@ impl<'tcx> TerminatorKind<'tcx> {
slice::ref_slice(t).into_cow(),
Call { destination: None, cleanup: Some(ref c), .. } => slice::ref_slice(c).into_cow(),
Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
Drop { target, unwind: Some(unwind), .. } => vec![target, unwind].into_cow(),
Drop { ref target, .. } => slice::ref_slice(target).into_cow(),
DropAndReplace { target, unwind: Some(unwind), .. } |
Drop { target, unwind: Some(unwind), .. } => {
vec![target, unwind].into_cow()
}
DropAndReplace { ref target, unwind: None, .. } |
Drop { ref target, unwind: None, .. } => {
slice::ref_slice(target).into_cow()
}
}
}

Expand All @@ -393,8 +407,12 @@ impl<'tcx> TerminatorKind<'tcx> {
Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
Call { destination: None, cleanup: None, .. } => vec![],
DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } |
Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind],
Drop { ref mut target, .. } => vec![target]
DropAndReplace { ref mut target, unwind: None, .. } |
Drop { ref mut target, unwind: None, .. } => {
vec![target]
}
}
}
}
Expand Down Expand Up @@ -461,7 +479,9 @@ impl<'tcx> TerminatorKind<'tcx> {
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
Return => write!(fmt, "return"),
Resume => write!(fmt, "resume"),
Drop { ref value, .. } => write!(fmt, "drop({:?})", value),
Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
DropAndReplace { ref location, ref value, .. } =>
write!(fmt, "replace({:?} <- {:?})", location, value),
Call { ref func, ref args, ref destination, .. } => {
if let Some((ref destination, _)) = *destination {
write!(fmt, "{:?} = ", destination)?;
Expand Down Expand Up @@ -506,8 +526,12 @@ impl<'tcx> TerminatorKind<'tcx> {
Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
Call { destination: None, cleanup: None, .. } => vec![],
DropAndReplace { unwind: None, .. } |
Drop { unwind: None, .. } => vec!["return".into_cow()],
Drop { .. } => vec!["return".into_cow(), "unwind".into_cow()],
DropAndReplace { unwind: Some(_), .. } |
Drop { unwind: Some(_), .. } => {
vec!["return".into_cow(), "unwind".into_cow()]
}
}
}
}
Expand Down Expand Up @@ -918,7 +942,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
ppaux::parameterized(fmt, substs, variant_def.did,
ppaux::Ns::Value, &[],
|tcx| {
tcx.lookup_item_type(variant_def.did).generics
Some(tcx.lookup_item_type(variant_def.did).generics)
})?;

match variant_def.kind() {
Expand Down Expand Up @@ -1010,8 +1034,9 @@ impl<'tcx> Debug for Literal<'tcx> {
use self::Literal::*;
match *self {
Item { def_id, substs } => {
ppaux::parameterized(fmt, substs, def_id, ppaux::Ns::Value, &[],
|tcx| tcx.lookup_item_type(def_id).generics)
ppaux::parameterized(
fmt, substs, def_id, ppaux::Ns::Value, &[],
|tcx| Some(tcx.lookup_item_type(def_id).generics))
}
Value { ref value } => {
write!(fmt, "const ")?;
Expand Down
14 changes: 12 additions & 2 deletions src/librustc/mir/visit.rs
Expand Up @@ -394,10 +394,20 @@ macro_rules! make_mir_visitor {
TerminatorKind::Return => {
}

TerminatorKind::Drop { ref $($mutability)* value,
TerminatorKind::Drop { ref $($mutability)* location,
target,
unwind } => {
self.visit_lvalue(value, LvalueContext::Drop);
self.visit_lvalue(location, LvalueContext::Drop);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
}

TerminatorKind::DropAndReplace { ref $($mutability)* location,
ref $($mutability)* value,
target,
unwind } => {
self.visit_lvalue(location, LvalueContext::Drop);
self.visit_operand(value);
self.visit_branch(block, target);
unwind.map(|t| self.visit_branch(block, t));
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/ty/item_path.rs
Expand Up @@ -13,6 +13,7 @@ use middle::cstore::LOCAL_CRATE;
use hir::def_id::{DefId, CRATE_DEF_INDEX};
use ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::parse::token;

use std::cell::Cell;

Expand Down Expand Up @@ -138,7 +139,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}

cur_path.push(self.sess.cstore.item_name(cur_def));
cur_path.push(self.sess.cstore.opt_item_name(cur_def).unwrap_or_else(||
token::intern("<unnamed>")));
match visible_parent_map.get(&cur_def) {
Some(&def) => cur_def = def,
None => return false,
Expand Down
12 changes: 12 additions & 0 deletions src/librustc/ty/mod.rs
Expand Up @@ -2503,6 +2503,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|| self.sess.cstore.item_type(self.global_tcx(), did))
}

pub fn opt_lookup_item_type(self, did: DefId) -> Option<TypeScheme<'gcx>> {
if let Some(scheme) = self.tcache.borrow_mut().get(&did) {
return Some(scheme.clone());
}

if did.krate == LOCAL_CRATE {
None
} else {
Some(self.sess.cstore.item_type(self.global_tcx(), did))
}
}

/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef<'gcx> {
lookup_locally_or_in_crate_store(
Expand Down
44 changes: 23 additions & 21 deletions src/librustc/util/ppaux.rs
Expand Up @@ -69,15 +69,12 @@ pub enum Ns {
Value
}

fn number_of_supplied_defaults<'a, 'gcx, 'tcx, GG>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &subst::Substs,
space: subst::ParamSpace,
get_generics: GG)
-> usize
where GG: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> ty::Generics<'tcx>
fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &subst::Substs,
space: subst::ParamSpace,
generics: ty::Generics<'tcx>)
-> usize
{
let generics = get_generics(tcx);

let has_self = substs.self_ty().is_some();
let ty_params = generics.types.get_slice(space);
let tps = substs.types.get_slice(space);
Expand Down Expand Up @@ -115,7 +112,8 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
projections: &[ty::ProjectionPredicate],
get_generics: GG)
-> fmt::Result
where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> ty::Generics<'tcx>
where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>)
-> Option<ty::Generics<'tcx>>
{
if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) {
write!(f, "<{} as ", self_ty)?;
Expand Down Expand Up @@ -176,13 +174,12 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
let num_supplied_defaults = if verbose {
0
} else {
// It is important to execute this conditionally, only if -Z
// verbose is false. Otherwise, debug logs can sometimes cause
// ICEs trying to fetch the generics early in the pipeline. This
// is kind of a hacky workaround in that -Z verbose is required to
// avoid those ICEs.
ty::tls::with(|tcx| {
number_of_supplied_defaults(tcx, substs, subst::TypeSpace, get_generics)
if let Some(generics) = get_generics(tcx) {
number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics)
} else {
0
}
})
};

Expand Down Expand Up @@ -312,7 +309,7 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
trait_ref.def_id,
Ns::Type,
projection_bounds,
|tcx| tcx.lookup_trait_def(trait_ref.def_id).generics.clone())
|tcx| Some(tcx.lookup_trait_def(trait_ref.def_id).generics.clone()))
}
}

Expand Down Expand Up @@ -814,7 +811,7 @@ impl fmt::Display for ty::Binder<ty::OutlivesPredicate<ty::Region, ty::Region>>
impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
parameterized(f, self.substs, self.def_id, Ns::Type, &[],
|tcx| tcx.lookup_trait_def(self.def_id).generics.clone())
|tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone()))
}
}

Expand Down Expand Up @@ -866,8 +863,9 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}

write!(f, "{} {{", bare_fn.sig.0)?;
parameterized(f, substs, def_id, Ns::Value, &[],
|tcx| tcx.lookup_item_type(def_id).generics)?;
parameterized(
f, substs, def_id, Ns::Value, &[],
|tcx| tcx.opt_lookup_item_type(def_id).map(|t| t.generics))?;
write!(f, "}}")
}
TyFnPtr(ref bare_fn) => {
Expand All @@ -890,8 +888,12 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
!tcx.tcache.borrow().contains_key(&def.did) {
write!(f, "{}<..>", tcx.item_path_str(def.did))
} else {
parameterized(f, substs, def.did, Ns::Type, &[],
|tcx| tcx.lookup_item_type(def.did).generics)
parameterized(
f, substs, def.did, Ns::Type, &[],
|tcx| {
tcx.opt_lookup_item_type(def.did).
map(|t| t.generics)
})
}
})
}
Expand Down
17 changes: 15 additions & 2 deletions src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
Expand Up @@ -200,6 +200,12 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>

pub struct DataflowResults<O>(DataflowState<O>) where O: BitDenotation;

impl<O: BitDenotation> DataflowResults<O> {
pub fn sets(&self) -> &AllSets<O::Idx> {
&self.0.sets
}
}

// FIXME: This type shouldn't be public, but the graphviz::MirWithFlowState trait
// references it in a method signature. Look into using `pub(crate)` to address this.
pub struct DataflowState<O: BitDenotation>
Expand Down Expand Up @@ -444,10 +450,17 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
repr::TerminatorKind::Return |
repr::TerminatorKind::Resume => {}
repr::TerminatorKind::Goto { ref target } |
repr::TerminatorKind::Drop { ref target, value: _, unwind: None } => {
repr::TerminatorKind::Drop { ref target, location: _, unwind: None } |

repr::TerminatorKind::DropAndReplace {
ref target, value: _, location: _, unwind: None
} => {
self.propagate_bits_into_entry_set_for(in_out, changed, target);
}
repr::TerminatorKind::Drop { ref target, value: _, unwind: Some(ref unwind) } => {
repr::TerminatorKind::Drop { ref target, location: _, unwind: Some(ref unwind) } |
repr::TerminatorKind::DropAndReplace {
ref target, value: _, location: _, unwind: Some(ref unwind)
} => {
self.propagate_bits_into_entry_set_for(in_out, changed, target);
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
}
Expand Down

0 comments on commit f97c411

Please sign in to comment.