-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Description
Consider the following specific use case explaining a more general
issue: We have a struct, RefStrings, that keeps a RefCell containing
some form of collection, Vec<String>. Part of RefStrings's API
surface is a function that aims to expose an iterator over the
underlying collection. The only possibility I see for exposing the
iterator (conceptually) is via a Ref and using RefCell's map
function:
struct RefStrings(RefCell<Vec<String>>);
impl RefStrings {
fn iter<'t, 's: 't>(&'s self) -> Ref<'t, Iter<String>> {
Ref::map(self.0.borrow(), |x| x.iter())
}
}Unfortunately, that does not work. The reason being that Ref is
defined to hold a reference to a member of the borrowed object, but an
iterator is effectively an actual object in itself that just happens to
have such a reference.
I have not found a way to get this working using the existing
functionality. Am I just missing something?
A possible solution that I worked with now is the introduction of a new
associated function Ref::map_val that returns an object that
effectively contains another object (i.e., something that is Sized)
that may hold a reference to the borrowed data (e.g., a concrete
iterator type). That solves the problem reasonably nicely, in my
opinion.
struct RefStrings(RefCell<Vec<String>>);
impl RefStrings {
fn iter<'t, 's: 't>(&'s self) -> RefVal<'t, Iter<String>> {
Ref::map_val(self.0.borrow(), |x| x.iter())
}
}
// ...
// RefVal is defined as:
pub struct RefVal<'b, T> {
value: T,
borrow: BorrowRef<'b>,
}(see the cell crate for the full functionality; note that the API provided is still limited, i.e., I mostly implemented what I needed right away)
Unfortunately I have not found a way to provide said functionality as
anything else than a replacement of RefCell itself, with all the code
duplication that accompanies.
So, I am filing this issue to discuss
- whether I am just missing something and there is a trivial way to
accomplish what I hopefully explained well enough if that is not the case, whether this functionality is desired to be
included in the Rust standard library (I believe this is a general
problem with a general solution; despite probably not being a very
common one)if such a desire exists, the steps to be taken to include this
functionality (RFC process?)
EDIT: Proposed solution turned out to be unsafe with no known workaround. So really this issue is only to discuss other solutions.