-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
RPITIT "captures lifetime that does not appear in bounds" #128752
Comments
Yeah, you're right that this is not possible to fix. Opaques can't capture intersection lifetimes, since they're local to the body of the function and not represented by any of the params on the function that defines the RPITIT -- this is what the lifetime Sorry that the diagnostic does not make this clear this is the problem -- it shouldn't be saying "captures the lifetime The fact that the async example works is because that I'll look into making the diagnostic less misleading, though. |
#128753 suppresses the part that says "captures the lifetime |
That's an implementation choice though, isn't it? At least in my conceptual framework, an intersection lifetime is purely a function of those input lifetimes. In other words, this refinement should be possible. trait MyTrait {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
}
impl MyTrait for Foo {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> Pin<Box<dyn Future<Output = i32> + intersection<'a, 'b>>> { todo!() }
} Happy to be told either that my conceptual framework is wrong or that it is theoretically sound but we aren't ready to represent this anytime soon.. just trying to understand what is meant by "impossible" here :)
Thanks for that explanation. I bet we can emulate this in the proc macro @spastorino and I have been working on.
Thank you! |
Well, the real issue here is that the opaque type inference algorithm relies on being able to map a hidden type of an opaque back onto the lifetime parameters that the opaque captures. When we have some: type RPIT<'a, 'b> = Pin<Box<dyn Future<Output = i32> + '1>>
// ^^^^^^ These are the captures of the opaque ...and all we know from the environment is that As an aside, you can observe that this is fixed if we added I don't think calling this an implementation choice is particularly useful here, since it overlooks the things that makes it hard in the implementation. I could call anything that Rust does an implementation detail, but the fact here is that Rust does not have first-class intersection regions in its type system (like, notice that you have to go out of your way to invent a new syntax to represent a region to put into the
I don't believe this can be emulated in general, for the same reasons that futures cannot always be lowered into state machines because they can feature existential inner regions that can't be named. Specifically, if you wrote some: enum ManuallyDesugaredStateMachine<'a, 'b> {
State1 {
self_: &'a Foo,
x: &'b i32,
},
State2 {
fut: Pin<Box<dyn Future<Output = i32> + /* what do we put here? */>>,
},
Done,
} Then you'd either need to introduce some interesection region directly to the enum like |
Yeah this matches my understanding. I don't think "implementation detail" was a good choice of words. What I meant was that there's nothing fundamentally unsound about this pattern and a language like Rust could support it. But I get that I am totally glossing over its interaction with other features in the type system.
I meant with unsafe code. In this case I would stick a |
|
I don't believe that there's anything fundamentally unsound about this. |
…=spastorino Don't arbitrarily choose one upper bound for hidden captured region error message You could argue that the error message is objectively worse, even though it's more accurate. I guess we could also add a note explaining like "cannot capture the intersection of two regions" or something, though I'm not sure if that is confusing due to being totally technical jargon. This addresses the fact that rust-lang#128752 says "add `+ 'b`" even though it does nothing to fix the issue. It doesn't fix the issue's root cause, though. r? `@spastorino`
Rollup merge of rust-lang#128753 - compiler-errors:arbitrary-upper, r=spastorino Don't arbitrarily choose one upper bound for hidden captured region error message You could argue that the error message is objectively worse, even though it's more accurate. I guess we could also add a note explaining like "cannot capture the intersection of two regions" or something, though I'm not sure if that is confusing due to being totally technical jargon. This addresses the fact that rust-lang#128752 says "add `+ 'b`" even though it does nothing to fix the issue. It doesn't fix the issue's root cause, though. r? `@spastorino`
I tried this code: playground
Diagnostics
I got a nonsensical error message:
This is an RPITIT so the lifetime should not have to appear in the bounds to be captured. As you might expect, adding the
+ 'b
leads to a different error, and using theCaptures
trick does not work either (in fact, it is quite a mess of surprising errors: playground).Should this compile?
Diagnostics aside, it's understandable that this wouldn't compile, because the compiler doesn't know what to do with the extra
'dynosaur
lifetime inErasedMyTrait::foo
. It would have to generate an intersection lifetime to get the full return type of that method (the'dynosaur
inPin<Box<dyn Future<Output = i32> + 'dynosaur>>
.Adding a lifetime that corresponds to
'dynosaur
to the original trait does the trick:As I alluded to above, I don't think have we to know which lifetime
'dynosaur
corresponds to to know that the original program is sound. Representing it as the intersection of'a
and'b
should be enough to see that ourPin<Box<dyn Future>>
satisfies-> impl Future
in the signature of the method we're implementing.Through some magic it isn't necessary if we use async fn directly; this impl compiles fine:
I'm pretty much expecting to hear that this is too hard to support now, but the async fn chicanery gives me hope that it can be supported sooner.
Meta
rustc version:
The text was updated successfully, but these errors were encountered: