move destructors_for_type into AdtDef

This commit is contained in:
Ariel Ben-Yehuda 2015-08-25 21:52:15 +03:00
parent d07ee255d0
commit 277eeb95c3
12 changed files with 69 additions and 56 deletions

View File

@ -548,7 +548,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
e: &ast::Expr, node_ty: Ty<'tcx>) {
match node_ty.sty {
ty::TyStruct(def, _) |
ty::TyEnum(def, _) if def.has_dtor(v.tcx) => {
ty::TyEnum(def, _) if def.has_dtor() => {
v.add_qualif(ConstQualif::NEEDS_DROP);
if v.mode != Mode::Var {
v.tcx.sess.span_err(e.span,

View File

@ -239,8 +239,9 @@ impl OverloadedCallType {
// mem_categorization, it requires a TYPER, which is a type that
// supplies types from the tree. After type checking is complete, you
// can just use the tcx as the typer.
pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> {
//
// FIXME(stage0): the :'t here is probably only important for stage0
pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d+'t> {
typer: &'t infer::InferCtxt<'a, 'tcx>,
mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
delegate: &'d mut (Delegate<'tcx>+'d),

View File

@ -355,9 +355,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// this properly would result in the necessity of computing *type*
// reachability, which might result in a compile time loss.
fn mark_destructors_reachable(&mut self) {
for (_, destructor_def_id) in self.tcx.destructor_for_type.borrow().iter() {
if destructor_def_id.is_local() {
self.reachable_symbols.insert(destructor_def_id.node);
for adt in self.tcx.adt_defs() {
if let Some(destructor_def_id) = adt.destructor() {
if destructor_def_id.is_local() {
self.reachable_symbols.insert(destructor_def_id.node);
}
}
}
}

View File

@ -112,7 +112,7 @@ pub struct CrateAnalysis {
#[derive(Copy, Clone)]
pub enum DtorKind {
NoDtor,
TraitDtor(DefId, bool)
TraitDtor(bool)
}
impl DtorKind {
@ -126,7 +126,7 @@ impl DtorKind {
pub fn has_drop_flag(&self) -> bool {
match self {
&NoDtor => false,
&TraitDtor(_, flag) => flag
&TraitDtor(flag) => flag
}
}
}
@ -797,12 +797,6 @@ pub struct ctxt<'tcx> {
/// True if the variance has been computed yet; false otherwise.
pub variance_computed: Cell<bool>,
/// A mapping from the def ID of an enum or struct type to the def ID
/// of the method that implements its destructor. If the type is not
/// present in this map, it does not have a destructor. This map is
/// populated during the coherence phase of typechecking.
pub destructor_for_type: RefCell<DefIdMap<DefId>>,
/// A method will be in this list if and only if it is a destructor.
pub destructors: RefCell<DefIdSet>,
@ -3057,7 +3051,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
_ => return Err(TypeIsStructural),
};
if adt.has_dtor(tcx) {
if adt.has_dtor() {
return Err(TypeHasDestructor)
}
@ -3262,6 +3256,7 @@ bitflags! {
const IS_PHANTOM_DATA = 1 << 3,
const IS_SIMD = 1 << 4,
const IS_FUNDAMENTAL = 1 << 5,
const IS_NO_DROP_FLAG = 1 << 6,
}
}
@ -3312,6 +3307,7 @@ pub struct FieldDefData<'tcx, 'container: 'tcx> {
pub struct AdtDefData<'tcx, 'container: 'tcx> {
pub did: DefId,
pub variants: Vec<VariantDefData<'tcx, 'container>>,
destructor: Cell<Option<DefId>>,
flags: Cell<AdtFlags>,
}
@ -3347,6 +3343,9 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
if attr::contains_name(&attrs, "fundamental") {
flags = flags | AdtFlags::IS_FUNDAMENTAL;
}
if attr::contains_name(&attrs, "unsafe_no_drop_flag") {
flags = flags | AdtFlags::IS_NO_DROP_FLAG;
}
if tcx.lookup_simd(did) {
flags = flags | AdtFlags::IS_SIMD;
}
@ -3360,6 +3359,7 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
did: did,
variants: variants,
flags: Cell::new(flags),
destructor: Cell::new(None)
}
}
@ -3410,8 +3410,11 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
}
/// Returns whether this type has a destructor.
pub fn has_dtor(&self, tcx: &ctxt<'tcx>) -> bool {
tcx.destructor_for_type.borrow().contains_key(&self.did)
pub fn has_dtor(&self) -> bool {
match self.dtor_kind() {
NoDtor => false,
TraitDtor(..) => true
}
}
/// Asserts this is a struct and returns the struct's unique
@ -3473,6 +3476,24 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
_ => panic!("unexpected def {:?} in variant_of_def", def)
}
}
pub fn destructor(&self) -> Option<DefId> {
self.destructor.get()
}
pub fn set_destructor(&self, dtor: DefId) {
assert!(self.destructor.get().is_none());
self.destructor.set(Some(dtor));
}
pub fn dtor_kind(&self) -> DtorKind {
match self.destructor.get() {
Some(_) => {
TraitDtor(!self.flags.get().intersects(AdtFlags::IS_NO_DROP_FLAG))
}
None => NoDtor,
}
}
}
impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
@ -3856,7 +3877,6 @@ impl<'tcx> ctxt<'tcx> {
normalized_cache: RefCell::new(FnvHashMap()),
lang_items: lang_items,
provided_method_sources: RefCell::new(DefIdMap()),
destructor_for_type: RefCell::new(DefIdMap()),
destructors: RefCell::new(DefIdSet()),
inherent_impls: RefCell::new(DefIdMap()),
impl_items: RefCell::new(DefIdMap()),
@ -4679,7 +4699,7 @@ impl<'tcx> TyS<'tcx> {
})
});
if def.has_dtor(cx) {
if def.has_dtor() {
res = res | TC::OwnsDtor;
}
@ -6017,18 +6037,6 @@ impl<'tcx> ctxt<'tcx> {
self.with_path(id, |path| ast_map::path_to_string(path))
}
/* If struct_id names a struct with a dtor. */
pub fn ty_dtor(&self, struct_id: DefId) -> DtorKind {
match self.destructor_for_type.borrow().get(&struct_id) {
Some(&method_def_id) => {
let flag = !self.has_attr(struct_id, "unsafe_no_drop_flag");
TraitDtor(method_def_id, flag)
}
None => NoDtor,
}
}
pub fn with_path<T, F>(&self, id: DefId, f: F) -> T where
F: FnOnce(ast_map::PathElems) -> T,
{
@ -6113,6 +6121,11 @@ impl<'tcx> ctxt<'tcx> {
self.lookup_adt_def_master(did)
}
/// Return the list of all interned ADT definitions
pub fn adt_defs(&self) -> Vec<AdtDef<'tcx>> {
self.adt_defs.borrow().values().cloned().collect()
}
/// Given the did of an item, returns its full set of predicates.
pub fn lookup_predicates(&self, did: DefId) -> GenericPredicates<'tcx> {
lookup_locally_or_in_crate_store(
@ -6760,8 +6773,8 @@ impl<'tcx> ctxt<'tcx> {
/// Returns true if this ADT is a dtorck type, i.e. whether it being
/// safe for destruction requires it to be alive
fn is_adt_dtorck(&self, adt: AdtDef<'tcx>) -> bool {
let dtor_method = match self.destructor_for_type.borrow().get(&adt.did) {
Some(dtor) => *dtor,
let dtor_method = match adt.destructor() {
Some(dtor) => dtor,
None => return false
};
let impl_did = self.impl_of_method(dtor_method).unwrap_or_else(|| {

View File

@ -747,7 +747,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}
LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
match lp_base.to_type().sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor(self.tcx()) => {
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => {
// In the case where the owner implements drop, then
// the path must be initialized to prevent a case of
// partial reinitialization

View File

@ -180,7 +180,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
mc::cat_interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
match b.ty.sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
if def.has_dtor(bccx.tcx) {
if def.has_dtor() {
Some(cmt.clone())
} else {
check_and_get_illegal_move_origin(bccx, b)

View File

@ -137,7 +137,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
mc::cat_interior(ref b, mc::InteriorField(_)) => {
match b.ty.sty {
ty::TyStruct(def, _) |
ty::TyEnum(def, _) if def.has_dtor(bccx.tcx) => {
ty::TyEnum(def, _) if def.has_dtor() => {
bccx.span_err(
move_from.span,
&format!("cannot move out of type `{}`, \

View File

@ -1952,26 +1952,26 @@ impl LintPass for MissingCopyImplementations {
if !cx.exported_items.contains(&item.id) {
return;
}
if cx.tcx.destructor_for_type.borrow().contains_key(&DefId::local(item.id)) {
return;
}
let ty = match item.node {
let (def, ty) = match item.node {
ast::ItemStruct(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
return;
}
cx.tcx.mk_struct(cx.tcx.lookup_adt_def(DefId::local(item.id)),
cx.tcx.mk_substs(Substs::empty()))
let def = cx.tcx.lookup_adt_def(DefId::local(item.id));
(def, cx.tcx.mk_struct(def,
cx.tcx.mk_substs(Substs::empty())))
}
ast::ItemEnum(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
return;
}
cx.tcx.mk_enum(cx.tcx.lookup_adt_def(DefId::local(item.id)),
cx.tcx.mk_substs(Substs::empty()))
let def = cx.tcx.lookup_adt_def(DefId::local(item.id));
(def, cx.tcx.mk_enum(def,
cx.tcx.mk_substs(Substs::empty())))
}
_ => return,
};
if def.has_dtor() { return; }
let parameter_environment = cx.tcx.empty_parameter_environment();
// FIXME (@jroesch) should probably inver this so that the parameter env still impls this
// method
@ -2583,7 +2583,7 @@ impl LintPass for DropWithReprExtern {
let self_type_did = self_type_def.did;
let hints = ctx.tcx.lookup_repr_hints(self_type_did);
if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
ctx.tcx.ty_dtor(self_type_did).has_drop_flag() {
self_type_def.dtor_kind().has_drop_flag() {
let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did,
codemap::DUMMY_SP);
let self_defn_span = ctx.tcx.map.def_id_span(self_type_did,

View File

@ -250,7 +250,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
monomorphize::field_ty(cx.tcx(), substs, field)
}).collect::<Vec<_>>();
let packed = cx.tcx().lookup_packed(def.did);
let dtor = cx.tcx().ty_dtor(def.did).has_drop_flag();
let dtor = def.dtor_kind().has_drop_flag();
if dtor {
ftys.push(cx.tcx().dtor_type());
}
@ -265,7 +265,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let hint = *cx.tcx().lookup_repr_hints(def.did).get(0)
.unwrap_or(&attr::ReprAny);
let dtor = cx.tcx().ty_dtor(def.did).has_drop_flag();
let dtor = def.dtor_kind().has_drop_flag();
if cases.is_empty() {
// Uninhabitable; represent as unit

View File

@ -1267,7 +1267,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
def::DefStruct(_) => {
let ty = expr_ty(bcx, ref_expr);
match ty.sty {
ty::TyStruct(def, _) if def.has_dtor(bcx.tcx()) => {
ty::TyStruct(def, _) if def.has_dtor() => {
let repr = adt::represent_type(bcx.ccx(), ty);
adt::trans_set_discr(bcx, &*repr, lldest, 0);
}

View File

@ -356,7 +356,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
traits::VtableImpl(data) => data,
_ => tcx.sess.bug(&format!("dtor for {:?} is not an impl???", t))
};
let dtor_did = tcx.destructor_for_type.borrow()[&def.did];
let dtor_did = def.destructor().unwrap();
let datum = callee::trans_fn_ref_with_substs(bcx.ccx(),
dtor_did,
ExprId(0),
@ -534,9 +534,8 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
}
}
ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
let tcx = bcx.tcx();
match (tcx.ty_dtor(def.did), skip_dtor) {
(ty::TraitDtor(_, true), false) => {
match (def.dtor_kind(), skip_dtor) {
(ty::TraitDtor(true), false) => {
// FIXME(16758) Since the struct is unsized, it is hard to
// find the drop flag (which is at the end of the struct).
// Lets just ignore the flag and pretend everything will be
@ -552,7 +551,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
trans_struct_drop(bcx, t, v0)
}
}
(ty::TraitDtor(_, false), false) => {
(ty::TraitDtor(false), false) => {
trans_struct_drop(bcx, t, v0)
}
(ty::NoDtor, _) | (_, true) => {

View File

@ -311,9 +311,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
match self_type.ty.sty {
ty::TyEnum(type_def, _) |
ty::TyStruct(type_def, _) => {
tcx.destructor_for_type
.borrow_mut()
.insert(type_def.did, method_def_id.def_id());
type_def.set_destructor(method_def_id.def_id());
tcx.destructors
.borrow_mut()
.insert(method_def_id.def_id());