Skip to content

Commit b46c1a9

Browse files
committed
move needs_drop into a query
1 parent 5a5c265 commit b46c1a9

File tree

3 files changed

+86
-106
lines changed

3 files changed

+86
-106
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub enum DepNode<D: Clone + Debug> {
111111
IsCopy(D),
112112
IsSized(D),
113113
IsFreeze(D),
114+
NeedsDrop(D),
114115

115116
// The set of impls for a given trait. Ultimately, it would be
116117
// nice to get more fine-grained here (e.g., to include a
@@ -240,6 +241,7 @@ impl<D: Clone + Debug> DepNode<D> {
240241
IsCopy(ref d) => op(d).map(IsCopy),
241242
IsSized(ref d) => op(d).map(IsSized),
242243
IsFreeze(ref d) => op(d).map(IsFreeze),
244+
NeedsDrop(ref d) => op(d).map(NeedsDrop),
243245
Hir(ref d) => op(d).map(Hir),
244246
HirBody(ref d) => op(d).map(HirBody),
245247
MetaData(ref d) => op(d).map(MetaData),

src/librustc/ty/maps.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
271271
}
272272
}
273273

274+
impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
275+
fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
276+
format!("computing whether `{}` needs drop", env.value)
277+
}
278+
}
279+
274280
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
275281
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
276282
format!("computing the supertraits of `{}`",
@@ -891,6 +897,7 @@ define_maps! { <'tcx>
891897
[] is_copy_raw: is_copy_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
892898
[] is_sized_raw: is_sized_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
893899
[] is_freeze_raw: is_freeze_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
900+
[] needs_drop_raw: needs_drop_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
894901
}
895902

896903
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -949,3 +956,8 @@ fn is_freeze_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> D
949956
let krate_def_id = DefId::local(CRATE_DEF_INDEX);
950957
DepNode::IsSized(krate_def_id)
951958
}
959+
960+
fn needs_drop_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
961+
let krate_def_id = DefId::local(CRATE_DEF_INDEX);
962+
DepNode::NeedsDrop(krate_def_id)
963+
}

src/librustc/ty/util.rs

Lines changed: 72 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ use hir::map::DefPathData;
1515
use infer::InferCtxt;
1616
use ich::{StableHashingContext, NodeIdHashingMode};
1717
use traits::{self, Reveal};
18-
use ty::{self, Ty, TyCtxt, TypeFlags, TypeFoldable};
18+
use ty::{self, Ty, TyCtxt, TypeFoldable};
1919
use ty::ParameterEnvironment;
2020
use ty::fold::TypeVisitor;
2121
use ty::layout::{Layout, LayoutError};
2222
use ty::subst::{Subst, Kind};
2323
use ty::TypeVariants::*;
2424
use util::common::ErrorReported;
25-
use util::nodemap::FxHashSet;
2625
use middle::lang_items;
2726

