Skip to content

Commit 04a5e18

Browse files
committed
Auto merge of #2780 - RalfJung:rustup, r=RalfJung
Rustup
2 parents 1bc3e00 + 8c0027d commit 04a5e18

File tree

6 files changed

+95
-77
lines changed

6 files changed

+95
-77
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f3126500f25114ba4e0ac3e76694dd45a22de56d
1+
dffea43fc1102bdfe16d88ed412c23d4f0f08d9d

src/borrow_tracker/stacked_borrows/mod.rs

+30-12
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),
@@ -137,6 +135,31 @@ impl NewPermission {
137135
}
138136
}
139137

138+
fn from_box_ty<'tcx>(
139+
ty: Ty<'tcx>,
140+
kind: RetagKind,
141+
cx: &crate::MiriInterpCx<'_, 'tcx>,
142+
) -> Self {
143+
// `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
144+
let pointee = ty.builtin_deref(true).unwrap().ty;
145+
if pointee.is_unpin(*cx.tcx, cx.param_env()) {
146+
// A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
147+
// a weak protector).
148+
NewPermission::Uniform {
149+
perm: Permission::Unique,
150+
access: Some(AccessKind::Write),
151+
protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
152+
}
153+
} else {
154+
// `!Unpin` boxes do not get `noalias` nor `dereferenceable`.
155+
NewPermission::Uniform {
156+
perm: Permission::SharedReadWrite,
157+
access: None,
158+
protector: None,
159+
}
160+
}
161+
}
162+
140163
fn protector(&self) -> Option<ProtectorKind> {
141164
match self {
142165
NewPermission::Uniform { protector, .. } => *protector,
@@ -916,12 +939,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
916939

917940
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
918941
// Boxes get a weak protectors, since they may be deallocated.
919-
let new_perm = NewPermission::Uniform {
920-
perm: Permission::Unique,
921-
access: Some(AccessKind::Write),
922-
protector: (self.kind == RetagKind::FnEntry)
923-
.then_some(ProtectorKind::WeakProtector),
924-
};
942+
let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx);
925943
self.retag_ptr_inplace(place, new_perm, self.retag_cause)
926944
}
927945

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/future-self-referential.rs

+44-10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ impl Future for Delay {
2626
}
2727
}
2828

29+
fn mk_waker() -> Waker {
30+
use std::sync::Arc;
31+
32+
struct MyWaker;
33+
impl Wake for MyWaker {
34+
fn wake(self: Arc<Self>) {
35+
unimplemented!()
36+
}
37+
}
38+
39+
Waker::from(Arc::new(MyWaker))
40+
}
41+
2942
async fn do_stuff() {
3043
(&mut Delay::new(1)).await;
3144
}
@@ -73,16 +86,7 @@ impl Future for DoStuff {
7386
}
7487

7588
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
76-
use std::sync::Arc;
77-
78-
struct MyWaker;
79-
impl Wake for MyWaker {
80-
fn wake(self: Arc<Self>) {
81-
unimplemented!()
82-
}
83-
}
84-
85-
let waker = Waker::from(Arc::new(MyWaker));
89+
let waker = mk_waker();
8690
let mut context = Context::from_waker(&waker);
8791

8892
let mut pinned = pin!(fut);
@@ -94,7 +98,37 @@ fn run_fut<T>(fut: impl Future<Output = T>) -> T {
9498
}
9599
}
96100

101+
fn self_referential_box() {
102+
let waker = mk_waker();
103+
let cx = &mut Context::from_waker(&waker);
104+
105+
async fn my_fut() -> i32 {
106+
let val = 10;
107+
let val_ref = &val;
108+
109+
let _ = Delay::new(1).await;
110+
111+
*val_ref
112+
}
113+
114+
fn box_poll<F: Future>(
115+
mut f: Pin<Box<F>>,
116+
cx: &mut Context<'_>,
117+
) -> (Pin<Box<F>>, Poll<F::Output>) {
118+
let p = f.as_mut().poll(cx);
119+
(f, p)
120+
}
121+
122+
let my_fut = Box::pin(my_fut());
123+
let (my_fut, p1) = box_poll(my_fut, cx);
124+
assert!(p1.is_pending());
125+
let (my_fut, p2) = box_poll(my_fut, cx);
126+
assert!(p2.is_ready());
127+
drop(my_fut);
128+
}
129+
97130
fn main() {
98131
run_fut(do_stuff());
99132
run_fut(DoStuff::new());
133+
self_referential_box();
100134
}

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)