Description
Some types are only visible through the traits that they implement. Currently, when Rust cannot infer a type it will either raise an error or, in some unclearly-defined situations, default the type to !
(or ()
). Perhaps we could allow defaulting in more situations and allow the defaulting to be trait-directed.
For example, the signature of Iterator::unzip
is:
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
Self: Iterator<Item = (A, B)>,
Now suppose I write:
let (_, foo) = some_iterator.unzip();
...
for x in foo {
...
}
If I haven't touched foo
anywhere else my code, then this won't compile. All rust knows about foo
's type is that it must impl Default + Extend<X> + IntoIterator<Item=X>
, and there may be lots of types that satisfy this requirement. However Vec<X>
is, in some sense, the canonical type that satisfies these requirements - when iterated it gives back the exact same items that where .extend
-ed into it, in the exact same order. Perhaps the compiler should be able to infer Vec<X>
in this case. Perhaps the standard library should be able to specify Vec<X>
as the inferred type in cases like this with a declaration like:
default<A> Default + Extend<A> + IntoIterator<Item=A> = Vec<A>;
Multiple default
declarations could override each other by being more specific in much the same way that impl specialization works. When the compiler tries to default a type which satisfies some required bounds B
, it looks for the most specific trait A <: B
for which there is a default type, and uses that type if it satisfies B
.
The current behaviour of defaulting to !
could be replaced by a declaration in libcore
of:
default ?Sized = !;
There could also be default of (just for example):
default Default = ();
So, is this a good idea? Or is it terrible?