Storing reference to an element in Vec<Box<_>> [duplicate] - rust

This question already has answers here:
How can I model a bidirectional map without annoying the borrow checker?
(1 answer)
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 5 years ago.
I have a struct Oid, which owns a vector of distinct objects. It also has a reverse map which maps an object to its index in the vector. Objects are never deleted from the struct. However, new objects can be added. The use case is simple: I need fast retrieval of an object by its index and of the index of a given object. Here's my attempt so far:
struct Oid<'a, T>
where
T: Eq + Hash,
{
objects: Vec<Box<T>>,
rev_map: HashMap<&'a T, usize>,
}
impl<'a, T> Oid<'a, T>
where
T: Eq + Hash,
{
pub fn insert(&mut self, t: T) -> usize {
match self.objects.get(&t) {
Some(&i) => i,
_ => {
let i = self.objects.size();
self.objects.push(Box::new(t));
self.rev_map
.insert(unsafe { &*(&*self.objects[i] as *const T) }, i);
i
}
}
}
}
As the memory locations of objects can change as the vector grows, I put each object in a Box, which ensures address stability. The problem is in rev_map, I can't figure out how to tell Rust that the object reference will never outlive the struct. Is there a way to do this in idiomatic Rust?

Related

How do I convert an iterator to an iterator of references in Rust? [duplicate]

This question already has answers here:
How to convert an Iterator on a tuple of (String, String) to an Iterator of (&str, &str)?
(2 answers)
Closed 2 months ago.
As the title says, how would one go about converting an Iterator<Item = T> to Iterator<Item = &'a T> (which is to be passed to a function) without collecting the contents of the iterator?
Basically, I want to accomplish the following:
fn foo<'a, T>(data: impl Iterator<Item = &'a T>){
// ..
}
let data: Vec<T> = ...;
let iter = data.iter().map(|t| {
let mut nt = t.clone();
// mutate nt...
return nt;
});
foo(iter); // Error: expected &T, iter returns T
The only way I can think of to get references to items without an owner is to leak them. It's most likely not what you want but here it is anyways:
fn leak_it<T>(i: impl Iterator<Item = T>) -> impl Iterator<Item = &'static T> {
i.map(|x| &*Box::leak(Box::new(x)))
}
To avoid leaking the memory for good either you have to store the references (in which case you should just collect the items in the first place) or the function you're calling has to return them so you can turn them back into a box with Box::from_raw and properly free the memory.

How do I transform a &Vec<Box<dyn Child>> into a &Vec<Box<dyn Base>> where trait Child : Base {}? [duplicate]

