-
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
"does not live long enough" when returning Option<impl trait> #55535
Comments
cc #46413 because I think this may be a result of our temporary lifetime rules (and perhaps some interaction between them and other features like variance) here is the message we currently emit from the 2018 edition for the given code:
Following the advice provided (by adding a semicolon after the |
I seem to have found another similar case where this happens. If an struct Array {
inner: [u32; 3],
}
impl Array {
fn iter(&self) -> impl Iterator<Item = &u32> {
self.inner.iter()
}
fn compare(&self) -> bool {
let foo2 = Array { inner: [1, 2, 3u32] };
self.iter().zip(foo2.iter()).all(|(&x, &y)| x > y)
// Switching to a return statement fixes it:
//return self.iter().zip(foo2.iter()).all(|(&x, &y)| x > y);
}
} The error message actually does show how to fix the problem, though it's still fairly silly. Output:
|
Yeah, this has to do with the drop glue (or potential drop glue in the case of RPIT ( In that case, that drop glue runs at "the end of statement" w.r.t. the outer scope, not the inner one, which means that that drop glue runs after all the locals of that scope have been themselves dropped. So, if that Doing Here is a curious playground showcasing this behavior: use ::core::cell::Cell as Mut;
fn on_drop<'f, F: 'f>(f: F) -> impl 'f + Sized
// Feel free to replace the RPIT with:
// -> ::scopeguard::ScopeGuard<(), F>
where
F: FnOnce(()),
{
::scopeguard::guard((), f)
}
fn explicit_return(b: &Mut<bool>) {
let _local = on_drop(|()| b.set(true));
return drop(&on_drop(|()| b.set(false)));
}
fn implicit_return(b: &Mut<bool>) {
let _local = on_drop(|()| b.set(true));
drop(&on_drop(|()| b.set(false)))
}
fn test(f: impl FnOnce(&Mut<bool>)) -> bool {
let mut temporary_is_dropped_before_local = <_>::default(); /* or whatever */
f(Mut::from_mut(&mut temporary_is_dropped_before_local));
temporary_is_dropped_before_local
}
fn main() {
assert_eq!(test(explicit_return), true);
assert_eq!(test(implicit_return), false);
} |
This doesn't compile:
However, it compiles when impl trait is replaced with the concrete type:
It also compiles with impl trait if
Option
is removed:The text was updated successfully, but these errors were encountered: