Skip to content

Commit 0adfd81

Browse files
committed
rustc: combine type_needs_drop_given_env and may_drop into needs_drop.
1 parent 9ad3b94 commit 0adfd81

File tree

10 files changed

+68
-64
lines changed

10 files changed

+68
-64
lines changed

src/librustc/ty/mod.rs

+2-35
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ bitflags! {
425425
const MOVES_BY_DEFAULT = 1 << 19,
426426
const FREEZENESS_CACHED = 1 << 20,
427427
const IS_FREEZE = 1 << 21,
428-
const MAY_DROP_CACHED = 1 << 22,
429-
const MAY_DROP = 1 << 23,
428+
const NEEDS_DROP_CACHED = 1 << 22,
429+
const NEEDS_DROP = 1 << 23,
430430
}
431431
}
432432

@@ -2381,39 +2381,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23812381
Some(self.item_mir(did))
23822382
}
23832383

2384-
/// If `type_needs_drop` returns true, then `ty` is definitely
2385-
/// non-copy and *might* have a destructor attached; if it returns
2386-
/// false, then `ty` definitely has no destructor (i.e. no drop glue).
2387-
///
2388-
/// (Note that this implies that if `ty` has a destructor attached,
2389-
/// then `type_needs_drop` will definitely return `true` for `ty`.)
2390-
pub fn type_needs_drop_given_env(self,
2391-
ty: Ty<'gcx>,
2392-
param_env: &ty::ParameterEnvironment<'gcx>) -> bool {
2393-
// Issue #22536: We first query type_moves_by_default. It sees a
2394-
// normalized version of the type, and therefore will definitely
2395-
// know whether the type implements Copy (and thus needs no
2396-
// cleanup/drop/zeroing) ...
2397-
let tcx = self.global_tcx();
2398-
let implements_copy = !ty.moves_by_default(tcx, param_env, DUMMY_SP);
2399-
2400-
if implements_copy { return false; }
2401-
2402-
// ... (issue #22536 continued) but as an optimization, still use
2403-
// prior logic of asking for the structural `may_drop`.
2404-
2405-
// FIXME(#22815): Note that calling `ty::may_drop` is a
2406-
// conservative heuristic; it may report `true` ("may drop")
2407-
// when actual type does not actually have a destructor associated
2408-
// with it. But since `ty` absolutely did not have the `Copy`
2409-
// bound attached (see above), it is sound to treat it as having a
2410-
// destructor.
2411-
2412-
let may_drop = ty.may_drop(tcx);
2413-
debug!("type_needs_drop ty={:?} may_drop={:?}", ty, may_drop);
2414-
may_drop
2415-
}
2416-
24172384
/// Get the attributes of a definition.
24182385
pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
24192386
if let Some(id) = self.hir.as_local_node_id(did) {

src/librustc/ty/util.rs

+58-20
Original file line numberDiff line numberDiff line change
@@ -699,31 +699,52 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
699699
result
700700
}
701701

702+
/// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
703+
/// non-copy and *might* have a destructor attached; if it returns
704+
/// `false`, then `ty` definitely has no destructor (i.e. no drop glue).
705+
///
706+
/// (Note that this implies that if `ty` has a destructor attached,
707+
/// then `needs_drop` will definitely return `true` for `ty`.)
702708
#[inline]
703-
pub fn may_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
704-
if self.flags.get().intersects(TypeFlags::MAY_DROP_CACHED) {
705-
return self.flags.get().intersects(TypeFlags::MAY_DROP);
709+
pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
710+
param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
711+
if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
712+
return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
706713
}
707714

708-
self.may_drop_inner(tcx, &mut FxHashSet())
715+
self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
709716
}
710717

