Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

It is possible to use std::rc::Rc with a trait type?

Tags:

rust

The code looks like this:

// Simplified
pub trait Field: Send + Sync + Clone {
    fn name(&self);
}

#[deriving(Clone)]
pub enum Select {
    SelectOnly(Vec<Rc<Field>>),
    SelectAll
}

The error is:

the trait `core::kinds::Sized` is not implemented for the type `Field+'static`

Is there any other way to have the vector with reference-counted immutable objects of trait type?

I suppose that I can rewrite the code like this:

#[deriving(Clone)]
pub enum Select {
    SelectOnly(Vec<Rc<Box<Field>>>),
    SelectAll
}

Is it the right way?

like image 692
Stanislav Panferov Avatar asked Oct 13 '14 07:10

Stanislav Panferov


2 Answers

It is possible to create an trait object with an Rc as of Rust 1.1. This compiles:

use std::rc::Rc;

trait Field: Send + Sync {
    fn name(&self);
}

enum Select {
    Only(Vec<Rc<Field>>),
    All,
}

// ---

struct Example;
impl Field for Example {
    fn name(&self) {}
}

fn main() {
    let fields: Vec<Rc<Field>> = vec![Rc::new(Example)];
    Select::Only(fields);
}

Note that your original example used Clone, but you cannot make such a trait into a trait object because it is not object safe. I've removed it to answer the question.

I also removed the redundancy of the enum variant names.

like image 62
Shepmaster Avatar answered Oct 28 '22 23:10

Shepmaster


I believe that it should be possible with DST, but Rust is not there just yet. The major motivation for DST was exactly the desire to use trait objects with any kind of smart pointer. As far as I know, this should be possible by 1.0 release.

As a temporary workaround, indeed, you can use Rc<Box<T>>, though this kind of double indirection is unfortunate.

like image 28
Vladimir Matveev Avatar answered Oct 28 '22 23:10

Vladimir Matveev