From f71741bac41a5373791958d4a0a36c84d83b1bd5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 26 Oct 2022 15:12:19 -0700 Subject: [PATCH 01/11] [rustc_ty_utils] Add the LLVM `noalias` parameter attribute to `drop_in_place` in certain cases. LLVM can make use of the `noalias` parameter attribute on the parameter to `drop_in_place` in areas like argument promotion. Because the Rust compiler fully controls the code for `drop_in_place`, it can soundly deduce parameter attributes on it. In the case of a value that has a programmer-defined Drop implementation, we know that the first thing `drop_in_place` will do is pass a pointer to the object to `Drop::drop`. `Drop::drop` takes `&mut`, so it must be guaranteed that there are no pointers to the object upon entering that function. Therefore, it should be safe to mark `noalias` there. With this patch, we mark `noalias` only when the type is a value with a programmer-defined Drop implementation. This is possibly overly conservative, but I thought that proceeding cautiously was best in this instance. --- compiler/rustc_ty_utils/src/abi.rs | 36 +++++++++++++++++++++++++- tests/codegen/drop-in-place-noalias.rs | 34 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/drop-in-place-noalias.rs diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 442d041a8a7..9b0d34b8979 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -238,6 +238,7 @@ fn adjust_for_rust_scalar<'tcx>( layout: TyAndLayout<'tcx>, offset: Size, is_return: bool, + is_drop_target: bool, ) { // Booleans are always a noundef i1 that needs to be zero-extended. if scalar.is_bool() { @@ -307,6 +308,25 @@ fn adjust_for_rust_scalar<'tcx>( } } } + + // If this is the argument to `drop_in_place`, the contents of which we fully control as the + // compiler, then we may be able to mark that argument `noalias`. Currently, we're conservative + // and do so only if `drop_in_place` results in a direct call to the programmer's `drop` method. + // The `drop` method requires `&mut self`, so we're effectively just propagating the `noalias` + // guarantee from `drop` upward to `drop_in_place` in this case. + if is_drop_target { + match *layout.ty.kind() { + ty::RawPtr(inner) => { + if let ty::Adt(adt_def, _) = inner.ty.kind() { + if adt_def.destructor(cx.tcx()).is_some() { + debug!("marking drop_in_place argument as noalias"); + attrs.set(ArgAttribute::NoAlias); + } + } + } + _ => bug!("drop target isn't a raw pointer"), + } + } } // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) @@ -362,10 +382,16 @@ fn fn_abi_new_uncached<'tcx>( use SpecAbi::*; let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); + let is_drop_in_place = match (cx.tcx.lang_items().drop_in_place_fn(), fn_def_id) { + (Some(drop_in_place_fn), Some(fn_def_id)) => drop_in_place_fn == fn_def_id, + _ => false, + }; + let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { let span = tracing::debug_span!("arg_of"); let _entered = span.enter(); let is_return = arg_idx.is_none(); + let is_drop_target = is_drop_in_place && arg_idx == Some(0); let layout = cx.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { @@ -379,7 +405,15 @@ fn fn_abi_new_uncached<'tcx>( let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| { let mut attrs = ArgAttributes::new(); - adjust_for_rust_scalar(*cx, &mut attrs, scalar, *layout, offset, is_return); + adjust_for_rust_scalar( + *cx, + &mut attrs, + scalar, + *layout, + offset, + is_return, + is_drop_target, + ); attrs }); diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs new file mode 100644 index 00000000000..bd9de4ad972 --- /dev/null +++ b/tests/codegen/drop-in-place-noalias.rs @@ -0,0 +1,34 @@ +// Tests that the compiler can mark `drop_in_place` as `noalias` when safe to do so. + +#![crate_type="lib"] + +use std::hint::black_box; + +// CHECK: define{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias{{.*}}) + +#[repr(C)] +pub struct Foo { + a: i32, + b: i32, + c: i32, +} + +impl Drop for Foo { + #[inline(never)] + fn drop(&mut self) { + black_box(self.a); + } +} + +extern { + fn bar(); + fn baz(foo: Foo); +} + +pub fn haha() { + let foo = Foo { a: 1, b: 2, c: 3 }; + unsafe { + bar(); + baz(foo); + } +} From 74dd3cb15931d8d7785b14b12500f190adae2b5e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 26 Oct 2022 21:49:23 -0700 Subject: [PATCH 02/11] Fix noalias box test --- tests/codegen/noalias-box-off.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs index afd17c7c160..aef3fd73994 100644 --- a/tests/codegen/noalias-box-off.rs +++ b/tests/codegen/noalias-box-off.rs @@ -3,6 +3,6 @@ #![crate_type = "lib"] // CHECK-LABEL: @box_should_not_have_noalias_if_disabled( -// CHECK-NOT: noalias +// CHECK-NOT: noalias{{.*}}% #[no_mangle] pub fn box_should_not_have_noalias_if_disabled(_b: Box) {} From 21b8815b6cd74d307ebbdef7cf8c6de6b486c706 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 Nov 2022 15:24:39 -0800 Subject: [PATCH 03/11] Apply `noalias`, `nonnull`, `dereferenceable`, and `align` attributes unconditionally. We've done measurements with Miri and have determined that `noalias` shouldn't break code. The requirements that allow us to add dereferenceable and align have been long documented in the standard library documentation. --- compiler/rustc_ty_utils/src/abi.rs | 27 ++++++++++---------------- tests/codegen/drop-in-place-noalias.rs | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 9b0d34b8979..5bfb48cb5e0 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -307,24 +307,17 @@ fn adjust_for_rust_scalar<'tcx>( attrs.set(ArgAttribute::ReadOnly); } } - } - // If this is the argument to `drop_in_place`, the contents of which we fully control as the - // compiler, then we may be able to mark that argument `noalias`. Currently, we're conservative - // and do so only if `drop_in_place` results in a direct call to the programmer's `drop` method. - // The `drop` method requires `&mut self`, so we're effectively just propagating the `noalias` - // guarantee from `drop` upward to `drop_in_place` in this case. - if is_drop_target { - match *layout.ty.kind() { - ty::RawPtr(inner) => { - if let ty::Adt(adt_def, _) = inner.ty.kind() { - if adt_def.destructor(cx.tcx()).is_some() { - debug!("marking drop_in_place argument as noalias"); - attrs.set(ArgAttribute::NoAlias); - } - } - } - _ => bug!("drop target isn't a raw pointer"), + // If this is the argument to `drop_in_place`, the contents of which we fully control as the + // compiler, then we mark this argument as `noalias`, aligned, and dereferenceable. (The + // standard library documents the necessary requirements to uphold these attributes for code + // that calls this method directly.) This can enable better optimizations, such as argument + // promotion. + if is_drop_target { + attrs.set(ArgAttribute::NoAlias); + attrs.set(ArgAttribute::NonNull); + attrs.pointee_size = pointee.size; + attrs.pointee_align = Some(pointee.align); } } } diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs index bd9de4ad972..64ac8760456 100644 --- a/tests/codegen/drop-in-place-noalias.rs +++ b/tests/codegen/drop-in-place-noalias.rs @@ -4,7 +4,7 @@ use std::hint::black_box; -// CHECK: define{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias{{.*}}) +// CHECK: define{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias {{.*}} align 4 dereferenceable(12){{.*}}) #[repr(C)] pub struct Foo { From 2836e5541ae611483dd65d07956d5413fb5bae11 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 Nov 2022 15:40:46 -0800 Subject: [PATCH 04/11] Update documentation for `drop_in_place()` --- library/core/src/ptr/mod.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ecbf4e66fa4..7245feed672 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -437,14 +437,34 @@ /// /// # Safety /// -/// Behavior is undefined if any of the following conditions are violated: +/// Immediately upon executing, `drop_in_place` takes out a mutable borrow on the +/// pointed-to-value. Effectively, this function is implemented like so: +/// +/// ``` +/// # struct Foo { x: i32 } +/// fn drop_in_place(to_drop: *mut Foo) { +/// let mut value = &mut *to_drop; +/// // ... drop the fields of `value` ... +/// } +/// ``` +/// +/// This implies that the behavior is undefined if any of the following +/// conditions are violated: /// /// * `to_drop` must be [valid] for both reads and writes. /// -/// * `to_drop` must be properly aligned. +/// * `to_drop` must be properly aligned, even if T has size 0. /// -/// * The value `to_drop` points to must be valid for dropping, which may mean it must uphold -/// additional invariants - this is type-dependent. +/// * `to_drop` must be nonnull, even if T has size 0. +/// +/// * The value `to_drop` points to must be valid for dropping, which may mean +/// it must uphold additional invariants. These invariants depend on the type +/// of the value being dropped. For instance, when dropping a Box, the box's +/// pointer to the heap must be valid. +/// +/// * While `drop_in_place` is executing, the only way to access parts of +/// `to_drop` is through the `&mut self` references supplied to the +/// `Drop::drop` methods that `drop_in_place` invokes. /// /// Additionally, if `T` is not [`Copy`], using the pointed-to value after /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = @@ -452,8 +472,6 @@ /// again. [`write()`] can be used to overwrite data without causing it to be /// dropped. /// -/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned. -/// /// [valid]: self#safety /// /// # Examples From b2ef9f72233d9bc88cbdd5533b12079e87cbf0c5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 Nov 2022 21:08:52 -0800 Subject: [PATCH 05/11] Add missing "unsafe" to fix doctest --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 7245feed672..6b96c6929a6 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -442,7 +442,7 @@ /// /// ``` /// # struct Foo { x: i32 } -/// fn drop_in_place(to_drop: *mut Foo) { +/// unsafe fn drop_in_place(to_drop: *mut Foo) { /// let mut value = &mut *to_drop; /// // ... drop the fields of `value` ... /// } From 58c39999499b3bb8966387c47699ac694bbd7a1c Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 17:46:47 -0400 Subject: [PATCH 06/11] improve drop_in_place docs --- library/core/src/ptr/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6b96c6929a6..1a5519b9307 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -443,8 +443,10 @@ /// ``` /// # struct Foo { x: i32 } /// unsafe fn drop_in_place(to_drop: *mut Foo) { -/// let mut value = &mut *to_drop; -/// // ... drop the fields of `value` ... +/// drop_in_place_inner(&mut *to_drop); +/// unsafe fn drop_in_place_inner(to_drop: &mut Foo) { +/// // ... drop the fields of `value` ... +/// } /// } /// ``` /// @@ -453,9 +455,9 @@ /// /// * `to_drop` must be [valid] for both reads and writes. /// -/// * `to_drop` must be properly aligned, even if T has size 0. +/// * `to_drop` must be properly aligned, even if `T` has size 0. /// -/// * `to_drop` must be nonnull, even if T has size 0. +/// * `to_drop` must be nonnull, even if `T` has size 0. /// /// * The value `to_drop` points to must be valid for dropping, which may mean /// it must uphold additional invariants. These invariants depend on the type From 47444d7c2559f4a82ec2d5ca65d86ad795e48aef Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 17:54:31 -0400 Subject: [PATCH 07/11] improve code checking for drop_in_place lang item --- compiler/rustc_ty_utils/src/abi.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 5bfb48cb5e0..b7d4d90f109 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -375,10 +375,8 @@ fn fn_abi_new_uncached<'tcx>( use SpecAbi::*; let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); - let is_drop_in_place = match (cx.tcx.lang_items().drop_in_place_fn(), fn_def_id) { - (Some(drop_in_place_fn), Some(fn_def_id)) => drop_in_place_fn == fn_def_id, - _ => false, - }; + let is_drop_in_place = + fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn(); let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { let span = tracing::debug_span!("arg_of"); From 644818351b95c7a50eb05d73164cc6f4480ce9e7 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 19:34:31 -0400 Subject: [PATCH 08/11] ensure !Unpin types do not get noalias --- compiler/rustc_ty_utils/src/abi.rs | 36 +++++++++++----------- tests/codegen/drop-in-place-noalias.rs | 42 ++++++++++++++------------ 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index b7d4d90f109..15c19104616 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -238,7 +238,7 @@ fn adjust_for_rust_scalar<'tcx>( layout: TyAndLayout<'tcx>, offset: Size, is_return: bool, - is_drop_target: bool, + drop_target_pointee: Option>, ) { // Booleans are always a noundef i1 that needs to be zero-extended. if scalar.is_bool() { @@ -252,14 +252,24 @@ fn adjust_for_rust_scalar<'tcx>( } // Only pointer types handled below. - let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return }; + let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return }; - if !valid_range.contains(0) { + // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`, + // which must be nonnull per its documented safety requirements. + if !valid_range.contains(0) || drop_target_pointee.is_some() { attrs.set(ArgAttribute::NonNull); } if let Some(pointee) = layout.pointee_info_at(&cx, offset) { - if let Some(kind) = pointee.safe { + let kind = if let Some(kind) = pointee.safe { + Some(kind) + } else if let Some(pointee) = drop_target_pointee { + // The argument to `drop_in_place` is semantically equivalent to a mutable reference. + Some(PointerKind::MutableRef { unpin: pointee.is_unpin(cx.tcx, cx.param_env()) }) + } else { + None + }; + if let Some(kind) = kind { attrs.pointee_align = Some(pointee.align); // `Box` are not necessarily dereferenceable for the entire duration of the function as @@ -307,18 +317,6 @@ fn adjust_for_rust_scalar<'tcx>( attrs.set(ArgAttribute::ReadOnly); } } - - // If this is the argument to `drop_in_place`, the contents of which we fully control as the - // compiler, then we mark this argument as `noalias`, aligned, and dereferenceable. (The - // standard library documents the necessary requirements to uphold these attributes for code - // that calls this method directly.) This can enable better optimizations, such as argument - // promotion. - if is_drop_target { - attrs.set(ArgAttribute::NoAlias); - attrs.set(ArgAttribute::NonNull); - attrs.pointee_size = pointee.size; - attrs.pointee_align = Some(pointee.align); - } } } @@ -383,6 +381,10 @@ fn fn_abi_new_uncached<'tcx>( let _entered = span.enter(); let is_return = arg_idx.is_none(); let is_drop_target = is_drop_in_place && arg_idx == Some(0); + let drop_target_pointee = is_drop_target.then(|| match ty.kind() { + ty::RawPtr(ty::TypeAndMut { ty, .. }) => *ty, + _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty), + }); let layout = cx.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { @@ -403,7 +405,7 @@ fn fn_abi_new_uncached<'tcx>( *layout, offset, is_return, - is_drop_target, + drop_target_pointee, ); attrs }); diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs index 64ac8760456..74d40c13c4c 100644 --- a/tests/codegen/drop-in-place-noalias.rs +++ b/tests/codegen/drop-in-place-noalias.rs @@ -1,34 +1,38 @@ -// Tests that the compiler can mark `drop_in_place` as `noalias` when safe to do so. +// compile-flags: -C no-prepopulate-passes + +// Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. +// Note that non-Unpin types should not get `noalias`, matching &mut behavior. #![crate_type="lib"] -use std::hint::black_box; +use std::marker::PhantomPinned; -// CHECK: define{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias {{.*}} align 4 dereferenceable(12){{.*}}) +// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}({{.*\*|ptr}} noalias noundef align 4 dereferenceable(12) %{{.+}}) -#[repr(C)] -pub struct Foo { +// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}({{.*\*|ptr}} noundef nonnull align 4 %{{.+}}) + +pub struct StructUnpin { a: i32, b: i32, c: i32, } -impl Drop for Foo { - #[inline(never)] - fn drop(&mut self) { - black_box(self.a); - } +impl Drop for StructUnpin { + fn drop(&mut self) {} } -extern { - fn bar(); - fn baz(foo: Foo); +pub struct StructNotUnpin { + a: i32, + b: i32, + c: i32, + p: PhantomPinned, } -pub fn haha() { - let foo = Foo { a: 1, b: 2, c: 3 }; - unsafe { - bar(); - baz(foo); - } +impl Drop for StructNotUnpin { + fn drop(&mut self) {} +} + +pub unsafe fn main(x: StructUnpin, y: StructNotUnpin) { + drop(x); + drop(y); } From c4d69b717f7dc6a469a65a1194ccdba2a833fefc Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 19:41:28 -0400 Subject: [PATCH 09/11] make noalias-box-off filecheck more precise The CHECK, -NOT, -SAME pattern ensures that the `CHECK-NOT: noalias` is limited to only one line, and won't match unrelated lines further down in the file. Explicit drop call added to preserve the `foo` argument name, since names of unused arguments are not preserved. --- tests/codegen/noalias-box-off.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs index aef3fd73994..c82c53b2a48 100644 --- a/tests/codegen/noalias-box-off.rs +++ b/tests/codegen/noalias-box-off.rs @@ -3,6 +3,9 @@ #![crate_type = "lib"] // CHECK-LABEL: @box_should_not_have_noalias_if_disabled( -// CHECK-NOT: noalias{{.*}}% +// CHECK-NOT: noalias +// CHECK-SAME: %foo) #[no_mangle] -pub fn box_should_not_have_noalias_if_disabled(_b: Box) {} +pub fn box_should_not_have_noalias_if_disabled(foo: Box) { + drop(foo); +} From 340827af9bcc140cbf3273a4a7f7b2628584f7a1 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 21 May 2023 11:34:01 -0400 Subject: [PATCH 10/11] drop_in_place docs: remove pseudocode-ish implementation details --- library/core/src/ptr/mod.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 1a5519b9307..ff9fa48f311 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -437,21 +437,7 @@ /// /// # Safety /// -/// Immediately upon executing, `drop_in_place` takes out a mutable borrow on the -/// pointed-to-value. Effectively, this function is implemented like so: -/// -/// ``` -/// # struct Foo { x: i32 } -/// unsafe fn drop_in_place(to_drop: *mut Foo) { -/// drop_in_place_inner(&mut *to_drop); -/// unsafe fn drop_in_place_inner(to_drop: &mut Foo) { -/// // ... drop the fields of `value` ... -/// } -/// } -/// ``` -/// -/// This implies that the behavior is undefined if any of the following -/// conditions are violated: +/// Behavior is undefined if any of the following conditions are violated: /// /// * `to_drop` must be [valid] for both reads and writes. /// From fb7f1d220c28dd86000d52f846ceb9055ae0ace4 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 22 May 2023 20:20:45 -0400 Subject: [PATCH 11/11] drop-in-place-noalias test: needs -O to ensure attributes are added on nopt builders --- tests/codegen/drop-in-place-noalias.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs index 74d40c13c4c..725e6fc048d 100644 --- a/tests/codegen/drop-in-place-noalias.rs +++ b/tests/codegen/drop-in-place-noalias.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes // Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. // Note that non-Unpin types should not get `noalias`, matching &mut behavior.