Skip to content

Commit 5b7197a

Browse files
committed
do not mark interior mutable shared refs as dereferenceable
1 parent 307e80c commit 5b7197a

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

compiler/rustc_middle/src/ty/layout.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -2636,7 +2636,7 @@ where
26362636
if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) {
26372637
PointerKind::UniqueBorrowed
26382638
} else {
2639-
PointerKind::SharedMutable
2639+
PointerKind::UniqueBorrowedPinned
26402640
}
26412641
}
26422642
}
@@ -3255,10 +3255,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32553255

32563256
// `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
32573257
// for the entire duration of the function as they can be deallocated
3258-
// at any time. Set their valid size to 0.
3258+
// at any time. Same for shared mutable references. If LLVM had a
3259+
// way to say "dereferenceable on entry" we could use it here.
32593260
attrs.pointee_size = match kind {
3260-
PointerKind::UniqueOwned => Size::ZERO,
3261-
_ => pointee.size,
3261+
PointerKind::UniqueBorrowed
3262+
| PointerKind::UniqueBorrowedPinned
3263+
| PointerKind::Frozen => pointee.size,
3264+
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
32623265
};
32633266

32643267
// `Box`, `&T`, and `&mut T` cannot be undef.
@@ -3285,7 +3288,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32853288
// or not to actually emit the attribute. It can also be controlled with the
32863289
// `-Zmutable-noalias` debugging option.
32873290
let no_alias = match kind {
3288-
PointerKind::SharedMutable | PointerKind::UniqueBorrowed => false,
3291+
PointerKind::SharedMutable
3292+
| PointerKind::UniqueBorrowed
3293+
| PointerKind::UniqueBorrowedPinned => false,
32893294
PointerKind::UniqueOwned => noalias_for_box,
32903295
PointerKind::Frozen => !is_return,
32913296
};

compiler/rustc_target/src/abi/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1352,13 +1352,17 @@ pub enum PointerKind {
13521352
/// Most general case, we know no restrictions to tell LLVM.
13531353
SharedMutable,
13541354

1355-
/// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
1355+
/// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
13561356
Frozen,
13571357

1358-
/// `&mut T` which is `noalias` but not `readonly`.
1358+
/// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
13591359
UniqueBorrowed,
13601360

1361-
/// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
1361+
/// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
1362+
UniqueBorrowedPinned,
1363+
1364+
/// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
1365+
/// nor `dereferenceable`.
13621366
UniqueOwned,
13631367
}
13641368

src/test/codegen/function-arguments.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use std::mem::MaybeUninit;
77
use std::num::NonZeroU64;
8+
use std::marker::PhantomPinned;
89

910
pub struct S {
1011
_field: [i32; 8],
@@ -14,6 +15,11 @@ pub struct UnsafeInner {
1415
_field: std::cell::UnsafeCell<i16>,
1516
}
1617

18+
pub struct NotUnpin {
19+
_field: i32,
20+
_marker: PhantomPinned,
21+
}
22+
1723
pub enum MyBool {
1824
True,
1925
False,
@@ -91,7 +97,7 @@ pub fn static_borrow(_: &'static i32) {
9197
pub fn named_borrow<'r>(_: &'r i32) {
9298
}
9399

94-
// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef align 2 dereferenceable(2) %_1)
100+
// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef nonnull align 2 %_1)
95101
// unsafe interior means this isn't actually readonly and there may be aliases ...
96102
#[no_mangle]
97103
pub fn unsafe_borrow(_: &UnsafeInner) {
@@ -109,6 +115,18 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
109115
pub fn mutable_borrow(_: &mut i32) {
110116
}
111117

118+
#[no_mangle]
119+
// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1)
120+
// This one is *not* `noalias` because it might be self-referential.
121+
pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
122+
}
123+
124+
// CHECK: @notunpin_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
125+
// But `&NotUnpin` behaves perfectly normal.
126+
#[no_mangle]
127+
pub fn notunpin_borrow(_: &NotUnpin) {
128+
}
129+
112130
// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef dereferenceable(32) %_1)
113131
#[no_mangle]
114132
pub fn indirect_struct(_: S) {

0 commit comments

Comments
 (0)