Default trait type not working for type inference?

So, the following code seems like it should work:

use std::marker::PhantomData;

pub struct Foo<X=()> {
    _a: PhantomData<X>,
}

impl<X> Foo<X> {
    pub fn new() -> Self {
        Foo {
            _a: PhantomData,
        }
    }
}

fn main() {
    let f = Foo::new();
}

(Playground)

But, I get the error:

   Compiling playground v0.0.1 (/playground)
error[E0282]: type annotations needed for `Foo<X>`
  --> src/main.rs:16:13
   |
16 |     let f = Foo::new();
   |         -   ^^^^^^^^ cannot infer type for `X`
   |         |
   |         consider giving `f` the explicit type `Foo<X>`, where the type parameter `X` is specified

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Why? Shouldn't the type inference see the clearly-marked default type for X and use that when it can't find a clear definition? I get that X can't be discovered from the line let f = Foo::new(); alone, but shouldn't that be where the default type comes into play? Otherwise, I have to have the clunky:

    let f: Foo<()> = Foo::new();

when it seems like that should be pretty obvious what was intended (and no other cases seem to make sense, otherwise I would have provided a type, so it doesn't seem like it could be ambiguous).

Edit to add:

I could just specify a type in the new constructor, which will avoid type inference altogether:

impl<X> Foo<X> {
    pub fn new(_: X) -> Self {

then call it as let f = Foo::new(());

This works, but is also quite clunky, and seems to defeat the purpose of a default type anyway.

Any thoughts or corrections on my usage (or understanding) of this feature?

Thanks!

As mentioned here, type inference works counterintuitively in this case.

Foo::new() tries to infer all type parameters and it doesn't use type defaults.

You need let f = <Foo>::new(); for your code to compile.

Ah, I didn't see that. What an... odd syntax.

But in any case, this won't work for me, as the example above is but a simple reproduction of my actual use case, where I have many type parameters, and the <Foo>::new() syntax assumes the default for ALL of them (with no inference), so that doesn't really help my case.

Thanks for the heads up, anyway, though!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.