711-
fn may_drop_inner(&'tcx self,
712-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
713-
visited: &mut FxHashSet<Ty<'tcx>>)
714-
-> bool {
715-
if self.flags.get().intersects(TypeFlags::MAY_DROP_CACHED) {
716-
return self.flags.get().intersects(TypeFlags::MAY_DROP);
718+
fn needs_drop_inner(&'tcx self,
719+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
720+
param_env: &ty::ParameterEnvironment<'tcx>,
721+
stack: &mut FxHashSet<Ty<'tcx>>)
722+
-> bool {
723+
if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
724+
return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
717725
}
718726

719727
// This should be reported as an error by `check_representable`.
720728
//
721729
// Consider the type as not needing drop in the meanwhile to avoid
722730
// further errors.
723-
if visited.replace(self).is_some() {
731+
if let Some(_) = stack.replace(self) {
724732
return false;
725733
}
726734

735+
let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
736+
737+
// "Pop" the cycle detection "stack".
738+
stack.remove(self);
739+
740+
needs_drop
741+
}
742+
743+
fn needs_drop_uncached(&'tcx self,
744+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
745+
param_env: &ty::ParameterEnvironment<'tcx>,
746+
stack: &mut FxHashSet<Ty<'tcx>>)
747+
-> bool {
727748
assert!(!self.needs_infer());
728749

729750
let result = match self.sty {
@@ -733,6 +754,21 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
733754
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
734755
ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
735756

757+
// Issue #22536: We first query type_moves_by_default. It sees a
758+
// normalized version of the type, and therefore will definitely
759+
// know whether the type implements Copy (and thus needs no
760+
// cleanup/drop/zeroing) ...
761+
_ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
762+
763+
// ... (issue #22536 continued) but as an optimization, still use
764+
// prior logic of asking for the structural "may drop".
765+
766+
// FIXME(#22815): Note that this is a conservative heuristic;
767+
// it may report that the type "may drop" when actual type does
768+
// not actually have a destructor associated with it. But since
769+
// the type absolutely did not have the `Copy` bound attached
770+
// (see above), it is sound to treat it as having a destructor.
771+
736772
// User destructors are the only way to have concrete drop types.
737773
ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
738774

@@ -743,16 +779,16 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
743779

744780
// Structural recursion.
745781
ty::TyArray(ty, _) | ty::TySlice(ty) => {
746-
ty.may_drop_inner(tcx, visited)
782+
ty.needs_drop_inner(tcx, param_env, stack)
747783
}
748784

749785
ty::TyClosure(def_id, ref substs) => {
750786
substs.upvar_tys(def_id, tcx)
751-
.any(|ty| ty.may_drop_inner(tcx, visited))
787+
.any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
752788
}
753789

754790
ty::TyTuple(ref tys, _) => {
755-
tys.iter().any(|ty| ty.may_drop_inner(tcx, visited))
791+
tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
756792
}
757793

758794
// unions don't have destructors regardless of the child types
@@ -761,17 +797,19 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
761797
ty::TyAdt(def, substs) => {
762798
def.variants.iter().any(|v| {
763799
v.fields.iter().any(|f| {
764-
f.ty(tcx, substs).may_drop_inner(tcx, visited)
800+
f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
765801
})
766802
})
767803
}
768804
};
769805

770-
self.flags.set(self.flags.get() | if result {
771-
TypeFlags::MAY_DROP_CACHED | TypeFlags::MAY_DROP
772-
} else {
773-
TypeFlags::MAY_DROP_CACHED
774-
});
806+
if !self.has_param_types() && !self.has_self_ty() {
807+
self.flags.set(self.flags.get() | if result {
808+
TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
809+
} else {
810+
TypeFlags::NEEDS_DROP_CACHED
811+
});
812+
}
775813

776814
result
777815
}

src/librustc_borrowck/borrowck/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
322322
let ty = lvalue.ty(mir, tcx).to_ty(tcx);
323323
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
324324

325-
if tcx.type_needs_drop_given_env(ty, &ctxt.param_env) {
325+
if ty.needs_drop(tcx, &ctxt.param_env) {
326326
each_child(child);
327327
} else {
328328
debug!("on_all_drop_children_bits - skipping")

src/librustc_lint/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
11521152
let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
11531153
for field in vdata.fields() {
11541154
let field_ty = ctx.tcx.item_type(ctx.tcx.hir.local_def_id(field.id));
1155-
if ctx.tcx.type_needs_drop_given_env(field_ty, param_env) {
1155+
if field_ty.needs_drop(ctx.tcx, param_env) {
11561156
ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
11571157
field.span,
11581158
"union contains a field with possibly non-trivial drop code, \

src/librustc_mir/hair/cx/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
168168
type with inference types/regions",
169169
ty);
170170
});
171-
self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
171+
ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
172172
}
173173

174174
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {

src/librustc_mir/transform/inline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
357357
// a regular goto.
358358
let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
359359
let ty = ty.to_ty(tcx);
360-
if tcx.type_needs_drop_given_env(ty, &param_env) {
360+
if ty.needs_drop(tcx, &param_env) {
361361
cost += CALL_PENALTY;
362362
if let Some(unwind) = unwind {
363363
work_list.push(unwind);

src/librustc_mir/transform/qualify_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'a, 'tcx> Qualif {
8383
if ty.is_freeze(tcx, param_env, DUMMY_SP) {
8484
*self = *self - Qualif::MUTABLE_INTERIOR;
8585
}
86-
if !tcx.type_needs_drop_given_env(ty, param_env) {
86+
if !ty.needs_drop(tcx, param_env) {
8787
*self = *self - Qualif::NEEDS_DROP;
8888
}
8989
}

src/librustc_mir/util/elaborate_drops.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
277277

278278
let mut fields = fields;
279279
fields.retain(|&(ref lvalue, _)| {
280-
self.tcx().type_needs_drop_given_env(
281-
self.lvalue_ty(lvalue), self.elaborator.param_env())
280+
self.lvalue_ty(lvalue).needs_drop(self.tcx(), self.elaborator.param_env())
282281
});
283282

284283
debug!("drop_ladder - fields needing drop: {:?}", fields);

src/librustc_passes/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
8989
self.promotable = false;
9090
}
9191

92-
if self.tcx.type_needs_drop_given_env(ty, &self.param_env) {
92+
if ty.needs_drop(self.tcx, &self.param_env) {
9393
self.promotable = false;
9494
}
9595
}

src/librustc_trans/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
392392
}
393393

394394
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
395-
self.tcx.type_needs_drop_given_env(ty, &self.empty_param_env)
395+
ty.needs_drop(self.tcx, &self.empty_param_env)
396396
}
397397

398398
pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {

0 commit comments

Comments
 (0)