This question already has answers here:
Why doesn't Rust support trait object upcasting?
(5 answers)
Can I cast between two traits?
(5 answers)
How do I convert a Vec<T> to a Vec<U> without copying the vector?
(2 answers)
Closed 2 years ago.
I've tried this post using the AsBase trait but couldn't quite get to a minimal example. And since that post is a bit old, the lack of dyn sometimes gets a bit confusing.
This is what I thought I could do:
trait Entity {}
trait Part: Entity {}
trait System {
fn parts(&self) -> &Vec<Box<dyn Entity>>; // This is the specification
}
struct System32 {
parts: Vec<Box<dyn Part>>, // But this is what I have
}
impl System for System32 {
fn parts(&self) -> &Vec<Box<dyn Entity>> {
&self.parts // error: expected trait Entity, found trait Part
// I've also tried:
// &self.parts as &Vec<Box<dyn Entity>>
// error: an `as` expression can only be used to convert between
// primitive types or to coerce to a specific trait object
}
}
Is this even possible? If yes, then how can I do the type conversion?
Is this even possible?
No.
There are two issues with it: first, Rust is not an inheritance-based language, trait B: A means "B requires A" more than "B extends A".
Now although this is probably not how Rust's trait should be thought of, there are ways to perform this "upcasting" regardless, and the language may eventually include this feature (in part for multi-trait objects).
However there is a bigger issue here: you're returning an &Vec.
This means that vector has to be owned by something as you're only returning a reference to it. But a Box<dyn Entity> and a Box<dyn Part> are completely different values.
Going back to Rust not being inheritance-based, the vtable for B does not embed the vtable for A, you can't just say "this is now a pointer to an A" because it absolutely is not[0].
This means going from Box<dyn Part> to Box<dyn Entity> is a full value conversion, not an in-place reinterpretation of the value as a different type.
Which means a new Box, and a new Vec, which means you can't just return a reference to an existing Vec claiming it's the type you want, the contents of the Vec itself need to change.
[0] unlike C++ I believe, at least for SI cases, with MI you'd have one of the parents be a simple reinterpretation but the others would have to offset the child pointer to get the correct vtable even if they're embedded, so I think you'd have the same issue
Masklinn above explained why you cannot do what you wanted to do.
I'm going here to try to provide an approach that would work for solving your problem using an approach similar to yours. Maybe there are better approaches though, could we see the bigger picture.
One way to achieve your pattern would be to have the type of entity your system manages be an associated type of your System trait. This enables you to write the following:
trait Entity {
fn do_something(&self) {}
}
trait Part: Entity {}
trait System {
type Entity: Entity + ?Sized;
// I renamed this function from "parts" to "entities" because it seems that's what you want it to return
fn entities(&self) -> &Vec<Box<Self::Entity>>; // This is the specification
fn do_something_with_entities(&self) {
for entity in self.entities() {
entity.do_something();
}
}
}
struct System32 {
parts: Vec<Box<dyn Part>>, // But this is what I have
}
impl System for System32 {
type Entity = dyn Part;
fn entities(&self) -> &Vec<Box<Self::Entity>> {
&self.parts
}
}
Now if you reaally need to be able to return some form of collection that outputs only actual dyn Entity because e.g. your system manages different types of what would be InnerEntity... well given the amount of dirty tricks I had to use I strongly beleive that is not idiomatic Rust, and you should probably express the whole problem so people can suggest more idiomatic solutions than trying to do inheritance in Rust, but in any case, this compilation of dirty stuff that eventually provides a reasonable interface with zero allocations was pretty fun to write.
// ------ TRAIT SYSTEM
// From https://users.rust-lang.org/t/casting-traitobject-to-super-trait/33524/16
// This intermediate trait allows to work around Sized/?Sized requirements
pub trait IntoSuper<Super: ?Sized> {
fn as_super(&self) -> &Super;
fn as_super_mut(&mut self) -> &mut Super;
fn into_super(self: Box<Self>) -> Box<Super>;
}
trait Entity {}
impl<'a, T: 'a + Entity> IntoSuper<dyn Entity + 'a> for T {
fn as_super(&self) -> &(dyn Entity + 'a) {
self
}
fn as_super_mut(&mut self) -> &mut (dyn Entity + 'a) {
self
}
fn into_super(self: Box<Self>) -> Box<dyn Entity + 'a> {
self
}
}
trait Part: Entity + IntoSuper<dyn Entity> {}
// The 'r lifetime needs to be at the trait level because GATs are not stable yet
// https://github.com/rust-lang/rust/issues/44265
// This workaround somewhat simulates GATs
trait System: for<'r> SystemInner<'r> {}
impl<T: for<'r> SystemInner<'r>> System for T {}
trait SystemInner<'r> {
/// Clone should be inexpensive
type EntitiesIter: Iterator<Item = &'r dyn Entity> + ExactSizeIterator + Clone + 'r;
fn entities(&'r self) -> Self::EntitiesIter; // This is the specification
}
type EntitiesIter<'r, Source> =
std::iter::Map<std::slice::Iter<'r, Box<Source>>, fn(&'r Box<Source>) -> &'r dyn Entity>;
// ------ END OF TRAIT SYSTEM
struct System32 {
parts: Vec<Box<dyn Part>>, // And this is what you have stored
}
impl<'r> SystemInner<'r> for System32 {
type EntitiesIter = EntitiesIter<'r, dyn Part>;
fn entities(&'r self) -> Self::EntitiesIter {
self.parts.iter().map(|p| p.as_super())
}
}
// System32 implements System because it implements SystemInner<'r> for every 'r
struct SomePart;
impl Entity for SomePart {}
impl Part for SomePart {}
fn main() {
let system = System32 {
parts: vec![Box::new(SomePart), Box::new(SomePart)],
};
let second_part: &dyn Entity = system.entities().nth(1).expect("We put two parts in our vec");
for part_as_dyn_entity in system.entities() {
// do stuff
}
}