2827
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
@@ -754,110 +753,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
754753
tcx: TyCtxt<'a, 'tcx, 'tcx>,
755754
param_env: ty::ParameterEnvironment<'tcx>)
756755
-> bool {
757-
if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
758-
return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
759-
}
760-
761-
self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
762-
}
763-
764-
fn needs_drop_inner(&'tcx self,
765-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
766-
param_env: ty::ParameterEnvironment<'tcx>,
767-
stack: &mut FxHashSet<Ty<'tcx>>)
768-
-> bool {
769-
if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
770-
return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
771-
}
772-
773-
// This should be reported as an error by `check_representable`.
774-
//
775-
// Consider the type as not needing drop in the meanwhile to avoid
776-
// further errors.
777-
if let Some(_) = stack.replace(self) {
778-
return false;
779-
}
780-
781-
let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
782-
783-
// "Pop" the cycle detection "stack".
784-
stack.remove(self);
785-
786-
needs_drop
787-
}
788-
789-
fn needs_drop_uncached(&'tcx self,
790-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
791-
param_env: ty::ParameterEnvironment<'tcx>,
792-
stack: &mut FxHashSet<Ty<'tcx>>)
793-
-> bool {
794-
assert!(!self.needs_infer());
795-
796-
let result = match self.sty {
797-
// Fast-path for primitive types
798-
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
799-
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
800-
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
801-
ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
802-
803-
// Issue #22536: We first query type_moves_by_default. It sees a
804-
// normalized version of the type, and therefore will definitely
805-
// know whether the type implements Copy (and thus needs no
806-
// cleanup/drop/zeroing) ...
807-
_ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
808-
809-
// ... (issue #22536 continued) but as an optimization, still use
810-
// prior logic of asking for the structural "may drop".
811-
812-
// FIXME(#22815): Note that this is a conservative heuristic;
813-
// it may report that the type "may drop" when actual type does
814-
// not actually have a destructor associated with it. But since
815-
// the type absolutely did not have the `Copy` bound attached
816-
// (see above), it is sound to treat it as having a destructor.
817-
818-
// User destructors are the only way to have concrete drop types.
819-
ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
820-
821-
// Can refer to a type which may drop.
822-
// FIXME(eddyb) check this against a ParameterEnvironment.
823-
ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
824-
ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
825-
826-
// Structural recursion.
827-
ty::TyArray(ty, _) | ty::TySlice(ty) => {
828-
ty.needs_drop_inner(tcx, param_env, stack)
829-
}
830-
831-
ty::TyClosure(def_id, ref substs) => {
832-
substs.upvar_tys(def_id, tcx)
833-
.any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
834-
}
835-
836-
ty::TyTuple(ref tys, _) => {
837-
tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
838-
}
839-
840-
// unions don't have destructors regardless of the child types
841-
ty::TyAdt(def, _) if def.is_union() => false,
842-
843-
ty::TyAdt(def, substs) => {
844-
def.variants.iter().any(|v| {
845-
v.fields.iter().any(|f| {
846-
f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
847-
})
848-
})
849-
}
850-
};
851-
852-
if !self.has_param_types() && !self.has_self_ty() {
853-
self.flags.set(self.flags.get() | if result {
854-
TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
855-
} else {
856-
TypeFlags::NEEDS_DROP_CACHED
857-
});
858-
}
859-
860-
result
756+
tcx.needs_drop_raw(param_env.and(self))
861757
}
862758

863759
#[inline]
@@ -1075,11 +971,81 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1075971
.enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
1076972
}
1077973

974+
fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
975+
query: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>)
976+
-> bool
977+
{
978+
let (param_env, ty) = query.into_parts();
979+
980+
let needs_drop = |ty: Ty<'tcx>| -> bool {
981+
match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
982+
Ok(v) => v,
983+
Err(_) => {
984+
// Cycles should be reported as an error by `check_representable`.
985+
//
986+
// Consider the type as not needing drop in the meanwhile to avoid
987+
// further errors.
988+
false
989+
}
990+
}
991+
};
992+
993+
assert!(!ty.needs_infer());
994+
995+
match ty.sty {
996+
// Fast-path for primitive types
997+
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
998+
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
999+
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
1000+
ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
1001+
1002+
// Issue #22536: We first query type_moves_by_default. It sees a
1003+
// normalized version of the type, and therefore will definitely
1004+
// know whether the type implements Copy (and thus needs no
1005+
// cleanup/drop/zeroing) ...
1006+
_ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false,
1007+
1008+
// ... (issue #22536 continued) but as an optimization, still use
1009+
// prior logic of asking for the structural "may drop".
1010+
1011+
// FIXME(#22815): Note that this is a conservative heuristic;
1012+
// it may report that the type "may drop" when actual type does
1013+
// not actually have a destructor associated with it. But since
1014+
// the type absolutely did not have the `Copy` bound attached
1015+
// (see above), it is sound to treat it as having a destructor.
1016+
1017+
// User destructors are the only way to have concrete drop types.
1018+
ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
1019+
1020+
// Can refer to a type which may drop.
1021+
// FIXME(eddyb) check this against a ParameterEnvironment.
1022+
ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
1023+
ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
1024+
1025+
// Structural recursion.
1026+
ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty),
1027+
1028+
ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
1029+
1030+
ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
1031+
1032+
// unions don't have destructors regardless of the child types
1033+
ty::TyAdt(def, _) if def.is_union() => false,
1034+
1035+
ty::TyAdt(def, substs) =>
1036+
def.variants.iter().any(
1037+
|variant| variant.fields.iter().any(
1038+
|field| needs_drop(field.ty(tcx, substs)))),
1039+
}
1040+
}
1041+
1042+
10781043
pub fn provide(providers: &mut ty::maps::Providers) {
10791044
*providers = ty::maps::Providers {
10801045
is_copy_raw,
10811046
is_sized_raw,
10821047
is_freeze_raw,
1048+
needs_drop_raw,
10831049
..*providers
10841050
};
10851051
}

0 commit comments

Comments
 (0)