Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I cast a literal value to a trait object?

Tags:

rust

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);
   |                   ^^
like image 321
Daniil Iaitskov Avatar asked Jul 10 '16 18:07

Daniil Iaitskov


2 Answers

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.

like image 75
Francis Gagné Avatar answered Sep 21 '22 02:09

Francis Gagné


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()));
like image 33
aSpex Avatar answered Sep 20 '22 02:09

aSpex