# Could returning \`impl Trait\` in a trait be allowed here?

**URL:** <https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568>\
**Category:** language design\
**Created:** [June 16, 2020, 1:21pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568 "2020-06-16T13:21:54Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [June 16, 2020, 1:21pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/1 "2020-06-16T13:21:54Z")

</div>

`impl Trait` in return position is not supported in traits (not even with nightly features). However, I think it should be easy to implement, if the return type is not constrained by generics and lifetimes defined in the function:

```rust
trait Foo<'a> {
    fn bar(&'a self) -> impl Debug + 'a;
}

// this is roughly equivalent to

trait Foo<'a> {
    type Bar: Debug + 'a;

    fn bar(&'a self) -> Self::Bar;
}

```

The above code with the associated type works, and with [`#![feature(type_alias_impl_trait)]`](https://github.com/rust-lang/rust/issues/63063), it's even possible to use it for opaque types:

```rust
impl<'a> Foo<'a> for String {
    type Bar = impl Debug + 'a;

    fn bar(&'a self) -> Self::Bar {
        // note that this type can't be named!
        self.chars().filter(|c| c.is_ascii())
    }
}

```

However, it would be even nicer if `impl Trait` in return position was allowed here. What do you think?

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [June 16, 2020, 1:27pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/2 "2020-06-16T13:27:47Z")

</div>

AFAIK this has pretty much been the plan for years, just blocked on more fundamental trait system work.

[http://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/#complication-1-returning-impl-trait-in-traits-is-not-supported](http://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/#complication-1-returning-impl-trait-in-traits-is-not-supported)

> `impl Trait` in traits requires GATs

> Conceptually, GATs are fairly simple. Implementation wise, though, we’re still working on how to support them in rustc – this may require porting rustc to use [chalk](https://github.com/rust-lang/chalk), though that’s not entirely clear. In any case, this work is definitely underway, but it’s going to take more time.

RF 2071 included the `type Foo = impl Trait;` feature under a different syntax, though iirc not long ago everyone agreed that `type Foo = impl Trait;` is the best syntax for it after all. [Meta tracking issue for `impl Trait` · Issue #63066 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/63066) includes it explicitly on the checklist of `impl Trait`-related things we need to do.

EDIT: That same checklist also has [Meta tracking issue for `impl Trait` · Issue #63066 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/63066) for the "just a type alias" case of this syntax, which appears to be what you're specifically asking about. I don't know what the status of that is, but I wouldn't be surprised if it's also simply waiting on all of the other fundamental work to reach a tipping point.

---

<div class="post-metadata">

**Author:** ![Kestrer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kestrer/32/8190_2.png) [@Kestrer](https://internals.rust-lang.org/u/Kestrer)\
**Post date:** [June 16, 2020, 1:28pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/3 "2020-06-16T13:28:24Z")

</div>

If we do this we could also add non-self-referential async functions in traits.

---

<div class="post-metadata">

**Author:** ![jschievink](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jschievink/32/3063_2.png) [@jschievink](https://internals.rust-lang.org/u/jschievink)\
**Post date:** [June 16, 2020, 1:29pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/4 "2020-06-16T13:29:31Z")

</div>

Note that the OP is specifically asking about the case that does **not** require GATs

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 16, 2020, 2:56pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/6 "2020-06-16T14:56:40Z")

</div>

> [@Kestrer](#):
>
> If we do this we could also add non-self-referential async functions in traits.

Unfortunately there’s no syntax for this other than writing out the `-> impl Future` return type, `async fn` always capture all arguments even if they’re unused.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 16, 2020, 3:12pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/7 "2020-06-16T15:12:19Z")

</div>

One downside to this shorthand is you lose out on the ability to add extra constraints to the associated type like

```rust
where
  T: Foo<'a>
  T::Bar: Send

```

Or eventually (hopefully)

```rust
where T: Foo<'a, Bar: Send>

```

---

<div class="post-metadata">

**Author:** ![robinm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robinm/32/6255_2.png) [@robinm](https://internals.rust-lang.org/u/robinm)\
**Post date:** [June 16, 2020, 5:54pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/8 "2020-06-16T17:54:32Z")

</div>

Why do you say that you lose the ability to add extra constraints? Shouldn't this work (eventually)?

```rust
type T: impl Foo<'a, Bar: impl Send>

```

Note: I think that this requires GAT, so it's outside of what OP is asking.

---

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [June 16, 2020, 6:14pm UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/9 "2020-06-16T18:14:16Z")

</div>

I think what @Nemo157 meant is this:

```rust
trait A {
    type Output: ToString;
    fn a() -> Self::Output;
}

trait B {
    fn b() -> impl ToString;
}

fn foo<T: A, U: B>()
where
    T::Output: Send;
    // you can't constrain the return type of U::b() here!

```

---

<div class="post-metadata">

**Author:** ![robinm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robinm/32/6255_2.png) [@robinm](https://internals.rust-lang.org/u/robinm)\
**Post date:** [June 17, 2020, 7:32am UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/10 "2020-06-17T07:32:49Z")

</div>

That's right, but I'm pretty sure you can still do something like this (not tested):

```rust
fn foo<T: A, U: B>()
where
    <T::b as Fn() -> _>::Output: Send;

```

And with GAT, it would be easier to extract the return type of function. C++ is using that kind of tricks since ages, so I don't see why it wouldn't be possible to implement them in Rust (those tricks may requires GATs however).

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 17, 2020, 8:17am UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/11 "2020-06-17T08:17:53Z")

</div>

Potentially, though probably written closer to

```rust
fn foo<T: Foo, U>(_: T)
where
    T::b: Fn() -> U,
    U: Send

```

(Since `Fn::Output` is unstable, and you can't have placeholders inside type bounds). Doesn't work currently because `b` doesn't exist in the associated type namespace, and as far as I know there is no way to reference the type of the associated function. So would need at least an additional new feature to support that somehow.

(And note that it can't just be to introduce associated functions directly into the type namespace too, `trait Foo { type bar; fn bar(); }` is valid).

---

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [June 18, 2020, 3:56am UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/12 "2020-06-18T03:56:19Z")

</div>

I don't think `T::b` can be referenced as a type at all. Rust complains: "associated type `b` not found for `T`".

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 16, 2020, 3:56am UTC](https://internals.rust-lang.org/t/could-returning-impl-trait-in-a-trait-be-allowed-here/12568/13 "2020-09-16T03:56:19Z")

</div>

Closed on September 16, 2020, 3:56am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