Multiply all elements in a generic vector? [duplicate]

This question already has answers here:
How to write a trait bound for adding two references of a generic type?
(1 answer)
How does "for<>" syntax differ from a regular lifetime bound?
(1 answer)
Closed 2 years ago.
I'm trying to multiply all elements in a vector but I can't figure out how to do this with a reference. Here is an example:
struct S<T> {
elements: Vec<T>,
}
impl<T> std::ops::MulAssign<T> for S<T>
where
T: std::ops::MulAssign,
{
fn mul_assign(&mut self, val: T) {
for i in 0..self.elements.len() {
self.elements[i] *= val;
}
}
}
This doesn't compile:
error[E0382]: use of moved value: `val`
--> src/lib.rs:11:33
|
9 | fn mul_assign(&mut self, val: T) {
| --- move occurs because `val` has type `T`, which does not implement the `Copy` trait
10 | for i in 0..self.elements.len() {
11 | self.elements[i] *= val;
| ^^^ value moved here, in previous iteration of loop
I've tried this with references in different ways, but I didn't succeed. How do you do this? I would prefer to implement this without the Copy trait.
Maybe like this?
struct S<T> {
elements: Vec<T>,
}
impl<T> std::ops::MulAssign<&T> for S<T>
where
for<'a> T: std::ops::MulAssign<&'a T>,
{
fn mul_assign(&mut self, val: &T) {
for i in self.elements.iter_mut() {
*i *= val;
}
}
}
Uses iter_mut to iterate over vector
Requires that your elements support multiplication by borrowed T (which seems to be the case for isize and others
Extra notes:
I wouldn't recommend direct index assignment such as elements[i]. You can achieve the same with a for element in self.elements. Rust iterators will directly understand you want to iterate over the whole vec, so you can apply the processing on the element object.
A direct index access will add bound-checking at runtime, making it a slower solution, instead of safely iterating over the array with the length pre-calculated.
Furthermore, if you want to apply the same processing over the vec, the .map() method can help greatly, taking a closure to defiune the processing you want. Rust offers many such functional higher-order-functions, that are much more concise and efficient.

Can I transfer ownership of local variables and references to them to a returned iterator? [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
How can I store a Chars iterator in the same struct as the String it is iterating on?
(2 answers)
Is there an owned version of String::chars?
(6 answers)
Closed 4 years ago.
I am using a trait with a method that returns an boxed iterator. Since the iterator will use self and the parameters of foo, all are constrained to the same lifetime:
pub trait Foo {
fn foo<'a>(&'a self, txt: &'a str) -> Box<Iterator<Item = String> + 'a>;
}
I would like to build a function around this method:
fn foo_int<'a, F: Foo>(f: &'a F, val: i32) -> impl Iterator<Item = String> + 'a {
let txt = format!("{}", val);
f.foo(&txt)
}
But that does not compile, because:
error[E0515]: cannot return value referencing local variable `txt`
--> src/lib.rs:7:5
|
7 | f.foo(&txt)
| ^^^^^^----^
| | |
| | `txt` is borrowed here
| returns a value referencing data owned by the current function
I understand why this happens, and it makes sense, but it seems to be that there should be a way to get around it. After all, that's what closures (with the move keyword) do: they take ownership of the values they need to "take away with them".
Is there a clever way to rewrite the foo_int function, using a closure or something else?
Actually, while working my minimal example, I came up with an idea that (kind of) solves the problem. It is available in the playground.
The idea is to wrap the parameter of foo and the returned iterator in a dedicated type, which itself implements the Iterator trait by delegating to the inner iterator.
pub struct Bar<'a>(String, Box<Iterator<Item = String> + 'a>);
impl<'a> Bar<'a> {
fn new<F: Foo>(foo: &'a F, txt: String) -> Bar<'a> {
let itr = foo.foo(unsafe { &*(&txt[..] as *const str) });
Bar(txt, itr)
}
}
impl<'a> Iterator for Bar<'a> {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
self.1.next()
}
}
fn foo_int<'a, F: Foo>(f: &'a F, val: i32) -> impl Iterator<Item = String> + 'a {
Bar::new(f, format!("{}", val))
}
I'm not entirely satisfied with that solution, though, because of the following reasons.
It is rather specific to this particular method; for another method with other parameters, I would need a different wrapper type.
It uses unsafe code. I believe this one is ok (because the inner &str of String is stable through move), but it might be harder (if not impossible) to achieve with other types.
It forces me to re-implement Iterator. While this minimal version works, it is suboptimal because the underlying iterator may have optimized implementations of some methods, which I "loose" here by relying on the default implementations. Implementing all methods of Iterator by hand (to pass them through to self.1) is tedious, and brittle (if further versions add new methods, I would have to add them as well).
So any better solution is still welcome...
edit: #Shepmaster's arguments convinced me; this is actually the same old problem of storing a value and a reference to it. So it is unsafe, and my solution is not general, because in general, it may not work :-/

