6

I am trying to make this code more concise and to get rid of redundant variables. Is it possible to do so?

trait Foo {}
impl Foo for i32 {}
impl Foo for String {}

fn main() {
    let xi32: i32 = 10;
    let y = String::from("ooo");
    let mut foo_list: Vec<&Foo> = vec![];
    foo_list.push(&xi32 as &Foo);
    foo_list.push(&y as &Foo);
}

The following variant doesn't work:

foo_list.push(10 as Foo);
error[E0620]: cast to unsized type: `{integer}` as `Foo`
  --> src/main.rs:11:19
   |
11 |     foo_list.push(10 as Foo);
   |                   ^^^^^^^^^
   |
help: consider using a box or reference as appropriate
  --> src/main.rs:11:19
   |
11 |     foo_list.push(10 as Foo);
   |                   ^^
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Daniil Iaitskov
  • 5,525
  • 8
  • 39
  • 49

2 Answers2

7

Rust lets you take a reference to a temporary:

foo_list.push(&10 as &Foo);

This exact code won't work until Rust 1.21, where the literal value 10 is automatically promoted to a static value and then a reference is taken to it.

Before Rust 1.21, the temporary ceases to exist at the end of the statement, so you'd end up with a dangling reference in your vector. Therefore, you must use a variable to extend the value's lifetime.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Francis Gagné
  • 60,274
  • 7
  • 180
  • 155
5

You can use boxed trait objects to store values in the vector:

let mut box_list: Vec<Box<Foo>> = vec![];
box_list.push(Box::new(42));
box_list.push(Box::new("forty two".to_owned()));
aSpex
  • 4,790
  • 14
  • 25