In my actual code I have some type Complex<A, B, C> and I want to set a default C = usize since C is an index-like type. I tried to achieve this through a type alias but realized that the default from the type alias seems to be ignored/not take priority. Here is a simplified example.
struct Wrap<T>(T);
impl<T> Wrap<T> {
pub fn new(t: T) -> Self{
Self(t)
}
}
impl<T> Wrap<T> where T: Copy + Into<usize> {
fn to_usize(&self) -> usize {
self.0.into()
}
}
type WrapUsize<T = usize> = Wrap<T>;
type WrapUsize2 = Wrap<usize>;
let out = Wrap::<usize>::new(1).to_usize(); // Compiles.
let out = WrapUsize::new(1).to_usize(); // Does not compile.
let out = WrapUsize2::new(1).to_usize(); // Compiles, but now I can not override the default through `WrapUsize2`.
In the line:
let out = WrapUsize::new(1).to_usize(); // Does not compile.
the type of out resolves to Wrap<i32>, with i32 being the default type for integer literals. Compilation fails because Wrap<T>::to_usize requires T: Copy + Into<usize> which i32 does not implement.
However, I expect the type of out to resolve to Wrap<usize>, because I expect the type alias to force Wrap::new to resolve to Wrap::<usize>::new. What is going on?
let out = Wrap::<_, _, usize>::new((), (), 1).to_usize();
let out = WrapUsize::<_, _>::new((), (), 1).to_usize();
let out = <WrapUsize<_, _>>::new((), (), 1).to_usize();
In short you need the qualified type expression (starts with <...>:: like <WrapUsize<_, _>>::) or a non-empty turbofish (WrapUsize::<_, _>) for the defaults to take effect. More details are in this section.