From 4953a8bc12b7133154efcba46cd9883112a4d8a3 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Thu, 6 Nov 2025 23:00:23 +0000 Subject: [PATCH] Constants of primitive types are always deterministic. --- compiler/rustc_middle/src/mir/consts.rs | 20 ++++++------- ...p_generic.PreCodegen.after.panic-abort.mir | 30 +++++++++---------- ..._generic.PreCodegen.after.panic-unwind.mir | 30 +++++++++---------- .../mir-opt/pre-codegen/drop_box_of_sized.rs | 6 ++-- ...ace.PreCodegen.after.32bit.panic-abort.mir | 20 +++++-------- ...ce.PreCodegen.after.32bit.panic-unwind.mir | 20 +++++-------- ...ace.PreCodegen.after.64bit.panic-abort.mir | 20 +++++-------- ...ce.PreCodegen.after.64bit.panic-unwind.mir | 20 +++++-------- tests/mir-opt/pre-codegen/drop_boxed_slice.rs | 5 ++-- 9 files changed, 74 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index afe39e4481ef..715e6e2917fc 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -478,6 +478,11 @@ pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self { /// Return true if any evaluation of this constant always returns the same value, /// taking into account even pointer identity tests. pub fn is_deterministic(&self) -> bool { + // Primitive types cannot contain provenance and always have the same value. + if self.ty().is_primitive() { + return true; + } + // Some constants may generate fresh allocations for pointers they contain, // so using the same constant twice can yield two different results. // Notably, valtrees purposefully generate new allocations. @@ -487,24 +492,19 @@ pub fn is_deterministic(&self) -> bool { // A valtree may be a reference. Valtree references correspond to a // different allocation each time they are evaluated. Valtrees for primitive // types are fine though. - ty::ConstKind::Value(cv) => cv.ty.is_primitive(), - ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false, + ty::ConstKind::Value(..) + | ty::ConstKind::Expr(..) + | ty::ConstKind::Unevaluated(..) // This can happen if evaluation of a constant failed. The result does not matter // much since compilation is doomed. - ty::ConstKind::Error(..) => false, + | ty::ConstKind::Error(..) => false, // Should not appear in runtime MIR. ty::ConstKind::Infer(..) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => bug!(), }, Const::Unevaluated(..) => false, - Const::Val( - ConstValue::Slice { .. } - | ConstValue::ZeroSized - | ConstValue::Scalar(_) - | ConstValue::Indirect { .. }, - _, - ) => true, + Const::Val(..) => true, } } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir index c446ab395f3e..fcb804cdbfd8 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir @@ -6,7 +6,7 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let _7: (); + let _5: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -24,7 +24,7 @@ fn drop_generic(_1: *mut Box) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _6: *mut u8; + let mut _4: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -44,8 +44,7 @@ fn drop_generic(_1: *mut Box) -> () { } } scope 7 (inlined Layout::for_value_raw::) { - let mut _3: usize; - let mut _5: std::ptr::Alignment; + let mut _3: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -53,7 +52,6 @@ fn drop_generic(_1: *mut Box) -> () { scope 9 (inlined size_of_val_raw::) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::) { - let _4: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -72,26 +70,26 @@ fn drop_generic(_1: *mut Box) -> () { bb0: { _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = const ::SIZE; - StorageLive(_4); - _4 = const ::ALIGN; - _5 = copy _4 as std::ptr::Alignment (Transmute); - StorageDead(_4); - switchInt(copy _3) -> [0: bb3, otherwise: bb1]; + _3 = const ::ALIGN as std::ptr::Alignment (Transmute); + switchInt(const ::SIZE) -> [0: bb4, otherwise: bb1]; } bb1: { - StorageLive(_6); - _6 = copy _2 as *mut u8 (Transmute); - _7 = alloc::alloc::__rust_dealloc(move _6, move _3, move _5) -> [return: bb2, unwind unreachable]; + switchInt(const ::SIZE) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_6); - goto -> bb3; + StorageLive(_4); + _4 = copy _2 as *mut u8 (Transmute); + _5 = alloc::alloc::__rust_dealloc(move _4, const ::SIZE, move _3) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_4); + goto -> bb4; + } + + bb4: { return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir index c446ab395f3e..fcb804cdbfd8 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir @@ -6,7 +6,7 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let _7: (); + let _5: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -24,7 +24,7 @@ fn drop_generic(_1: *mut Box) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _6: *mut u8; + let mut _4: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -44,8 +44,7 @@ fn drop_generic(_1: *mut Box) -> () { } } scope 7 (inlined Layout::for_value_raw::) { - let mut _3: usize; - let mut _5: std::ptr::Alignment; + let mut _3: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -53,7 +52,6 @@ fn drop_generic(_1: *mut Box) -> () { scope 9 (inlined size_of_val_raw::) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::) { - let _4: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -72,26 +70,26 @@ fn drop_generic(_1: *mut Box) -> () { bb0: { _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = const ::SIZE; - StorageLive(_4); - _4 = const ::ALIGN; - _5 = copy _4 as std::ptr::Alignment (Transmute); - StorageDead(_4); - switchInt(copy _3) -> [0: bb3, otherwise: bb1]; + _3 = const ::ALIGN as std::ptr::Alignment (Transmute); + switchInt(const ::SIZE) -> [0: bb4, otherwise: bb1]; } bb1: { - StorageLive(_6); - _6 = copy _2 as *mut u8 (Transmute); - _7 = alloc::alloc::__rust_dealloc(move _6, move _3, move _5) -> [return: bb2, unwind unreachable]; + switchInt(const ::SIZE) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageDead(_6); - goto -> bb3; + StorageLive(_4); + _4 = copy _2 as *mut u8 (Transmute); + _5 = alloc::alloc::__rust_dealloc(move _4, const ::SIZE, move _3) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_4); + goto -> bb4; + } + + bb4: { return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs index 1e2953aa46b7..088339b15c87 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs @@ -6,10 +6,8 @@ // EMIT_MIR drop_box_of_sized.drop_generic.PreCodegen.after.mir pub unsafe fn drop_generic(x: *mut Box) { // CHECK-LABEL: fn drop_generic - // CHECK: [[SIZE:_.+]] = const ::SIZE; - // CHECK: [[ALIGN:_.+]] = const ::ALIGN; - // CHECK: [[ALIGNMENT:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute) - // CHECK: alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[ALIGNMENT]]) + // CHECK: [[ALIGNMENT:_.+]] = const ::ALIGN as std::ptr::Alignment (Transmute) + // CHECK: alloc::alloc::__rust_dealloc({{.+}}, const ::SIZE, move [[ALIGNMENT]]) std::ptr::drop_in_place(x) } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index f8e575f490b0..f4794a974bf2 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let _8: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -26,7 +26,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _8: *mut u8; + let mut _7: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -47,7 +47,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } scope 7 (inlined Layout::for_value_raw::<[T]>) { let mut _5: usize; - let mut _7: std::ptr::Alignment; + let mut _6: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -55,7 +55,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 9 (inlined size_of_val_raw::<[T]>) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) { - let _6: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -82,22 +81,19 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } bb1: { - StorageLive(_6); - _6 = const ::ALIGN; - _7 = copy _6 as std::ptr::Alignment (Transmute); - StorageDead(_6); + _6 = const ::ALIGN as std::ptr::Alignment (Transmute); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageLive(_8); - _8 = copy _3 as *mut u8 (PtrToPtr); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _7) -> [return: bb3, unwind unreachable]; + StorageLive(_7); + _7 = copy _3 as *mut u8 (PtrToPtr); + _8 = alloc::alloc::__rust_dealloc(move _7, move _5, move _6) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); + StorageDead(_7); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index f8e575f490b0..f4794a974bf2 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let _8: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -26,7 +26,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _8: *mut u8; + let mut _7: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -47,7 +47,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } scope 7 (inlined Layout::for_value_raw::<[T]>) { let mut _5: usize; - let mut _7: std::ptr::Alignment; + let mut _6: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -55,7 +55,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 9 (inlined size_of_val_raw::<[T]>) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) { - let _6: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -82,22 +81,19 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } bb1: { - StorageLive(_6); - _6 = const ::ALIGN; - _7 = copy _6 as std::ptr::Alignment (Transmute); - StorageDead(_6); + _6 = const ::ALIGN as std::ptr::Alignment (Transmute); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageLive(_8); - _8 = copy _3 as *mut u8 (PtrToPtr); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _7) -> [return: bb3, unwind unreachable]; + StorageLive(_7); + _7 = copy _3 as *mut u8 (PtrToPtr); + _8 = alloc::alloc::__rust_dealloc(move _7, move _5, move _6) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); + StorageDead(_7); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index f8e575f490b0..f4794a974bf2 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let _8: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -26,7 +26,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _8: *mut u8; + let mut _7: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -47,7 +47,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } scope 7 (inlined Layout::for_value_raw::<[T]>) { let mut _5: usize; - let mut _7: std::ptr::Alignment; + let mut _6: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -55,7 +55,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 9 (inlined size_of_val_raw::<[T]>) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) { - let _6: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -82,22 +81,19 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } bb1: { - StorageLive(_6); - _6 = const ::ALIGN; - _7 = copy _6 as std::ptr::Alignment (Transmute); - StorageDead(_6); + _6 = const ::ALIGN as std::ptr::Alignment (Transmute); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageLive(_8); - _8 = copy _3 as *mut u8 (PtrToPtr); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _7) -> [return: bb3, unwind unreachable]; + StorageLive(_7); + _7 = copy _3 as *mut u8 (PtrToPtr); + _8 = alloc::alloc::__rust_dealloc(move _7, move _5, move _6) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); + StorageDead(_7); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index f8e575f490b0..f4794a974bf2 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let _8: (); scope 3 { scope 4 { scope 17 (inlined Layout::size) { @@ -26,7 +26,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _8: *mut u8; + let mut _7: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { @@ -47,7 +47,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } scope 7 (inlined Layout::for_value_raw::<[T]>) { let mut _5: usize; - let mut _7: std::ptr::Alignment; + let mut _6: std::ptr::Alignment; scope 8 { scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { } @@ -55,7 +55,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 9 (inlined size_of_val_raw::<[T]>) { } scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) { - let _6: usize; scope 11 { scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) { scope 14 (inlined core::ub_checks::check_language_ub) { @@ -82,22 +81,19 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } bb1: { - StorageLive(_6); - _6 = const ::ALIGN; - _7 = copy _6 as std::ptr::Alignment (Transmute); - StorageDead(_6); + _6 = const ::ALIGN as std::ptr::Alignment (Transmute); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - StorageLive(_8); - _8 = copy _3 as *mut u8 (PtrToPtr); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _7) -> [return: bb3, unwind unreachable]; + StorageLive(_7); + _7 = copy _3 as *mut u8 (PtrToPtr); + _8 = alloc::alloc::__rust_dealloc(move _7, move _5, move _6) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); + StorageDead(_7); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index ae10cfb0b171..9e56b310e818 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -9,8 +9,7 @@ pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { // CHECK-LABEL: fn generic_in_place(_1: *mut Box<[T]>) // CHECK: (inlined as Drop>::drop) // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> - // CHECK: [[ALIGN:_.+]] = const ::ALIGN; - // CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute); - // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[B]]) -> + // CHECK: [[ALIGN:_.+]] = const ::ALIGN as std::ptr::Alignment (Transmute); + // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[ALIGN]]) -> std::ptr::drop_in_place(ptr) }