Setting default/fallback for type that cannot be infered

example:

use std::marker::PhantomData;

struct A<T, U = T> {
    a: T,
    b: PhantomData<U>,
}

impl<T, U> A<T, U> {
    fn new(a: T) -> Self {
        Self {
            a,
            b: PhantomData,
        }
    }
}

fn main() {
    let a = A::new(3);
}

since U = T I would expect it to fallback/default to T when U cannot be inferred.

this should also be the case for functions, e.g.:

use std::marker::PhantomData;

struct A<T, U = T> {
    a: PhantomData<T>,
    b: PhantomData<U>,
}

impl<T, U> A<T, U> {
    fn new() -> Self {
        Self {
            a: PhantomData,
            b: PhantomData,
        }
    }

    fn f(&self, a: T) {}
}

fn main() {
    let a = A::new();
    a.f(2);
}

(as if right now, T from the original type is inferred but U did not fallback/default to T)

I don't have the canonical issue for this handy, but this is a known problem; type parameter defaults are only applied syntactically, when a type argument is missing in a place where it is required, not to resolve ambiguities in inference.

It hasn't been done yet because it is hard.

5 Likes

"fallback" is fundamentally hard in the same way that coercions are hard: when you're running type inference, you don't know where to add them.

(This is one of the costs of having a system where foo.into() works. In something like C++98 where each subexpression needs to be able to determine its own type in a standalone way, then you can look at the type it produced and see if that matches the type that's expected. But when things work bidirectionally it's just fundamentally harder. If done poorly you ruin compilation time because you have to try the full powerset of possible locations.)

2 Likes

Which, AFAIK, Swift actually does and has to give up in some cases because it can’t find a unique solution in a reasonable time but also can’t prove that one does not exist.

It was part of this RFC tracking issue. I'm unaware of a canonical replacement issue.

related issue: Inconsistent rustc inference · Issue #141103 · rust-lang/rust · GitHub