also do not add noalias on not-Unpin Box
This commit is contained in:
parent
ea541bc2ee
commit
1ef16874b5
6 changed files with 183 additions and 119 deletions
|
|
@ -135,6 +135,32 @@ impl NewPermission {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_box_ty<'tcx>(
|
||||
ty: Ty<'tcx>,
|
||||
kind: RetagKind,
|
||||
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
) -> Self {
|
||||
// `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
|
||||
let pointee = ty.builtin_deref(true).unwrap().ty;
|
||||
if pointee.is_unpin(*cx.tcx, cx.param_env()) {
|
||||
// A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
|
||||
// a weak protector).
|
||||
NewPermission::Uniform {
|
||||
perm: Permission::Unique,
|
||||
access: Some(AccessKind::Write),
|
||||
protector: (kind == RetagKind::FnEntry)
|
||||
.then_some(ProtectorKind::WeakProtector),
|
||||
}
|
||||
} else {
|
||||
// `!Unpin` boxes do not get `noalias` nor `dereferenceable`.
|
||||
NewPermission::Uniform {
|
||||
perm: Permission::SharedReadWrite,
|
||||
access: None,
|
||||
protector: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn protector(&self) -> Option<ProtectorKind> {
|
||||
match self {
|
||||
NewPermission::Uniform { protector, .. } => *protector,
|
||||
|
|
@ -914,12 +940,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
// Boxes get a weak protectors, since they may be deallocated.
|
||||
let new_perm = NewPermission::Uniform {
|
||||
perm: Permission::Unique,
|
||||
access: Some(AccessKind::Write),
|
||||
protector: (self.kind == RetagKind::FnEntry)
|
||||
.then_some(ProtectorKind::WeakProtector),
|
||||
};
|
||||
let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx);
|
||||
self.retag_ptr_inplace(place, new_perm, self.retag_cause)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ impl Future for Delay {
|
|||
}
|
||||
}
|
||||
|
||||
fn mk_waker() -> Waker {
|
||||
use std::sync::Arc;
|
||||
|
||||
struct MyWaker;
|
||||
impl Wake for MyWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
Waker::from(Arc::new(MyWaker))
|
||||
}
|
||||
|
||||
async fn do_stuff() {
|
||||
(&mut Delay::new(1)).await;
|
||||
}
|
||||
|
|
@ -73,16 +86,7 @@ impl Future for DoStuff {
|
|||
}
|
||||
|
||||
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
||||
use std::sync::Arc;
|
||||
|
||||
struct MyWaker;
|
||||
impl Wake for MyWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
let waker = Waker::from(Arc::new(MyWaker));
|
||||
let waker = mk_waker();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
|
||||
let mut pinned = pin!(fut);
|
||||
|
|
@ -94,7 +98,37 @@ fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
|||
}
|
||||
}
|
||||
|
||||
fn self_referential_box() {
|
||||
let waker = mk_waker();
|
||||
let cx = &mut Context::from_waker(&waker);
|
||||
|
||||
async fn my_fut() -> i32 {
|
||||
let val = 10;
|
||||
let val_ref = &val;
|
||||
|
||||
let _ = Delay::new(1).await;
|
||||
|
||||
*val_ref
|
||||
}
|
||||
|
||||
fn box_poll<F: Future>(
|
||||
mut f: Pin<Box<F>>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> (Pin<Box<F>>, Poll<F::Output>) {
|
||||
let p = f.as_mut().poll(cx);
|
||||
(f, p)
|
||||
}
|
||||
|
||||
let my_fut = Box::pin(my_fut());
|
||||
let (my_fut, p1) = box_poll(my_fut, cx);
|
||||
assert!(p1.is_pending());
|
||||
let (my_fut, p2) = box_poll(my_fut, cx);
|
||||
assert!(p2.is_ready());
|
||||
drop(my_fut);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
run_fut(do_stuff());
|
||||
run_fut(DoStuff::new());
|
||||
self_referential_box();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue