@@ 1,15 @@
+use std::marker::PhantomData;
+
+use stable_deref_trait::StableDeref;
+
+pub trait GetHandle {
+ type Handle<'a>;
+}
+
+pub struct GetDeref<T: StableDeref> {
+ _phantom: PhantomData<T>,
+}
+
+impl<T: StableDeref + 'static> GetHandle for GetDeref<T> {
+ type Handle<'a> = &'a T::Target;
+}
@@ 1,54 @@
+#![feature(generic_associated_types)]
+
+use stable_deref_trait::StableDeref;
+
+mod handle;
+
+use handle::{GetDeref, GetHandle};
+
+pub struct ORef<T, H>
+where
+ T: StableDeref,
+ H: GetHandle,
+{
+ owner: T,
+ // really 'unsafe
+ handle: H::Handle<'static>,
+}
+
+impl<T> ORef<T, GetDeref<T>>
+where
+ T: StableDeref + 'static,
+{
+ pub fn new(owner: T) -> Self {
+ // Safety: We are extenting a reference to parts of owner to static lifetime. This is only
+ // safe because
+ //
+ // * we ensure through StableDeref that what is borrowed lives for as long as owner lives
+ // * we never actually give out self.handle, only a copy of it with a shorter lifetime
+ let handle: &'static T::Target = unsafe { &*(owner.deref() as *const T::Target) };
+
+ Self { owner, handle }
+ }
+}
+
+impl<T, H> ORef<T, H>
+where
+ T: StableDeref,
+ H: GetHandle,
+{
+ pub fn map<I, F>(self, f: F) -> ORef<T, I>
+ where
+ I: GetHandle,
+ F: FnOnce(H::Handle<'static>) -> I::Handle<'static>,
+ // ^ This is unsound, as the 'static handle or something it deref's to can be "stolen" by
+ // the map function. However, the correct variant of this code (see below) currently
+ // doesn't compile due to https://github.com/rust-lang/rust/issues/49601
+ // F: for<'a> FnOnce(H::Handle<'a>) -> I::Handle<'a>,
+ {
+ ORef {
+ owner: self.owner,
+ handle: f(self.handle),
+ }
+ }
+}