mirror of https://github.com/rust-lang/rust.git
do not mark interior mutable shared refs as dereferenceable
This commit is contained in:
parent
307e80c1a6
commit
5b7197af7f
|
@ -2636,7 +2636,7 @@ where
|
||||||
if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) {
|
if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) {
|
||||||
PointerKind::UniqueBorrowed
|
PointerKind::UniqueBorrowed
|
||||||
} else {
|
} else {
|
||||||
PointerKind::SharedMutable
|
PointerKind::UniqueBorrowedPinned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3255,10 +3255,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
// `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
|
// `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
|
||||||
// for the entire duration of the function as they can be deallocated
|
// 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 {
|
attrs.pointee_size = match kind {
|
||||||
PointerKind::UniqueOwned => Size::ZERO,
|
PointerKind::UniqueBorrowed
|
||||||
_ => pointee.size,
|
| PointerKind::UniqueBorrowedPinned
|
||||||
|
| PointerKind::Frozen => pointee.size,
|
||||||
|
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
|
||||||
};
|
};
|
||||||
|
|
||||||
// `Box`, `&T`, and `&mut T` cannot be undef.
|
// `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
|
// or not to actually emit the attribute. It can also be controlled with the
|
||||||
// `-Zmutable-noalias` debugging option.
|
// `-Zmutable-noalias` debugging option.
|
||||||
let no_alias = match kind {
|
let no_alias = match kind {
|
||||||
PointerKind::SharedMutable | PointerKind::UniqueBorrowed => false,
|
PointerKind::SharedMutable
|
||||||
|
| PointerKind::UniqueBorrowed
|
||||||
|
| PointerKind::UniqueBorrowedPinned => false,
|
||||||
PointerKind::UniqueOwned => noalias_for_box,
|
PointerKind::UniqueOwned => noalias_for_box,
|
||||||
PointerKind::Frozen => !is_return,
|
PointerKind::Frozen => !is_return,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1352,13 +1352,17 @@ pub enum PointerKind {
|
||||||
/// Most general case, we know no restrictions to tell LLVM.
|
/// Most general case, we know no restrictions to tell LLVM.
|
||||||
SharedMutable,
|
SharedMutable,
|
||||||
|
|
||||||
/// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
|
/// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
|
||||||
Frozen,
|
Frozen,
|
||||||
|
|
||||||
/// `&mut T` which is `noalias` but not `readonly`.
|
/// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
|
||||||
UniqueBorrowed,
|
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,
|
UniqueOwned,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
|
use std::marker::PhantomPinned;
|
||||||
|
|
||||||
pub struct S {
|
pub struct S {
|
||||||
_field: [i32; 8],
|
_field: [i32; 8],
|
||||||
|
@ -14,6 +15,11 @@ pub struct UnsafeInner {
|
||||||
_field: std::cell::UnsafeCell<i16>,
|
_field: std::cell::UnsafeCell<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NotUnpin {
|
||||||
|
_field: i32,
|
||||||
|
_marker: PhantomPinned,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum MyBool {
|
pub enum MyBool {
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
@ -91,7 +97,7 @@ pub fn static_borrow(_: &'static i32) {
|
||||||
pub fn named_borrow<'r>(_: &'r 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 ...
|
// unsafe interior means this isn't actually readonly and there may be aliases ...
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn unsafe_borrow(_: &UnsafeInner) {
|
pub fn unsafe_borrow(_: &UnsafeInner) {
|
||||||
|
@ -109,6 +115,18 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
|
||||||
pub fn mutable_borrow(_: &mut i32) {
|
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)
|
// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef dereferenceable(32) %_1)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn indirect_struct(_: S) {
|
pub fn indirect_struct(_: S) {
|
||||||
|
|
Loading…
Reference in New Issue