Skip to content

Closure-like blocks capture all generic type and const parameters #65442

Open
@jonhoo

Description

@jonhoo

I'd like to write the following code:

use std::future::Future;
struct Foo<A>(A);
impl<A> Foo<A> {
    fn bar<Q, R: Default>(&mut self, q: Q) -> impl Future<Output = R> {
        let _ = q;
        async move {
            R::default()
        }
    }
    
    fn baz(&mut self, x: &str) -> impl Future<Output = usize> {
        self.bar(x)
    }
}

In particular, I would like to have the impl Trait returned by baz not be tied to the lifetime of its &str argument. Since impl Trait captures the lifetimes of all generic arguments (as per RFC 1951), I can't write the code this way though. So instead, I tried

#![feature(type_alias_impl_trait)]
use std::future::Future;
struct Foo<A>(A);

type BarFut<A, R> = impl Future<Output = R>;
impl<A> Foo<A> {
    fn bar<Q, R: Default>(&mut self, q: Q) -> BarFut<A, R> {
        let _ = q;
        async move {
            R::default()
        }
    }
    
    fn baz(&mut self, x: &str) -> impl Future<Output = usize> {
        self.bar(x)
    }
}

However, with this, I get the error:

error: type parameter `Q` is part of concrete type but not used in parameter list for the `impl Trait` type alias

This seems odd, since Q is (intentionally) not used in the async block. I can work around this by adding an async fn and calling that instead of using async move, but that seems like an odd hack:

async fn make_r_fut<R: Default>() -> R {
    R::default()
}
// ...
    fn bar<Q, R: Default>(&mut self, q: Q) -> BarFut<A, R> {
        let _ = q;
        make_r_fut()
    }
// ...

Is it intentional that the async block "captures" Q here, even though it never contains a Q?

Metadata

Metadata

Assignees

Labels

A-async-awaitArea: Async & AwaitA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.T-langRelevant to the language team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions