diff options
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/mod.rs | 10 | ||||
| -rw-r--r-- | src/test/codegen/function-arguments.rs | 20 |
3 files changed, 36 insertions, 9 deletions
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3c27e36795e..dde55dd9655 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2636,7 +2636,7 @@ where if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { PointerKind::UniqueBorrowed } else { - PointerKind::SharedMutable + PointerKind::UniqueBorrowedPinned } } } @@ -3255,10 +3255,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable // for the entire duration of the function as they can be deallocated - // at any time. Set their valid size to 0. + // at any time. Same for shared mutable references. If LLVM had a + // way to say "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::UniqueOwned => Size::ZERO, - _ => pointee.size, + PointerKind::UniqueBorrowed + | PointerKind::UniqueBorrowedPinned + | PointerKind::Frozen => pointee.size, + PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO, }; // `Box`, `&T`, and `&mut T` cannot be undef. @@ -3285,7 +3288,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // or not to actually emit the attribute. It can also be controlled with the // `-Zmutable-noalias` debugging option. let no_alias = match kind { - PointerKind::SharedMutable | PointerKind::UniqueBorrowed => false, + PointerKind::SharedMutable + | PointerKind::UniqueBorrowed + | PointerKind::UniqueBorrowedPinned => false, PointerKind::UniqueOwned => noalias_for_box, PointerKind::Frozen => !is_return, }; diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b8398daadf1..b35502d9ee4 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1352,13 +1352,17 @@ pub enum PointerKind { /// Most general case, we know no restrictions to tell LLVM. SharedMutable, - /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. + /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`. Frozen, - /// `&mut T` which is `noalias` but not `readonly`. + /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`. UniqueBorrowed, - /// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns. + /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`. + UniqueBorrowedPinned, + + /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly` + /// nor `dereferenceable`. UniqueOwned, } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index ae6abe7a184..dda139be6fc 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -5,6 +5,7 @@ use std::mem::MaybeUninit; use std::num::NonZeroU64; +use std::marker::PhantomPinned; pub struct S { _field: [i32; 8], @@ -14,6 +15,11 @@ pub struct UnsafeInner { _field: std::cell::UnsafeCell<i16>, } +pub struct NotUnpin { + _field: i32, + _marker: PhantomPinned, +} + pub enum MyBool { True, False, @@ -91,7 +97,7 @@ pub fn static_borrow(_: &'static i32) { pub fn named_borrow<'r>(_: &'r i32) { } -// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef align 2 dereferenceable(2) %_1) +// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef nonnull align 2 %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) { @@ -109,6 +115,18 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { pub fn mutable_borrow(_: &mut i32) { } +#[no_mangle] +// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1) +// This one is *not* `noalias` because it might be self-referential. +pub fn mutable_notunpin_borrow(_: &mut NotUnpin) { +} + +// CHECK: @notunpin_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1) +// But `&NotUnpin` behaves perfectly normal. +#[no_mangle] +pub fn notunpin_borrow(_: &NotUnpin) { +} + // CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { |
