Skip to content

Commit c20717e

Browse files
committed
Lower core::ops::drop directly to MIR drop
This change causes drop() to always drop in-place. This is meant to allow internal optimizations (see rust-lang#62508). This does _not_ change the documented contract for drop(). Only internal compiler code is allowed to rely on this for now.
1 parent 95b1fe5 commit c20717e

File tree

8 files changed

+60
-30
lines changed

8 files changed

+60
-30
lines changed

src/libcore/mem/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
693693
/// [`Copy`]: ../../std/marker/trait.Copy.html
694694
#[inline]
695695
#[stable(feature = "rust1", since = "1.0.0")]
696+
#[cfg_attr(not(bootstrap), lang = "drop")]
696697
pub fn drop<T>(_x: T) { }
697698

698699
/// Interprets `src` as having type `&U`, and then reads `src` without moving

src/libcore/ops/drop.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@
8080
/// let _second = PrintOnDrop("Declared second!");
8181
/// }
8282
/// ```
83-
#[lang = "drop"]
83+
#[cfg_attr(not(bootstrap), lang = "drop_trait")]
84+
#[cfg_attr(bootstrap, lang = "drop")]
8485
#[stable(feature = "rust1", since = "1.0.0")]
8586
pub trait Drop {
8687
/// Executes the destructor for this type.

src/librustc/middle/lang_items.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ language_item_table! {
279279
SyncTraitLangItem, "sync", sync_trait, Target::Trait;
280280
FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait;
281281

282-
DropTraitLangItem, "drop", drop_trait, Target::Trait;
282+
DropTraitLangItem, "drop_trait", drop_trait, Target::Trait;
283283

284284
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
285285
DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait;
@@ -349,6 +349,7 @@ language_item_table! {
349349

350350
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn, Target::Fn;
351351
BoxFreeFnLangItem, "box_free", box_free_fn, Target::Fn;
352+
DropFnLangItem, "drop", drop_fn, Target::Fn;
352353
DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn, Target::Fn;
353354
OomLangItem, "oom", oom, Target::Fn;
354355
AllocLayoutLangItem, "alloc_layout", alloc_layout, Target::Struct;

src/librustc_mir/build/expr/into.rs

+46-21
Original file line numberDiff line numberDiff line change
@@ -191,16 +191,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
191191
exit_block.unit()
192192
}
193193
ExprKind::Call { ty, fun, args, from_hir_call } => {
194-
let intrinsic = match ty.sty {
194+
let (fn_def_id, intrinsic) = match ty.sty {
195195
ty::FnDef(def_id, _) => {
196196
let f = ty.fn_sig(this.hir.tcx());
197197
if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
198-
Some(this.hir.tcx().item_name(def_id).as_str())
198+
(Some(def_id), Some(this.hir.tcx().item_name(def_id).as_str()))
199199
} else {
200-
None
200+
(Some(def_id), None)
201201
}
202202
}
203-
_ => None,
203+
_ => (None, None),
204204
};
205205
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
206206
let fun = unpack!(block = this.as_local_operand(block, fun));
@@ -237,26 +237,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
237237
.map(|arg| unpack!(block = this.as_local_operand(block, arg)))
238238
.collect();
239239

240+
let drop_location = if fn_def_id.is_some()
241+
&& this.hir.tcx().lang_items().drop_fn() == fn_def_id
242+
{
243+
assert_eq!(args.len(), 1, "drop() must have exactly one argument");
244+
match &args[0] {
245+
Operand::Move(place) => Some(place.clone()),
246+
_ => None,
247+
}
248+
} else {
249+
None
250+
};
251+
240252
let success = this.cfg.start_new_block();
241253
let cleanup = this.diverge_cleanup();
242-
this.cfg.terminate(
243-
block,
244-
source_info,
245-
TerminatorKind::Call {
246-
func: fun,
247-
args,
248-
cleanup: Some(cleanup),
249-
// FIXME(varkor): replace this with an uninhabitedness-based check.
250-
// This requires getting access to the current module to call
251-
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
252-
destination: if expr.ty.is_never() {
253-
None
254-
} else {
255-
Some((destination.clone(), success))
254+
255+
if let Some(location) = drop_location {
256+
this.cfg.terminate(
257+
block,
258+
source_info,
259+
TerminatorKind::Drop {
260+
location,
261+
target: success,
262+
unwind: Some(cleanup)
256263
},
257-
from_hir_call,
258-
},
259-
);
264+
);
265+
} else {
266+
this.cfg.terminate(
267+
block,
268+
source_info,
269+
TerminatorKind::Call {
270+
func: fun,
271+
args,
272+
cleanup: Some(cleanup),
273+
// FIXME(varkor): replace this with an uninhabitedness-based check.
274+
// This requires getting access to the current module to call
275+
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
276+
destination: if expr.ty.is_never() {
277+
None
278+
} else {
279+
Some((destination.clone(), success))
280+
},
281+
from_hir_call,
282+
},
283+
);
284+
}
260285
success.unit()
261286
}
262287
}

src/test/mir-opt/box_expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl Drop for S {
5353
// StorageLive(_3);
5454
// StorageLive(_4);
5555
// _4 = move _1;
56-
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
56+
// drop(_4) -> [return: bb5, unwind: bb7];
5757
// }
5858
//
5959
// bb5: {

src/test/mir-opt/issue-49232.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn main() {
7676
// StorageLive(_5);
7777
// StorageLive(_6);
7878
// _6 = &_2;
79-
// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4];
79+
// drop(_6) -> [return: bb13, unwind: bb4];
8080
// }
8181
// bb13: {
8282
// StorageDead(_6);

src/test/ui/type_length_limit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ link! { F, G }
2222

2323
pub struct G;
2424

25+
fn take<T>(x: T) {}
26+
2527
fn main() {
26-
drop::<Option<A>>(None);
28+
take::<Option<A>>(None);
2729
}

src/test/ui/type_length_limit.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
2-
--> $SRC_DIR/libcore/mem/mod.rs:LL:COL
1+
error: reached the type-length limit while instantiating `take::<std::option::Option<(((((... G), (G, G, G), (G, G, G))))))>>`
2+
--> $DIR/type_length_limit.rs:25:1
33
|
4-
LL | pub fn drop<T>(_x: T) { }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | fn take<T>(x: T) {}
5+
| ^^^^^^^^^^^^^^^^^^^
66
|
77
= note: consider adding a `#![type_length_limit="1094"]` attribute to your crate
88

0 commit comments

Comments
 (0)