Noxivs
Noxivs

Reputation: 21

Is it possible to use the Any trait through channels?

This example is not right but it gives an idea of what I expect:

fn main() {
    let (chan, port) = channel();

    load(chan);

    let r = port.recv().unwrap().unwrap();
    println!("{}", r.downcast_ref::<String>().unwrap());
}

pub fn load<T:Send + Any>(sender: Sender<Option<T>>) {
    // do some works

    sender.send(Some(String::new("test") as Any);
}

I can't go further than this, due to these kinds of errors:

error: non-scalar cast:
error: cast to unsized type:

I am not sure, but Servo has something similar using the Deserialize/Serialize traits from Serde.

Upvotes: 0

Views: 530

Answers (1)

Shepmaster
Shepmaster

Reputation: 431669

Yes, it is possible to send a boxed trait object of the Any trait through a channel:

use std::sync::mpsc::{channel, Sender};
use std::any::Any;

fn main() {
    let (chan, port) = channel();

    load(chan);

    let r = port.recv().expect("Unable to receive");
    println!("{}", r.downcast_ref::<String>().expect("Not a string"));
}

pub fn load(sender: Sender<Box<Any>>) {
    let s = String::from("test");
    let s = Box::new(s) as Box<Any>;
    sender.send(s).expect("Unable to send");
}

Your original attempt doesn't make sense:

pub fn load<T:Send + Any>(sender: Sender<Option<T>>)

A generic type is determined at compile time, which means that T is a fixed type, such as String. If you know the type that is going through the channel, you don't need to use Any

String::new("test") as Any

This doesn't make sense because String::new takes no arguments. Additionally, you cannot cast a value to a trait - traits have no known size. They always need to be behind a pointer of some kind.

Upvotes: 4

Related Questions