Skip to content

Commit

Permalink
rustc: replace TypeContents::needs_drop with Ty::may_drop.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 20, 2017
1 parent 6563374 commit 9ad3b94
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 154 deletions.
139 changes: 0 additions & 139 deletions src/librustc/ty/contents.rs

This file was deleted.

4 changes: 0 additions & 4 deletions src/librustc/ty/context.rs
Expand Up @@ -436,9 +436,6 @@ pub struct GlobalCtxt<'tcx> {
// Internal cache for metadata decoding. No need to track deps on this.
pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,

// Cache for the type-contents routine. FIXME -- track deps?
pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>,

// FIXME dep tracking -- should be harmless enough
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,

Expand Down Expand Up @@ -708,7 +705,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
freevars: RefCell::new(resolutions.freevars),
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
rcache: RefCell::new(FxHashMap()),
tc_cache: RefCell::new(FxHashMap()),
normalized_cache: RefCell::new(FxHashMap()),
inhabitedness_cache: RefCell::new(FxHashMap()),
lang_items: lang_items,
Expand Down
19 changes: 9 additions & 10 deletions src/librustc/ty/mod.rs
Expand Up @@ -71,7 +71,6 @@ pub use self::sty::InferTy::*;
pub use self::sty::Region::*;
pub use self::sty::TypeVariants::*;

pub use self::contents::TypeContents;
pub use self::context::{TyCtxt, GlobalArenas, tls};
pub use self::context::{Lift, TypeckTables};

Expand Down Expand Up @@ -99,7 +98,6 @@ pub mod walk;
pub mod wf;
pub mod util;

mod contents;
mod context;
mod flags;
mod instance;
Expand Down Expand Up @@ -427,6 +425,8 @@ bitflags! {
const MOVES_BY_DEFAULT = 1 << 19,
const FREEZENESS_CACHED = 1 << 20,
const IS_FREEZE = 1 << 21,
const MAY_DROP_CACHED = 1 << 22,
const MAY_DROP = 1 << 23,
}
}

Expand Down Expand Up @@ -2400,19 +2400,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
if implements_copy { return false; }

// ... (issue #22536 continued) but as an optimization, still use
// prior logic of asking if the `needs_drop` bit is set; we need
// not zero non-Copy types if they have no destructor.
// prior logic of asking for the structural `may_drop`.

// FIXME(#22815): Note that calling `ty::type_contents` is a
// conservative heuristic; it may report that `needs_drop` is set
// FIXME(#22815): Note that calling `ty::may_drop` is a
// conservative heuristic; it may report `true` ("may drop")
// when actual type does not actually have a destructor associated
// with it. But since `ty` absolutely did not have the `Copy`
// bound attached (see above), it is sound to treat it as having a
// destructor (e.g. zero its memory on move).
// destructor.

let contents = ty.type_contents(tcx);
debug!("type_needs_drop ty={:?} contents={:?}", ty, contents.bits());
contents.needs_drop(tcx)
let may_drop = ty.may_drop(tcx);
debug!("type_needs_drop ty={:?} may_drop={:?}", ty, may_drop);
may_drop
}

/// Get the attributes of a definition.
Expand Down
79 changes: 78 additions & 1 deletion src/librustc/ty/util.rs
Expand Up @@ -21,7 +21,7 @@ use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::TypeVariants::*;
use util::common::ErrorReported;
use util::nodemap::FxHashMap;
use util::nodemap::{FxHashMap, FxHashSet};
use middle::lang_items;

use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
Expand Down Expand Up @@ -699,6 +699,83 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
result
}

#[inline]
pub fn may_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
if self.flags.get().intersects(TypeFlags::MAY_DROP_CACHED) {
return self.flags.get().intersects(TypeFlags::MAY_DROP);
}

self.may_drop_inner(tcx, &mut FxHashSet())
}

fn may_drop_inner(&'tcx self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
visited: &mut FxHashSet<Ty<'tcx>>)
-> bool {
if self.flags.get().intersects(TypeFlags::MAY_DROP_CACHED) {
return self.flags.get().intersects(TypeFlags::MAY_DROP);
}

// This should be reported as an error by `check_representable`.
//
// Consider the type as not needing drop in the meanwhile to avoid
// further errors.
if visited.replace(self).is_some() {
return false;
}

assert!(!self.needs_infer());

let result = match self.sty {
// Fast-path for primitive types
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,

// User destructors are the only way to have concrete drop types.
ty::TyAdt(def, _) if def.has_dtor(tcx) => true,

// Can refer to a type which may drop.
// FIXME(eddyb) check this against a ParameterEnvironment.
ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,

// Structural recursion.
ty::TyArray(ty, _) | ty::TySlice(ty) => {
ty.may_drop_inner(tcx, visited)
}

ty::TyClosure(def_id, ref substs) => {
substs.upvar_tys(def_id, tcx)
.any(|ty| ty.may_drop_inner(tcx, visited))
}

ty::TyTuple(ref tys, _) => {
tys.iter().any(|ty| ty.may_drop_inner(tcx, visited))
}

// unions don't have destructors regardless of the child types
ty::TyAdt(def, _) if def.is_union() => false,

ty::TyAdt(def, substs) => {
def.variants.iter().any(|v| {
v.fields.iter().any(|f| {
f.ty(tcx, substs).may_drop_inner(tcx, visited)
})
})
}
};

self.flags.set(self.flags.get() | if result {
TypeFlags::MAY_DROP_CACHED | TypeFlags::MAY_DROP
} else {
TypeFlags::MAY_DROP_CACHED
});

result
}

#[inline]
pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
-> Result<&'tcx Layout, LayoutError<'tcx>> {
Expand Down

0 comments on commit 9ad3b94

Please sign in to comment.