Closed
Description
I tried this code:
use futures::{
Future,
task::{Context, Poll}
};
use std::pin::Pin;
pub struct ListFut<'a>(&'a mut [&'a mut [u8]]);
impl<'a> Future for ListFut<'a> {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
unimplemented!()
}
}
/// The compiler complains that "this parameter and the return type are declared
/// with different lifetimes"
pub async fn readv_at(bufs: &mut [&mut [u8]]) {
ListFut(bufs).await
}
/// The same thing, but making the lifetimes explicit
pub async fn readv_at2<'a, 'b>(bufs: &'a mut [&'b mut [u8]]) {
ListFut(bufs).await
}
/// But the compiler accepts this method just fine, because there is only one
/// lifetime.
pub async fn readv_at1<'a>(bufs: &'a mut [&'a mut [u8]]) {
ListFut(bufs).await
}
/// Even if we explicitly bound one lifetime by the other, the compiler still
/// can't handle it.
pub async fn readv_at3<'a, 'b: 'a>(bufs: &'a mut [&'b mut [u8]]) {
ListFut(bufs).await
}
I expected to see this happen: No error
Instead, this happened: For every variant with two lifetimes, the compiler complains "these two types are declared with different lifetimes... but data from bufs
flows into bufs
here"
This looks similar to #56238 , but I see that the commit which closed that issue didn't included any test cases involving slices.
Meta
rustc --version --verbose
:
rustc 1.48.0-nightly (d006f5734 2020-08-28)
rustc 1.42.0 (b8cedc004 2020-03-09)
Metadata
Metadata
Assignees
Labels
Area: Async & AwaitArea: Messages for errors, warnings, and lintsArea: Lifetimes / regionsAsync-await issues that are part of the "polish" areaAsync-await issues that have been triaged during a working group meeting.Category: This is a bug.Diagnostics: Confusing error or lint that should be reworked.Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.Call for participation: Help is requested to fix this issue.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Type
Projects
Status
Done
Milestone
Relationships
Development
No branches or pull requests
Activity
Matthias247 commentedon Sep 10, 2020
As discussed on discord I'm not sure whether this is a bug. It works if
ListFut
is declared asit works. That allows the 2 lifetimes to be separate - compared the original declaration which forces them to be the same.
It could be that the compiler interprets:
as
However I'm not sure whether this makes a difference here. On the first glance it doesn't, because all those references are pure "inputs". Nothing is returned, so as long as the lifetimes are covering the function duration we should be good - independent whether they are the same or different.
However on the other hand
readv_at
returns a hiddenimpl Future
, which carries the input lifetime forwards. Based on that it could matter if these are different or not.taiki-e commentedon Sep 10, 2020
This is because elided lifetimes are handled as different lifetimes. (in this case, handled as
&'1 mut &'2 mut [u8]
)It can be reproduced not only with async functions but also with normal functions:
playground
taiki-e commentedon Sep 10, 2020
fwiw,
'b
overlives than'a
, so this fails to compile, but you could compile it using a lifetime bound like'a: 'b, 'b
.tmandry commentedon Sep 15, 2020
Discussed in our async foundations triage meeting today.
We can solve this in two parts.. one would be to change the wording "...but data from
bufs
is returned here" in the async case to make it more clear that we're returning a future (or just not use the special case wording for returned at all.)EDIT: Added E- labels for this first part.
The other is not async-related, really, but has to do with improving the error message wording and suggestion.
Rollup merge of rust-lang#76765 - guswynn:async_return, r=tmandry
18 remaining items