-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Experiment with a safe adoption API #47
base: trunk
Are you sure you want to change the base?
Conversation
src/adopt.rs
Outdated
@@ -34,6 +35,14 @@ mod sealed { | |||
/// [`adopt_unchecked`]: Adopt::adopt_unchecked | |||
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html | |||
pub unsafe trait Adopt: sealed::Sealed { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adopt's trait-level documentation will need to be significantly reworked.
src/trace.rs
Outdated
/// TODO: document me! | ||
fn yield_owned_rcs<F>(&self, mark: F) | ||
where | ||
F: for<'a> FnMut(&'a mut Rc<Self>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if the higher ranked lifetime bound is correct here. Do we want to enforce that the lifetime of the yielded &mut Rc<T>
is the same as &self
? Removing the for<'a>
would disallow non-static T
that have &mut Rc<T>
fields which would be a good thing.
src/adopt.rs
Outdated
type Inner = T; | ||
|
||
/// TODO: document me! | ||
fn adopt(this: &mut Self, other: &Self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe adopt should return Result<(), &Self>
where the error variant contains other
if the adoption failed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe there is try_adopt
and adopt
which unwraps try_adopt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The
E
type inResult
should implementError
, otherwise it won't compose well with existing error-handling mechanisms, such as the?
sugar. try_adopt
that returns aResult
andadopt
that unwraps the former is indeed a good, ergonomic API. The standard library does that a lot too, I think.- Why would you want to return
other
in case of a failure, if it's a reference and the callee already has it anyway?
…_rcs This ensures that yielded Rcs have the same lifetime as self, which is what we want to assert that self owns the Rc.
This PR experiments with a safe
Adopt::adopt
API.The API requires that the inner
T
of andRc<T>
implement a new trait,Trace
.Trace
has a single required method:Trace::mark
.Rc::<T>::adopt
is only available whenT
implsTrace
.Trace::mark
allows aT
to use internal iteration to mark all of theRc<T>
s that are immediately reachable.Rc::<T>::adopt
determines whether an adoption ofother
is safe based on whetherT
yields a&mut Rc<T>
that points to the same allocation as the given otherRc
to adopt.By yielding a
&mut Rc<T>
,T
proves that it owns anRc<T>
that points to the same allocation asother
, which satisfies the safety invariants ofAdopt::adopt_unchecked
.Practically,
T
s that implementTrace
must use some sort of interior mutability, sinceTrace::mark
takes&self
.The doubly linked list integration test is updated to use this new safe
adopt
API and implsTrace
. The orphan rule for trait impls complicates implementingTrace
forRc<RefCell<T>>
and requires the introduction of a wrapper type. The doubly linked list test now has#![forbid(unsafe_code)]
.r? @tummychow