-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Mapping Ref
to a value containing a reference
#54776
Comments
I am also very bothered by the awkwardness of dealing with With your solution, however, I found that I can invalidate the iterator: use cell::*;
use std::slice::Iter;
struct MyRef(RefCell<Vec<usize>>);
impl MyRef {
fn iter<'t, 's: 't>(&'s self) -> RefVal<'t, Iter<usize>> {
Ref::map_val(self.0.borrow(), |x| x.iter())
}
}
fn main() {
let v = MyRef(RefCell::new(vec![1,2,3,4,5]));
println!("capacity before: {:?}", v.0.borrow().capacity());
let it = v.iter().clone();
v.0.borrow_mut().push(0);
println!("capacity after: {:?}", v.0.borrow().capacity());
for &a in it {
print!("{} ", a);
}
} This will compile and run. If the capacity before and after don't match, it means the vector has been reallocated and the output will read something other than "1 2 3 4 5 ". But just seeing that I can push to the original |
Yeah, that looks like an instance of a known problem to me. It has been discussed in quite some length on Github and the Rust user forum, but I am not sure of a good solution. |
Ah thank you. I agree that it looks like the same problem. |
Just to get everybody on the same page: the proposed solution is unsafe in a very subtle way, so I am no longer suggesting to upstream it. I am keeping this issue open to discuss alternative solutions as the motivating problem seems to be something that others have stumbled over as well. |
When it comes to alternative solutions, as I understand it, the use-case is that "I have a struct which uses a The main motivating example for me was a One solution proposed on the internals thread was to have a struct similar to your current For a For iterators, we could imagine a type We could imagine similar types I believe it would be safe to construct an I believe it would be possible to implement both |
Some research has uncovered the mature owning_ref crate, which has already solved my own use-case. It provides an There's a pull request which would add a restricted cc @Kimundi |
Probably worth mentioning that it's not entirely clear whether crates like owning_ref are sound: rust-lang/unsafe-code-guidelines#194 |
Consider the following specific use case explaining a more general
issue: We have a struct,
RefStrings
, that keeps aRefCell
containingsome form of collection,
Vec<String>
. Part ofRefStrings
's APIsurface 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 usingRefCell
'smap
function:
(playground)
Unfortunately, that does not work. The reason being that
Ref
isdefined 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 thateffectively 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.
(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 codeduplication that accompanies.
So, I am filing this issue to discuss
accomplish what I hopefully explained well enough
if that is not the case, whether this functionality is desired to beincluded in the Rust standard library (I believe this is a generalproblem with a general solution; despite probably not being a verycommon one)if such a desire exists, the steps to be taken to include thisfunctionality (RFC process?)EDIT: Proposed solution turned out to be unsafe with no known workaround. So really this issue is only to discuss other solutions.
The text was updated successfully, but these errors were encountered: