-
Notifications
You must be signed in to change notification settings - Fork 4
[WIP] Experiment with a safe adoption API #47
base: trunk
Are you sure you want to change the base?
Conversation
src/adopt.rs
Outdated
| /// | ||
| /// [`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
Etype inResultshould implementError, otherwise it won't compose well with existing error-handling mechanisms, such as the?sugar. try_adoptthat returns aResultandadoptthat 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
otherin 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::adoptAPI.The API requires that the inner
Tof andRc<T>implement a new trait,Trace.Tracehas a single required method:Trace::mark.Rc::<T>::adoptis only available whenTimplsTrace.Trace::markallows aTto use internal iteration to mark all of theRc<T>s that are immediately reachable.Rc::<T>::adoptdetermines whether an adoption ofotheris safe based on whetherTyields a&mut Rc<T>that points to the same allocation as the given otherRcto adopt.By yielding a
&mut Rc<T>,Tproves that it owns anRc<T>that points to the same allocation asother, which satisfies the safety invariants ofAdopt::adopt_unchecked.Practically,
Ts that implementTracemust use some sort of interior mutability, sinceTrace::marktakes&self.The doubly linked list integration test is updated to use this new safe
adoptAPI and implsTrace. The orphan rule for trait impls complicates implementingTraceforRc<RefCell<T>>and requires the introduction of a wrapper type. The doubly linked list test now has#![forbid(unsafe_code)].r? @tummychow