Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to infer enough type information about _; type annotations or generic parameter binding required

Tags:

rust

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.

like image 654
Wim V Avatar asked Mar 15 '23 00:03

Wim V


1 Answers

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.

like image 124
Shepmaster Avatar answered Apr 17 '23 03:04

Shepmaster