Is it possible to use `impl Trait` as a function's return type in a trait definition?

Ameo picture Ameo · Sep 14, 2016 · Viewed 10.7k times · Source

Is it at all possible to define functions inside of traits as having impl Trait return types? I want to create a trait that can be implemented by multiple structs so that the new() functions of all of them returns an object that they can all be used in the same way without having to write code specific to each one.

trait A {
    fn new() -> impl A;
}

However, I get the following error:

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --> src/lib.rs:2:17
  |
2 |     fn new() -> impl A;
  |                 ^^^^^^

Is this a limitation of the current implementation of impl Trait or am I using it wrong?

Answer

Shepmaster picture Shepmaster · Sep 14, 2016

As trentcl mentions, you cannot currently place impl Trait in the return position of a trait method.

From RFC 1522:

impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.

  • Eventually, we will want to allow the feature to be used within traits [...]

For now, you must use a boxed trait object:

trait A {
    fn new() -> Box<dyn A>;
}

See also:

Nightly only

If you wish to use unstable nightly features, you can use existential types (RFC 2071):

// 1.40.0-nightly (2019-11-05 1423bec54cf2db283b61)
#![feature(type_alias_impl_trait)]

trait FromTheFuture {
    type Iter: Iterator<Item = u8>;

    fn example(&self) -> Self::Iter;
}

impl FromTheFuture for u8 {
    type Iter = impl Iterator<Item = u8>;

    fn example(&self) -> Self::Iter {
        std::iter::repeat(*self).take(*self as usize)
    }
}

fn main() {
    for v in 7.example() {
        println!("{}", v);
    }
}