Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d23d87c

Browse files
committedDec 12, 2020
Stop generating code in mem::forget
Yes, the optimizer can remove it, but there's really no reason to bother emitting it in the first place. Not to mention that it all gets run in debug mode...
1 parent 7efc097 commit d23d87c

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed
 

‎library/core/src/intrinsics.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -838,8 +838,11 @@ extern "rust-intrinsic" {
838838

839839
/// Moves a value out of scope without running drop glue.
840840
///
841-
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
842-
/// `ManuallyDrop` instead.
841+
/// This is only strictly needed for [`mem::forget_unsized`]; normal [`mem::forget`]
842+
/// compiles fine just using `ManuallyDrop` instead.
843+
///
844+
/// As this does literally nothing, it's trivially const-safe.
845+
#[rustc_const_stable(feature = "const_forget_intrinsic", since = "1.50")]
843846
pub fn forget<T: ?Sized>(_: T);
844847

845848
/// Reinterprets the bits of a value of one type as another type.

‎library/core/src/mem/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,16 @@ pub use crate::intrinsics::transmute;
141141
#[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
142142
#[stable(feature = "rust1", since = "1.0.0")]
143143
pub const fn forget<T>(t: T) {
144-
let _ = ManuallyDrop::new(t);
144+
// Ideally this would just be
145+
// ```
146+
// let _ = ManuallyDrop::new(t);
147+
// ```
148+
// but as of 2020-12-12 that actually codegens the construction of the type,
149+
// which there's no reason to do. Please switch it back if things have changed and
150+
// the forget-is-nop codegen test confirms the intrinsic is no longer needed here.
151+
152+
// SAFETY: Forgetting is safe; it's just the intrinsic that isn't.
153+
unsafe { intrinsics::forget(t) }
145154
}
146155

147156
/// Like [`forget`], but also accepts unsized values.

‎src/test/codegen/forget-is-nop.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C opt-level=0
2+
3+
#![crate_type = "lib"]
4+
5+
// CHECK-LABEL: mem6forget{{.+}}[100 x %"std::string::String"]*
6+
// CHECK-NOT: alloca
7+
// CHECK-NOT: memcpy
8+
// CHECK: ret
9+
10+
// CHECK-LABEL: mem6forget{{.+}}[100 x i64]*
11+
// CHECK-NOT: alloca
12+
// CHECK-NOT: memcpy
13+
// CHECK: ret
14+
15+
pub fn forget_large_copy_type(whatever: [i64; 100]) {
16+
std::mem::forget(whatever)
17+
}
18+
19+
pub fn forget_large_drop_type(whatever: [String; 100]) {
20+
std::mem::forget(whatever)
21+
}

0 commit comments

Comments
 (0)
Please sign in to comment.