-
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
Explicit lifetime required on scoped value #123195
Comments
This is likely due to #118882. I don't believe this is a regression, since this is a correct error message -- the lifetime on |
Ah, makes sense. I thought there was some inference going on. |
What about this? (I'm sure I'm just misreading/thinking wrong somehere here, too..) use std::{
future::Future,
marker::PhantomData,
ops::{Deref, DerefMut},
pin::Pin,
};
pub trait ScopedFuture<'upper_bound, 'subject, Bound = ImpliedLifetimeBound<'upper_bound, 'subject>>:
Future
where
Bound: sealed::Sealed,
{
}
pub type ImpliedLifetimeBound<'upper_bound, 'subject> = PhantomData<&'subject &'upper_bound ()>;
impl<'upper_bound: 'subject, 'subject, Fut: Future + 'subject> ScopedFuture<'upper_bound, 'subject>
for Fut
{
}
mod sealed {
pub trait Sealed {}
impl<'upper_bound, 'a> Sealed for super::ImpliedLifetimeBound<'upper_bound, 'a> {}
}
/// A [`Future`] wrapper type that imposes an upper bound on its lifetime's duration.
#[derive(Clone, Debug)]
pub struct ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
future: Fut,
scope: ImpliedLifetimeBound<'upper_bound, 'subject>,
}
impl<'upper_bound, 'subject, Fut> ScopedFutureWrapper<'upper_bound, 'subject, Fut> {
pin_utils::unsafe_pinned!(future: Fut);
}
impl<'upper_bound, 'subject, Fut: Future> Future
for ScopedFutureWrapper<'upper_bound, 'subject, Fut>
{
type Output = Fut::Output;
fn poll(
self: Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
self.future().poll(cx)
}
}
struct Resource;
struct Wrapper<'a>(&'a mut Resource);
impl Deref for Wrapper<'_> {
type Target = Resource;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl DerefMut for Wrapper<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
struct Owner {
resource: Resource,
}
impl Owner {
async fn obtain(&mut self) -> Wrapper<'_> {
Wrapper(&mut self.resource)
}
}
async fn works_on_stable<'a, F, Fut>(owner: &'a mut Owner, func: F)
where
for<'conn> F: FnOnce(&'conn mut Resource) -> ScopedFutureWrapper<'conn, 'a, Fut>,
Fut: Future,
{
let mut conn = owner.obtain().await;
func(&mut conn).await;
} A bit more involved, yes. Here's the issue:
|
So the async fn works_on_stable<'a, F, Fut>(owner: &'a mut Owner, func: F)
where
for<'conn> F: FnOnce(&'conn mut Resource) -> ScopedFutureWrapper<'conn, 'a, Fut>,
Fut: Future,
{
let mut conn = owner.obtain().await;
- func(&mut conn).await;
+ func(conn.0).await;
} You can move the mutable reference out of |
It's interesting that the local lifetime is upper-bounded. It's not something I would have expected here, since it's all derived from the top and just borrows all the way down. (also about moving the reference out of the structure, that's a bit hard in the real-world case I'm encountering it in. The real-world case is a database connection borrowed from a pool, and the connection is wrapped inside a wrapper to return it back on drop, etc etc.) |
@aumetra -- that has to do with mutable reborrows and the signature of
You may want to rework the way you're using |
Thing is, the execution of the function is guaranteed to finish while I have the lease, is it not?
The expression of this idea is probably just wrong in terms of trait bounds. |
This is an issue with the
scoped-futures
library, which is aFuture
-specific implementation of a technique outlined in this article.On stable code I wrote compiles just fine, but on beta it fails. In simple cases this is solved by adding a lifetime, but in other cases the fix can get rather gnarly.
I managed to minimize it down into a small sample:
Code
I tried this code:
I expected to see this happen: It simply compiles.
Instead, this happened: A lifetime-related compiler error happened.
Error message:
Version it worked on
Version with regression
The latest beta
rustc --version --verbose
:@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged
The text was updated successfully, but these errors were encountered: