Skip to content

Commit 3c5de9a

Browse files
committed
add known-bug test for unsound issue 85099
1 parent be68c69 commit 3c5de9a

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// check-pass
2+
// known-bug: #85099
3+
4+
// Should fail. Can coerce `Pin<T>` into `Pin<U>` where
5+
// `T: Deref<Target: Unpin>` and `U: Deref<Target: !Unpin>`, using the
6+
// `CoerceUnsized` impl on `Pin` and an unorthodox `DerefMut` impl for
7+
// `Pin<&_>`.
8+
9+
// This should not be allowed, since one can unpin `T::Target` (since it is
10+
// `Unpin`) to gain unpinned access to the previously pinned `U::Target` (which
11+
// is `!Unpin`) and then move it.
12+
13+
use std::{
14+
cell::{RefCell, RefMut},
15+
future::Future,
16+
ops::DerefMut,
17+
pin::Pin,
18+
};
19+
20+
struct SomeLocalStruct<'a, Fut>(&'a RefCell<Fut>);
21+
22+
trait SomeTrait<'a, Fut> {
23+
#[allow(clippy::mut_from_ref)]
24+
fn deref_helper(&self) -> &mut (dyn SomeTrait<'a, Fut> + 'a) {
25+
unimplemented!()
26+
}
27+
fn downcast(self: Pin<&mut Self>) -> Pin<&mut Fut> {
28+
unimplemented!()
29+
}
30+
}
31+
32+
impl<'a, Fut: Future<Output = ()>> SomeTrait<'a, Fut> for SomeLocalStruct<'a, Fut> {
33+
fn deref_helper(&self) -> &mut (dyn SomeTrait<'a, Fut> + 'a) {
34+
let x = Box::new(self.0.borrow_mut());
35+
let x: &'a mut RefMut<'a, Fut> = Box::leak(x);
36+
&mut **x
37+
}
38+
}
39+
impl<'a, Fut: Future<Output = ()>> SomeTrait<'a, Fut> for Fut {
40+
fn downcast(self: Pin<&mut Self>) -> Pin<&mut Fut> {
41+
self
42+
}
43+
}
44+
45+
impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> {
46+
fn deref_mut<'c>(
47+
self: &'c mut Pin<&'b dyn SomeTrait<'a, Fut>>,
48+
) -> &'c mut (dyn SomeTrait<'a, Fut> + 'b) {
49+
self.deref_helper()
50+
}
51+
}
52+
53+
// obviously a "working" function with this signature is problematic
54+
pub fn unsound_pin<Fut: Future<Output = ()>>(
55+
fut: Fut,
56+
callback: impl FnOnce(Pin<&mut Fut>),
57+
) -> Fut {
58+
let cell = RefCell::new(fut);
59+
let s: &SomeLocalStruct<'_, Fut> = &SomeLocalStruct(&cell);
60+
let p: Pin<Pin<&SomeLocalStruct<'_, Fut>>> = Pin::new(Pin::new(s));
61+
let mut p: Pin<Pin<&dyn SomeTrait<'_, Fut>>> = p;
62+
let r: Pin<&mut dyn SomeTrait<'_, Fut>> = p.as_mut();
63+
let f: Pin<&mut Fut> = r.downcast();
64+
callback(f);
65+
cell.into_inner()
66+
}
67+
68+
fn main() {}

0 commit comments

Comments
 (0)