You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TAIT: hidden type captures lifetime that does not appear in bounds #104691
error[E0700]: hidden type for `<&Thingy as Trait>::FooFn<'_>` captures lifetime that does not appear in bounds
--> src/lib.rs:16:9
|
13 | impl Trait for &Thingy {
| - hidden type `[closure@src/lib.rs:16:9: 16:16]` captures the anonymous lifetime as defined here
...
16 | / move || {
17 | | println!("{}", self.0);
18 | | }
| |_________^
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
The provided code does indeed capture the implicit lifetime 'b: the closure upvar is &'c mut 'b Thingy.
So, IMO, the error is legitimate, and previous implementation erroneously considered 'b as allowed, which is inconsistent with how RPIT worked. Do you agree with those TAIT semantics @oli-obk?
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?
Shouldn't it be taken care of by where Self: 'a? It means any possible lifetime in Self outlives 'a, so saying "FooFn captures 'a" should be "strong enough" (?)
Also, forcing the user to write every single lifetime is going to be quite unergonomic.
I've noticed let _ = self is not enough to trigger the error. It does trigger in the original code, but it doesn't when I extract it to a separate crate, nor in the playground. Not sure why. println!("{}", self.0); always triggers it. I've updated the first post.
nightly-2022-11-22 is out now, so it's failing in the playground now.
@oli-obk how would you fix the code so that it works? I've tried + 'a + 'b and variations of it, but can't get it to compile.
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
this avoids capturing the &mut &Thingy in foo, avoiding the problematic case you're encountering.
Shouldn't it be taken care of by where Self: 'a? It means any possible lifetime in Self outlives 'a, so saying "FooFn captures 'a" should be "strong enough" (?)
that's the wrong end of where we should be figuring out what's wrong here. I am now realizing that
@oli-obk I think the presence of a mut in &'c mut 'b Thingy prevents leveraging the 'b outlives 'c bound. With shared reference, all works well, and the code is accepted. With a mut, we have no guarantee that 'b itself isn't relevant eg. for assignment. Or am I wrong in this?
Activity
cjgillot commentedon Nov 22, 2022
Is this a bug or a bugfix? If I name lifetimes:
The provided code does indeed capture the implicit lifetime
'b: the closure upvar is&'c mut 'b Thingy.So, IMO, the error is legitimate, and previous implementation erroneously considered
'bas allowed, which is inconsistent with how RPIT worked. Do you agree with those TAIT semantics @oli-obk?oli-obk commentedon Nov 22, 2022
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?
oli-obk commentedon Nov 22, 2022
But yea, I'd expect this to fail without a 'b bound
Dirbaio commentedon Nov 22, 2022
Shouldn't it be taken care of by
where Self: 'a? It means any possible lifetime inSelfoutlives'a, so saying "FooFn captures 'a" should be "strong enough" (?)Also, forcing the user to write every single lifetime is going to be quite unergonomic.
Dirbaio commentedon Nov 23, 2022
I've noticed
let _ = selfis not enough to trigger the error. It does trigger in the original code, but it doesn't when I extract it to a separate crate, nor in the playground. Not sure why.println!("{}", self.0);always triggers it. I've updated the first post.nightly-2022-11-22is out now, so it's failing in the playground now.Dirbaio commentedon Nov 23, 2022
@oli-obk how would you fix the code so that it works? I've tried
+ 'a + 'band variations of it, but can't get it to compile.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
This issue is breaking a lot of uses of GAT+TAIT for manually-desugared async traits: here, here, here, here, here, here
oli-obk commentedon Nov 23, 2022
this avoids capturing the
&mut &Thingyinfoo, avoiding the problematic case you're encountering.that's the wrong end of where we should be figuring out what's wrong here. I am now realizing that
while correctly causing
Should also allow us to realize that
&'c mut 'b Thingymeans'boutlives'cand thus we may capture'bif'cis in the bounds.But that doesn't even work for RPIT (playground):
I'm moderately certain this will compile with
-Zchalkand will be solved by implied boundscjgillot commentedon Nov 24, 2022
@oli-obk I think the presence of a
mutin&'c mut 'b Thingyprevents leveraging the'boutlives'cbound. With shared reference, all works well, and the code is accepted. With amut, we have no guarantee that'bitself isn't relevant eg. for assignment. Or am I wrong in this?oli-obk commentedon Nov 24, 2022
Ah. If we didn't correctly handle variance here, we'd be able to write something with 'c lifetime into something with 'b lifetime.
oli-obk commentedon Nov 24, 2022
The
foo_innersituation works, because it changes that reference to &&Thingy with not mutable refs.Closing as working as intended