'in rust-lang, what's the difference between `static_fly::<Number>(number);` and `static_fly(number);`

in rust-lang, what's the difference between static_fly::<Number>(number); and static_fly(number);

here is a demo:

enum Number {
    Zero,
    One,
    Two,
}

trait Fly {
    fn fly(&self);
}

impl Fly for Number {
    fn fly(&self) {
        println!("flying number: {}", self)
    }
}

// 静态分发
fn static_fly<T: Fly>(f: T){
    print!("静态分发\t");
    f.fly()
}

fn main() {
    let number = Zero;
    // 泛型的分发调用
    static_fly(number);                 // <-- here is the 1st method for calling static_fly
    // static_fly::<Number>(number);    // <-- here is the 2nd method for calling static_fly
}

what's the difference between this two calling.



Solution 1:[1]

The two methods of calling the function are equivalent in this case.

Given enough information, Rust can infer generic type arguments. In the case of static_fly(number) the compiler has inferred that T is Number. In the case of static_fly::<Number>(number) you are just providing the type for the type argument T explicitly.

This is very similar to other kinds of inference the compiler performs. For example, both of these statements are also equivalent:

let number = Zero;
let number: Number = Zero;

It's the same principle -- in one case we specify the type, in the other we let the compiler figure it out.

Solution 2:[2]

Its the same thing as let a = b; compared to let a: Type = b;. It gives you the option to explicitly state which type is used in an operation. Normally Rust can infer what you want to do, however if there is any ambiguity the compiler will ask you to explicitly specify a type.

For example, the most common instance of this I run into is when calling .collect() on an iterator.


fn foo(vals: &[u32]) -> Vec<u32> {
    // In this case there is no ambiguity since the result of collect must
    // be a `Vec<u32>`. Since the compiler can infer the type, we don't need
    // to state what type collect uses.
    vals.iter()
        .map(|x| x * 2)
        .collect()
}

fn bar(vals: &[u32]) -> u32 {
    // In this case the compiler is unable to infer a type as collect can
    // create any type that can be initialized with an iterator.
    let mut a = vals.iter()
        .map(|x| x * 2)
        .collect();

    a.sort();
    a[0]
}

For this example there are a couple ways you can fix bar.

// State the type of a so the compiler can infer collect's types
let mut a: Vec<u32> = vals.iter()
    .map(|x| x * 2)
    .collect();

// State the types used by the function in question but let the compiler infer a's type
let mut a = vals.iter()
    .map(|x| x * 2)
    .collect::<Vec<u32>>();

Another option is to only partially state the type in question. A type name can be replaced with an underscore to tell the compiler to infer that part of a type. This is generally my preferred way of handling this specific case.

// Tell the compiler we will collect items to a Vec, but let it infer the content type
let mut a = vals.iter()
    .map(|x| x * 2)
    .collect::<Vec<_>>();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cdhowie
Solution 2 Locke