Skip to content

Commit 8e1bc87

Browse files
committed
make &mut !Unpin not dereferenceable
See rust-lang/unsafe-code-guidelines#381 for discussion.
1 parent 313a19e commit 8e1bc87

File tree

4 files changed

+24
-60
lines changed

4 files changed

+24
-60
lines changed

src/borrow_tracker/stacked_borrows/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,18 @@ impl NewPermission {
8181
protector: None,
8282
}
8383
} else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
84-
// A regular full mutable reference.
84+
// A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`.
8585
NewPermission::Uniform {
8686
perm: Permission::Unique,
8787
access: Some(AccessKind::Write),
8888
protector,
8989
}
9090
} else {
91+
// `!Unpin` dereferences do not get `noalias` nor `dereferenceable`.
9192
NewPermission::Uniform {
9293
perm: Permission::SharedReadWrite,
93-
// FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
94-
// should do fake accesses here. But then we run into
95-
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
96-
// we don't do that.
9794
access: None,
98-
protector,
95+
protector: None,
9996
}
10097
}
10198
}
@@ -109,6 +106,7 @@ impl NewPermission {
109106
}
110107
}
111108
ty::Ref(_, _pointee, Mutability::Not) => {
109+
// Shared references. If frozen, these get `noalias` and `dereferenceable`; otherwise neither.
112110
NewPermission::FreezeSensitive {
113111
freeze_perm: Permission::SharedReadOnly,
114112
freeze_access: Some(AccessKind::Read),

tests/fail/stacked_borrows/deallocate_against_protector2.rs

-16
This file was deleted.

tests/fail/stacked_borrows/deallocate_against_protector2.stderr

-38
This file was deleted.

tests/pass/stacked-borrows/stacked-borrows.rs

+20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ fn main() {
1919
array_casts();
2020
mut_below_shr();
2121
wide_raw_ptr_in_tuple();
22+
not_unpin_not_protected();
2223
}
2324

2425
// Make sure that reading from an `&mut` does, like reborrowing to `&`,
@@ -219,3 +220,22 @@ fn wide_raw_ptr_in_tuple() {
219220
// Make sure the fn ptr part of the vtable is still fine.
220221
r.type_id();
221222
}
223+
224+
fn not_unpin_not_protected() {
225+
// `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also
226+
// don't add protectors. (We could, but until we have a better idea for where we want to go with
227+
// the self-referntial-generator situation, it does not seem worth the potential trouble.)
228+
use std::marker::PhantomPinned;
229+
230+
pub struct NotUnpin(i32, PhantomPinned);
231+
232+
fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) {
233+
// `f` may mutate, but it may not deallocate!
234+
f(x)
235+
}
236+
237+
inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
238+
let raw = x as *mut _;
239+
drop(unsafe { Box::from_raw(raw) });
240+
});
241+
}

0 commit comments

Comments
 (0)