-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
TAIT: hidden type captures lifetime that does not appear in bounds #104691
Comments
Is this a bug or a bugfix? If I name lifetimes: pub trait Trait {
type FooFn<'a>: FnOnce() + 'a where Self: 'a;
fn foo(&mut self) -> Self::FooFn<'_>;
}
struct Thingy;
impl<'b> Trait for &'b Thingy {
type FooFn<'a> = impl FnOnce() + 'a where Self: 'a;
fn foo<'c>(&'c mut self) -> Self::FooFn<'c> {
move || {
let _ = self;
}
}
} The provided code does indeed capture the implicit lifetime |
I tried the same thing but realized the original also passes on playground until tomorrow. So I don't know if explicit lifetimes actually change anything? |
But yea, I'd expect this to fail without a 'b bound |
Shouldn't it be taken care of by Also, forcing the user to write every single lifetime is going to be quite unergonomic. |
I've noticed
|
@oli-obk how would you fix the code so that it works? I've tried Also, I've found it compiles if you add extra indirection through a method without changing any signature. This really makes me believe the original code is sound and should be accepted. playground impl Trait for &Thingy {
type FooFn<'a> = impl FnOnce() + 'a where Self: 'a;
fn foo(&mut self) -> Self::FooFn<'_> {
self.foo_inner()
}
}
impl Thingy {
fn foo_inner(&self) -> impl FnOnce() + '_ {
move || {
println!("{}", self.0);
}
}
} This issue is breaking a lot of uses of GAT+TAIT for manually-desugared async traits: here, here, here, here, here, here |
impl Thingy {
fn foo_inner(&self) -> impl FnOnce() + '_ {
move || {
println!("{}", self.0);
}
}
} this avoids capturing the
that's the wrong end of where we should be figuring out what's wrong here. I am now realizing that pub trait Trait {
type FooFn<'a>: FnOnce() + 'a where Self: 'a;
fn foo(&mut self) -> Self::FooFn<'_>;
}
struct Thingy;
impl<'b> Trait for &'b Thingy {
type FooFn<'a> = impl FnOnce() + 'a where Self: 'a;
fn foo<'c>(&'c mut self) -> Self::FooFn<'c> {
move || {
let _ = self;
}
}
} while correctly causing
Should also allow us to realize that But that doesn't even work for RPIT (playground): struct Thingy(u32);
fn foo<'c, 'b>(x: &'c mut &'b Thingy) -> impl FnOnce() + 'c {
move || {
println!("{}", x.0);
}
} I'm moderately certain this will compile with |
@oli-obk I think the presence of a |
Ah. If we didn't correctly handle variance here, we'd be able to write something with 'c lifetime into something with 'b lifetime. |
The Closing as working as intended |
playground
fails with
while this used to work before. I think because the
where Self: 'a
part takes care of the capture (?).Not present in nightly yet, found it by building 1cbc459 from git master. Bisected it to 7fe6f36 which is #103491 @cjgillot
@rustbot label F-type_alias_impl_trait
The text was updated successfully, but these errors were encountered: