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

Existential types: Unused closure environment is part of concrete type #57678

Closed
zroug opened this Issue Jan 16, 2019 · 5 comments

Comments

Projects
None yet
5 participants
@zroug
Copy link

zroug commented Jan 16, 2019

Compare

#![feature(existential_type)]

existential type T: ;
fn test(_unused: impl Copy) -> T {
    || {}
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=194cca6bdb23ec0b634bc01dea43abd4

which results in error: type parameter `impl Copy` is part of concrete type but not used in parameter list for existential type to

#![feature(existential_type)]

existential type T: ;
fn test(_unused: impl Copy) -> T {
    fn workaround() -> impl Fn() {
        || {}
    }
    workaround()
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=23789461920ea49d85042a9604f86f97

which compiles fine.

There are quite a few open issues for existential types so I hope I haven't overlooked a duplicate. #42940 might be related.

Meta

rustc 1.33.0-nightly (03acbd71c 2019-01-14)
binary: rustc
commit-hash: 03acbd71c977cd63ce5f39ba9b6fe9ffd578785a
commit-date: 2019-01-14
host: x86_64-unknown-linux-gnu
release: 1.33.0-nightly
LLVM version: 8.0
@Centril

This comment has been minimized.

Copy link
Contributor

Centril commented Jan 17, 2019

@alexreg

This comment has been minimized.

Copy link
Contributor

alexreg commented Jan 17, 2019

I'm confident this is a duplicate of #42940, but let's wait for others to confirm.

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Jan 17, 2019

This isn't a duplicate of that issue-- the error message here is "correct" in a sense. The issue here is that the closure being generated is still generic over type parameters, even when they're unused. We don't have any logic today (AFAIK) for detecting when a type parameter goes unused in a closure, so by default they capture all generic parameters in scope. Desugaring the argument-position impl Copy makes this more obvious:

#![feature(existential_type)]

existential type T: ;
fn test<A>() -> T {
    || {}
}
error: type parameter `A` is part of concrete type but not used in parameter list for existential type
 --> src/main.rs:4:19
  |
4 |   fn test<A>() -> T {
  |  ___________________^
5 | |     || {}
6 | | }
  | |_^

The fix here is to detect when a type parameter is unused in a closure and make it so that the closure is no longer generic over that parameter. I remember talking with @nikomatsakis about this in the past and I think they indicated that this was hard to do in the current system.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 22, 2019

That would indeed be quite hard to do. For one thing, the set of generics is determined quite early on -- this would require us to wait until we see what the closure does. But also, it's non-trivial to figure out when the type parameter was important to the closure.

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Jan 22, 2019

I guess I'll close this for now as "working as intended", though it'd definitely be nice to drop unnecessary type parameters from closures anyways (for codegen purposes).

@cramertj cramertj closed this Jan 22, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment