I am a Rust beginner and I can’t get the following code to compile. What I want is to store several traits in a vector and each of the traits should also have read-only access to a borrowed variable.
I am guessing I have to use „Lifetime bounds“ - like discussed in this thread - because if I comment out lines 60-68, the code compiles fine.
Can somebody please explain how to use „lifetime bounds“ - if this is the way to solve the problem - or is this not the Rust way to solve the problem? If there is a better way to achieve what I’m trying to do I’m glad to change my approach to the problem.
The code which doesn’t compile is here and on rust-playground.
struct PixelImageSimple<'a> {
pixels: &'a Vec<i32>,
width: i32,
height: i32,
}
trait ImageOperation<'a> {
fn execute_op(&self);
}
struct ImageOperationSharpen<'a> {
val: i32,
bitmapdata: &'a PixelImageSimple<'a>
}
impl<'a> ImageOperation<'a> for ImageOperationSharpen<'a> {
fn execute_op(&self) {
println!("ImageOperationSharpen - val = {}, width = {}, height = {}, pixels = {:?}",
&self.val, &self.bitmapdata.width, &self.bitmapdata.height,&self.bitmapdata.pixels);
}
}
struct ImageOperationRotate<'a> {
angle: f64,
bitmapdata: &'a PixelImageSimple<'a>
}
impl<'a> ImageOperation<'a> for ImageOperationRotate<'a> {
fn execute_op(&self) {
println!("ImageOperationRotate - angle = {}, width = {}, height = {}, pixels = {:?}",
&self.angle, &self.bitmapdata.width, &self.bitmapdata.height,&self.bitmapdata.pixels);
}
}
struct Image<'a> {
image_operations: Vec<Box<ImageOperation<'a>>>
}
impl<'a> Image<'a> {
fn new() -> Image<'a> {
Image { image_operations: vec![] }
}
fn add_op(&mut self, image_ops: Box<ImageOperation<'a>>) {
self.image_operations.push(image_ops);
}
}
fn main () {
let bitmapdata = vec![1,2,3];
let bitmap = PixelImageSimple { pixels: &bitmapdata, width: 222, height:334 };
let sharpen = ImageOperationSharpen { val: 34, bitmapdata: &bitmap };
let rotate = ImageOperationRotate { angle: 13.32, bitmapdata: &bitmap };
let box_sharpen = Box::new(sharpen);
let box_rotate = Box::new(rotate);
let mut image = Image::new();
image.add_op(box_sharpen);
image.add_op(box_rotate);
println!("execute_op()");
for imageops in image.image_operations.iter() {
imageops.execute_op();
}
}
I get 3 errors for variable 'bitmapdata' and 'bitmap' twice. As I mentioned above: the code compiles fine without lines 60-68 but results in a compiler error with those lines.
Interesting thing: the compilers hint message note:
reference must be valid for the static lifetime...
So the compiler wants a static lifetime? (replacing 'a with 'static in the code didn't help)
lifetime_bounds.rs:52:46: 52:56 error: `bitmapdata` does not live long enough
lifetime_bounds.rs:52 let bitmap = PixelImageSimple { pixels: &bitmapdata, width: 222, height:334 };
^~~~~~~~~~
note: reference must be valid for the static lifetime...
lifetime_bounds.rs:50:34: 69:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 50:33
lifetime_bounds.rs:50 let bitmapdata = vec![1,2,3];
lifetime_bounds.rs:51
lifetime_bounds.rs:52 let bitmap = PixelImageSimple { pixels: &bitmapdata, width: 222, height:334 };
lifetime_bounds.rs:53
lifetime_bounds.rs:54 let sharpen = ImageOperationSharpen { val: 34, bitmapdata: &bitmap };
lifetime_bounds.rs:55 let rotate = ImageOperationRotate { angle: 13.32, bitmapdata: &bitmap };
...
As an alternative approach I tried a solution using a collection
type CollectionOfImageOperations<'a> = Vec<&'a (ImageOperation<'a> + 'a)>;
but this gave me compile errors which made less sense to me than in the approach above. (It seems like I can only push one trait object to the vector - but why) - see rust-playground for the code and error.
Any hints & tips are welcome and appreciated.
PixelImageSimple
by value and put thebitmap
into anRc
and then clone theRc
to pass the cloned version by value into the other objects. is.gd/QIVXaN – oli_obkbitmap
when creating the sharpen object? – Syntactic FructoseRc
does nothing but increase the reference counter. No data is copied. – oli_obk