"borrowed value does not live long enough", but why do we need it to live so long? [duplicate]

This question already has answers here:
How do I write the lifetimes for references in a type constraint when one of them is a local reference?
(1 answer)
Borrowed value does not live long enough when iterating over a generic value with a lifetime on the function body
(1 answer)
How does "for<>" syntax differ from a regular lifetime bound?
(1 answer)
Closed 4 years ago.
There are lots of similar questions, but I couldn't find the answer to my exact question.
In my Rust code, I have a generic type and want to implement a method that takes a reference to another instance of the that type, and then another method that consumes its argument but does exactly the same thing as the first one:
#[derive(Debug, PartialEq, Clone)]
pub struct Wrapper<T> {
v: T,
}
impl<T> Wrapper<T> {
pub fn f_ref(&self, _other: &Wrapper<T>) { /* ... */ }
pub fn f_consume(&self, other: Wrapper<T>) {
self.f_ref(&other)
}
}
It compiles just fine.
Now I want to do basically the same, but while implementing a trait. First, the function that takes a reference:
use std::ops::AddAssign;
impl<'a, T> AddAssign<&'a Wrapper<T>> for Wrapper<T> where T: AddAssign<&'a T> {
fn add_assign(&mut self, other: &'a Wrapper<T>) {
self.v += &other.v;
}
}
#[test]
fn test() {
let mut a = Wrapper { v: 1_i32 };
let b = Wrapper { v: 2 };
a += &b;
drop(b);
assert_eq!(a, Wrapper { v: 3 });
}
It works, too.
Now I want to implement AddAssign for Wrapper<T> based on the implementation of AddAssign<&Wrapper<T>> that I already have. I understand that if T has references in it, it will cause trouble, so I make sure it has 'static lifetime. I'm OK with it: in my program, I expect T to be something like an owned matrix of numbers wrapped in some custom struct.
impl<'a, T> AddAssign for Wrapper<T> where T: 'static + AddAssign<&'a T>, Wrapper<T>: 'static {
fn add_assign(&mut self, other: Wrapper<T>) {
*self += &other;
}
}
And it fails. The compiler says that other must stay valid after we used a reference to it to in a += expression. But when we used such a reference in the test() function above and dropped b there (which played the role of other here) and used the result later, the compiler agreed it's OK. Why?
I suspect that I need to specify some additional trait bounds for T or Wrapper<T> but don't understand what these bound should be.
Code in playground.

Resources