Cyclip
Cyclip

Reputation: 13

Why does storing &str in a Box<dyn Any> and downcasting it to a &Box<&str> always result in None?

I want to create a vector of structs each of which contains a field that can have any (multiple) type, being able to extract those values too. I've tried this:

use std::any::Any;

fn main() {
    let mut v: Vec<Box<dyn Any>> = Vec::new();
    v.push(Box::new("test"));
    v.push(Box::new(3i32));

    let string: &Box<&str> = &v[0].downcast_ref().unwrap(); // erroneous line

    println!("{}", string);

    let int: &Box<&i32> = &v[1].downcast_ref().unwrap(); // probably gives an error too

    println!("{}", int);
}

It should print out

test
3

Instead, it panics:

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:8:51

From what I understand, it downcasts to &str and unwraps to give &Box<&str>, except it returns a None value.

I've tried other stuff such as structs with generics but that's limited to only 1 type:

struct Item<T> {
    item: T,
}

fn main() {
    let mut v: Vec<Item<&str>> = Vec::new();
    v.push(Item { item: "hi" });
    v.push(Item { item: 3i32 }); // error because it can only be &str, not i32
}

How would I do this?

Upvotes: 1

Views: 109

Answers (1)

KamilCuk
KamilCuk

Reputation: 140960

You do not hold Box<&str> in Any. You hold &str in Any.

let string: &str = v[0]
    .downcast_ref::<&str>()
    .unwrap();

println!("{}", string);

let int: &i32 = v[1]
    .downcast_ref()  // Rust infers ::<i32>
    .unwrap();

println!("{}", int);

Upvotes: 6

Related Questions