4
votes
trait Bar {
    fn bar(&self);
}
enum Foo<T: Bar> {
    F1,
    F2(T)
}
struct Something;
impl Bar for Something {
    fn bar(&self) {
    }
}
fn main() {
    let a = Foo::F2(Something); //<== this works fine.
    let b = Foo::F1; //<== gives a compilation error.
}

Compilation error E0282: Unable to infer enough type information about _; type annotations or generic parameter binding required.

I understand why the compiler is complaining but can't seem to figure out how to do this without having to assign a type to T in the F1 case.

1
without having to assign a type to T — Why don't you want to assign a concrete type to T?Shepmaster
Well I meant in the case of F1 I don't need the type T so it seems pointless to do so. If there is no way to do this I can live with assigning a type to T in all cases.Wim V
You can specify a default value for T, but it seems to be buggy with inference: This doesn't work, but this does.oli_obk
Ah, that's just a not yet stable feature: github.com/rust-lang/rust/issues/29101, works now: is.gd/GIiHHPoli_obk
Thanks for the answer but default is not what I was looking for. I followed Shepmaster adivce and solved it like this is.gd/lz8TRrWim V

1 Answers

7
votes

Enum variants do not have their own type. There is only the type of the enum itself. Check out this example:

enum Thing<T> {
    One,
    Two(T),
}

fn main() {
    let a = Thing::One;
    let b = Thing::Two(true);
}

The type of b is a Thing<bool>. The type has no mention of Two. The same thing needs to happen for a, but there's nothing that the compiler can use to infer the value of T, so you have to provide it explicitly:

let a = Thing::One::<u8>;

And an even-smaller example is to use an enum that is built-in and very familiar — Option:

fn main() {
    // let a = None;
    let a = None::<u8>;
    let b = Some(true);
}

I don't need the type T so it seems pointless to do so.

Let's dive in a bit deeper. An enum takes up the space of the max of all the variants (plus a wee bit to tell them apart):

enum Foo {
    One(u64),
    Two(u8),
}

fn main() {
    println!("{}", std::mem::size_of::<u64>());
    // 8
    println!("{}", std::mem::size_of::<u8>());
    // 1
    println!("{}", std::mem::size_of::<Foo>());
    // 16
}

Also, all variants of the same enum take up the same amount of space:

fn main() {
    let a = Some(true);
    let b = None::<bool>;

    println!("{}", std::mem::size_of_val(&a));
    // 2
    println!("{}", std::mem::size_of_val(&b));
    // 2
}

This helps lead us to the realization that not all Nones are the same:

fn main() {
    let a = None::<u8>;
    println!("{}", std::mem::size_of_val(&a));
    // 2

    let b = None::<u64>;
    println!("{}", std::mem::size_of_val(&b));
    // 16
}

Thus it is important to know exactly what kind of None you have. This extends to every kind of enum and variant.