Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl Trait that does not capture generic argument #65442

Open
jonhoo opened this issue Oct 15, 2019 · 4 comments

Comments

@jonhoo
Copy link
Contributor

@jonhoo jonhoo commented Oct 15, 2019

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?

@Mark-Simulacrum

This comment has been minimized.

Copy link
Member

@Mark-Simulacrum Mark-Simulacrum commented Oct 18, 2019

I suspect the answer is no -- cc @rust-lang/wg-async-await -- this might contribute to "not Send/Sync" errors if we're capturing what we shouldn't be

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis commented Oct 22, 2019

I think my expectation is that the explicit type = impl Trait version should work. I'm not 100% sure why it doesn't, but I can do some investigation.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis commented Oct 22, 2019

Assigning to myself to investigate and document the cause of the issue, at least.

@Arnavion

This comment has been minimized.

Copy link

@Arnavion Arnavion commented Nov 16, 2019

Related to / dupe of #42940

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.