Skip to content

Commit dc1f442

Browse files
committed
Auto merge of #30492 - wesleywiser:fix_extra_drops, r=pnkfelix
Fixes #28159
2 parents bd58fd8 + 8c897ee commit dc1f442

File tree

5 files changed

+44
-55
lines changed

5 files changed

+44
-55
lines changed

src/librustc/middle/ty/mod.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use std::vec::IntoIter;
4646
use std::collections::{HashMap, HashSet};
4747
use syntax::ast::{self, CrateNum, Name, NodeId};
4848
use syntax::attr::{self, AttrMetaMethods};
49-
use syntax::codemap::Span;
49+
use syntax::codemap::{DUMMY_SP, Span};
5050
use syntax::parse::token::{InternedString, special_idents};
5151

5252
use rustc_front::hir;
@@ -2394,6 +2394,39 @@ impl<'tcx> ctxt<'tcx> {
23942394
|| self.sess.cstore.item_super_predicates(self, did))
23952395
}
23962396

2397+
/// If `type_needs_drop` returns true, then `ty` is definitely
2398+
/// non-copy and *might* have a destructor attached; if it returns
2399+
/// false, then `ty` definitely has no destructor (i.e. no drop glue).
2400+
///
2401+
/// (Note that this implies that if `ty` has a destructor attached,
2402+
/// then `type_needs_drop` will definitely return `true` for `ty`.)
2403+
pub fn type_needs_drop_given_env<'a>(&self,
2404+
ty: Ty<'tcx>,
2405+
param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool {
2406+
// Issue #22536: We first query type_moves_by_default. It sees a
2407+
// normalized version of the type, and therefore will definitely
2408+
// know whether the type implements Copy (and thus needs no
2409+
// cleanup/drop/zeroing) ...
2410+
let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP);
2411+
2412+
if implements_copy { return false; }
2413+
2414+
// ... (issue #22536 continued) but as an optimization, still use
2415+
// prior logic of asking if the `needs_drop` bit is set; we need
2416+
// not zero non-Copy types if they have no destructor.
2417+
2418+
// FIXME(#22815): Note that calling `ty::type_contents` is a
2419+
// conservative heuristic; it may report that `needs_drop` is set
2420+
// when actual type does not actually have a destructor associated
2421+
// with it. But since `ty` absolutely did not have the `Copy`
2422+
// bound attached (see above), it is sound to treat it as having a
2423+
// destructor (e.g. zero its memory on move).
2424+
2425+
let contents = ty.type_contents(self);
2426+
debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
2427+
contents.needs_drop(self)
2428+
}
2429+
23972430
/// Get the attributes of a definition.
23982431
pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> {
23992432
if let Some(id) = self.map.as_local_node_id(did) {

src/librustc_mir/build/scope.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
248248
kind: DropKind,
249249
lvalue: &Lvalue<'tcx>,
250250
lvalue_ty: Ty<'tcx>) {
251-
if self.hir.needs_drop(lvalue_ty, span) {
251+
if self.hir.needs_drop(lvalue_ty) {
252252
match self.scopes.iter_mut().rev().find(|s| s.extent == extent) {
253253
Some(scope) => {
254254
scope.drops.push((kind, span, lvalue.clone()));

src/librustc_mir/hair/cx/mod.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,8 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
9090
.collect()
9191
}
9292

93-
pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool {
94-
if self.infcx.type_moves_by_default(ty, span) {
95-
// FIXME(#21859) we should do an add'l check here to determine if
96-
// any dtor will execute, but the relevant fn
97-
// (`type_needs_drop`) is currently factored into
98-
// `librustc_trans`, so we can't easily do so.
99-
true
100-
} else {
101-
// if type implements Copy, cannot require drop
102-
false
103-
}
93+
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
94+
self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
10495
}
10596

10697
pub fn span_bug(&mut self, span: Span, message: &str) -> ! {

src/librustc_trans/trans/common.rs

+1-40
Original file line numberDiff line numberDiff line change
@@ -73,45 +73,6 @@ pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
7373
}
7474
}
7575

76-
/// If `type_needs_drop` returns true, then `ty` is definitely
77-
/// non-copy and *might* have a destructor attached; if it returns
78-
/// false, then `ty` definitely has no destructor (i.e. no drop glue).
79-
///
80-
/// (Note that this implies that if `ty` has a destructor attached,
81-
/// then `type_needs_drop` will definitely return `true` for `ty`.)
82-
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
83-
type_needs_drop_given_env(cx, ty, &cx.empty_parameter_environment())
84-
}
85-
86-
/// Core implementation of type_needs_drop, potentially making use of
87-
/// and/or updating caches held in the `param_env`.
88-
fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
89-
ty: Ty<'tcx>,
90-
param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool {
91-
// Issue #22536: We first query type_moves_by_default. It sees a
92-
// normalized version of the type, and therefore will definitely
93-
// know whether the type implements Copy (and thus needs no
94-
// cleanup/drop/zeroing) ...
95-
let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP);
96-
97-
if implements_copy { return false; }
98-
99-
// ... (issue #22536 continued) but as an optimization, still use
100-
// prior logic of asking if the `needs_drop` bit is set; we need
101-
// not zero non-Copy types if they have no destructor.
102-
103-
// FIXME(#22815): Note that calling `ty::type_contents` is a
104-
// conservative heuristic; it may report that `needs_drop` is set
105-
// when actual type does not actually have a destructor associated
106-
// with it. But since `ty` absolutely did not have the `Copy`
107-
// bound attached (see above), it is sound to treat it as having a
108-
// destructor (e.g. zero its memory on move).
109-
110-
let contents = ty.type_contents(cx);
111-
debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
112-
contents.needs_drop(cx)
113-
}
114-
11576
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
11677
match ty.sty {
11778
ty::TyStruct(def, substs) => {
@@ -518,7 +479,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
518479
/// This is the same as `common::type_needs_drop`, except that it
519480
/// may use or update caches within this `FunctionContext`.
520481
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
521-
type_needs_drop_given_env(self.ccx.tcx(), ty, &self.param_env)
482+
self.ccx.tcx().type_needs_drop_given_env(ty, &self.param_env)
522483
}
523484

524485
pub fn eh_personality(&self) -> ValueRef {

src/librustc_trans/trans/glue.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
8888
}
8989
}
9090

91+
fn type_needs_drop<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
92+
tcx.type_needs_drop_given_env(ty, &tcx.empty_parameter_environment())
93+
}
94+
9195
pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
9296
t: Ty<'tcx>) -> Ty<'tcx> {
9397
let tcx = ccx.tcx();
@@ -106,11 +110,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
106110
// returned `tcx.types.i8` does not appear unsound. The impact on
107111
// code quality is unknown at this time.)
108112

109-
if !type_needs_drop(tcx, t) {
113+
if !type_needs_drop(&tcx, t) {
110114
return tcx.types.i8;
111115
}
112116
match t.sty {
113-
ty::TyBox(typ) if !type_needs_drop(tcx, typ)
117+
ty::TyBox(typ) if !type_needs_drop(&tcx, typ)
114118
&& type_is_sized(tcx, typ) => {
115119
let llty = sizing_type_of(ccx, typ);
116120
// `Box<ZeroSizeType>` does not allocate.

0 commit comments

Comments
 (0)