2

I understand this is illegal in Rust:

trait A { }
struct S { a: A, b: A }

The reason is that all members except the last one must be sized, and a trait is not sized.

Does this mean it is impossible to have a struct/tuple of traits? How would I return a pair of values from a function and I only know that they implement a certain trait?

rityzmon
  • 1,945
  • 16
  • 26

1 Answers1

7

You've already identified the problem of type being not sized, so you just need to turn it into sized type.

If you don't own the objects, you may use reference.

struct S1<'a> {
    a: &'a A,
    b: &'a A,
}

You can use two lifetimes instead of one if they are different.

struct S1<'a, 'b> {
    a: &'a A,
    b: &'b A,
}

If you want to own the objects, you may use Box.

struct S2 {
    a: Box<A>,
    b: Box<A>,
}

Further, if you know the concrete type at compile time, and you just want to write generic code, you can write generic struct too

struct S3<A1: A, A2: A> {
    a: A1,
    b: A2,
}

In S3, each A1 or A2 represents a concrete type that implements trait A when you instantiate it in your code.

WiSaGaN
  • 46,887
  • 10
  • 54
  • 88
  • Thanks. I think S3 is what I'm looking for, but how does that declaration make the struct sized so that the compiler doesn't complain? – rityzmon Nov 01 '16 at 09:15
  • @rityzmon, it's because `A1` and `A2` will be actual types when instantiated which are sized although trait `A` is not. You'll have to specify type `A1` and `A2` when you use the generic struct in your code. That's how (and when) the compiler knows the size of your types, because you literally tell the compiler what exactly those types are. – WiSaGaN Nov 01 '16 at 09:39
  • Thanks. And how would I use the same technique if I want to return a tuple of traits from a function? One specific problem I'm trying to figure out is `trait T { fn func(&self, x: &Self) -> (Self, Self); }`. The single function in the trait takes another object of the same type, and returns two more objects of the same type. – rityzmon Nov 01 '16 at 10:26
  • @rityzmon, since you need `Self` to be a sized type so that it can be used in a tuple, you just need to declare `T` to be `std::marker::Sized` in your trait declaration. Here is an example: https://play.rust-lang.org/?gist=00374c64cacb8ad774d41f1457bb62cb&version=stable&backtrace=0 – WiSaGaN Nov 01 '16 at 11:03