This seems not possible currently:
trait MyTrait {
fn foo() -> impl Trait;
}
However this is possible:
trait MyTrait {
fn foo<T: Trait>() -> T;
}
But is only really useful when you have some way of returning the exact same generic T
, for example with a function in Trait
returning Self
.
From a syntax perspective, it would be nice if these two versions both were valid and equivalent, because -> impl Trait
is much more readable.
But this is still very rarely useful and does not really express "foo
returns something implementing Trait
", but rather "given some type implementing Trait
, foo
can return it", i.e. the type needs to be known to the caller.
This introduces a lot of coupling in the code because whenever foo
changes, users of foo
need to adapt. It would be better if callers would just have to know "whatever foo
returns, it implements Trait
".
As an example, foo
might want to return some type of Iterator
, but not need to be specifically commited to any concrete implementation of an Iterator
, so that it can easily change in the future without disrupting callers.
The way to achieve this right now seems to be:
trait Trait {}
struct A;
impl Trait for A {}
trait MyTrait {
type T: Trait;
fn foo() -> Self::T;
}
struct Imp1;
impl MyTrait for Imp1 {
type T = A;
fn foo() -> Self::T {
A
}
}
struct Imp2;
impl MyTrait for Imp2 {
type T = A;
fn foo() -> Self::T {
A
}
}
fn main() {
let a: A = Imp1::foo();
let a2: A = Imp2::foo();
}
So we have to explicitly define each implementation to give it the exact type we want to return, but this means we can't use default trait methods, because we can't set a default for an associated type.
My question is, will it eventually be possible to define default trait methods returning impl Trait
, or a default associated type? Which RFCs are relevant to this? I have seen associated_type_defaults, which would help a bit, but using the nightly version it was not possible to "assume associated type defaults in the trait defining them" (playground).
And it would also be useful if the concrete return type could be implicit, i.e. we can define a default trait method returning some trait, the concrete type is inferred from the returned type in the default method, but never mentioned explicitly. When an implementation of the trait overrides the default, it could be forced to use the same concrete type as the default implementation if needed. Although callers should only expect a type implementing the trait, so shouldn't it be possible to return any type implementing the mentioned trait?