Skip to content

Commit

Permalink
make &mut !Unpin not dereferenceable
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Feb 6, 2023
1 parent 201ae73 commit ea541bc
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 67 deletions.
15 changes: 9 additions & 6 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,16 @@ fn adjust_for_rust_scalar<'tcx>(

// `Box` are not necessarily dereferenceable for the entire duration of the function as
// they can be deallocated at any time. Same for non-frozen shared references (see
// <https://github.com/rust-lang/rust/pull/98017>). If LLVM had a way to say
// "dereferenceable on entry" we could use it here.
// <https://github.com/rust-lang/rust/pull/98017>), and for mutable references to
// potentially self-referential types (see
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>). If LLVM had a way
// to say "dereferenceable on entry" we could use it here.
attrs.pointee_size = match kind {
PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO,
PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => {
pointee.size
}
PointerKind::Box
| PointerKind::SharedRef { frozen: false }
| PointerKind::MutableRef { unpin: false } => Size::ZERO,
PointerKind::SharedRef { frozen: true }
| PointerKind::MutableRef { unpin: true } => pointee.size,
};

// The aliasing rules for `Box<T>` are still not decided, but currently we emit
Expand Down
10 changes: 4 additions & 6 deletions src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,18 @@ impl NewPermission {
protector: None,
}
} else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
// A regular full mutable reference.
// A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`.
NewPermission::Uniform {
perm: Permission::Unique,
access: Some(AccessKind::Write),
protector,
}
} else {
// `!Unpin` dereferences do not get `noalias` nor `dereferenceable`.
NewPermission::Uniform {
perm: Permission::SharedReadWrite,
// FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
// should do fake accesses here. But then we run into
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
// we don't do that.
access: None,
protector,
protector: None,
}
}
}
Expand All @@ -109,6 +106,7 @@ impl NewPermission {
}
}
ty::Ref(_, _pointee, Mutability::Not) => {
// Shared references. If frozen, these get `noalias` and `dereferenceable`; otherwise neither.
NewPermission::FreezeSensitive {
freeze_perm: Permission::SharedReadOnly,
freeze_access: Some(AccessKind::Read),
Expand Down

This file was deleted.

This file was deleted.

20 changes: 20 additions & 0 deletions src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn main() {
array_casts();
mut_below_shr();
wide_raw_ptr_in_tuple();
not_unpin_not_protected();
}

// Make sure that reading from an `&mut` does, like reborrowing to `&`,
Expand Down Expand Up @@ -219,3 +220,22 @@ fn wide_raw_ptr_in_tuple() {
// Make sure the fn ptr part of the vtable is still fine.
r.type_id();
}

fn not_unpin_not_protected() {
// `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also
// don't add protectors. (We could, but until we have a better idea for where we want to go with
// the self-referntial-generator situation, it does not seem worth the potential trouble.)
use std::marker::PhantomPinned;

pub struct NotUnpin(i32, PhantomPinned);

fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) {
// `f` may mutate, but it may not deallocate!
f(x)
}

inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
let raw = x as *mut _;
drop(unsafe { Box::from_raw(raw) });
});
}
16 changes: 15 additions & 1 deletion tests/codegen/function-arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
pub fn readonly_borrow(_: &i32) {
}

// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret()
#[no_mangle]
pub fn readonly_borrow_ret() -> &'static i32 {
loop {}
}

// CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// static borrow may be captured
#[no_mangle]
Expand Down Expand Up @@ -115,9 +121,17 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
pub fn mutable_borrow(_: &mut i32) {
}

// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret()
#[no_mangle]
pub fn mutable_borrow_ret() -> &'static mut i32 {
loop {}
}

#[no_mangle]
// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1)
// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1)
// This one is *not* `noalias` because it might be self-referential.
// It is also not `dereferenceable` due to
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.
pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
}

Expand Down

0 comments on commit ea541bc

Please sign in to comment.