Open
Listed in
Description
Someone on the Tokio discord came across the following bad compiler error message. Given the following code:
use std::sync::Arc;
use futures::stream::{self, StreamExt};
struct MyStruct {}
impl MyStruct {
async fn import_all(&self, list: Arc<Vec<String>>) {
stream::iter(&*list)
.map(|txn| {
let bd_c = list.clone();
async move { self.import(bd_c, txn).await }
})
.buffer_unordered(10)
.collect::<Vec<bool>>()
.await;
}
async fn import(&self, list: Arc<Vec<String>>, now: &str) -> bool {
list.iter().any(|v| v == now)
}
}
#[tokio::main]
async fn main() {
let ms = MyStruct {};
tokio::spawn(async move {
ms.import_all(Arc::new(vec![])).await;
}).await.unwrap();
}
The current output is:
error: implementation of `FnOnce` is not general enough
--> src/main.rs:27:5
|
27 | tokio::spawn(async move {
| ^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'0 String) -> impl futures::Future` must implement `FnOnce<(&String,)>`, for any lifetime `'0`...
= note: ...but it actually implements `FnOnce<(&String,)>`
This is an incredibly confusing error message, and it isn't in the right place. This fix is to change import
to take an index instead of a reference in the last argument. Interestingly if you remove the main function, the error disappears. If you replace the import_all
function with a function returning a boxed future, then the error happens in the import_all
function instead.
cc @ryanobjc
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
JanBeh commentedon Oct 21, 2021
I encountered a similar error in a different context, as described here. Not sure if these two cases are related at all.
shepmaster commentedon Nov 24, 2021
See also #85516
jerry-best commentedon Dec 28, 2021
I just tripped over a very similar error. I resolved it similarly by handing around indexes instead of references, but I would have had no idea what was going on if not for this issue.
petrosagg commentedon Mar 19, 2022
I just hit this extremely confusing issue. My minimal reproduction seems to imply that depending on the incantation the compiler sometimes infers the lifetime on the closure as generic and sometimes as some specific lifetime. I have no idea why
tokio::spawn()
affects this though.Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e08e92aa9cdfa05a0b99a66869f9761a
guswynn commentedon Mar 22, 2022
@petrosagg it appears to be referring to
FnOnce
, but the type signature of theFnMut
being passed into themap
?this makes me think the compiler is confusing 2 trait bounds somewhere, very cursed
Niedzwiedzw commentedon Jul 2, 2022
happened to me today
for some reason this produces a cryptic error:
jakubdabek commentedon Jul 2, 2022
@petrosagg
tokio::spawn
requires the future to beSend
, and that's what triggers the error.On today's nightly (and beta
1.63.0-beta.2
) on the playground with the following example the error is different (same one is withtokio::spawn
):Error message:
It explains why the error happened, but gives zero information about what could be wrong, the
not general enough
one could at least somewhat pinpoint the location.In this example it can be fixed by using
futures::stream::iter(ints)
instead.@petrosagg's example also triggers a different error on nightly/beta:
higher-ranked lifetime error
in an async block #102211Yossipossi1 commentedon May 6, 2024
Thought I'd note that I got a similar error recently (on Rust 1.77.2 stable). @petrosagg's
type_hint
solution worked for me, just in case anyone else is still scratching their heads over this.rbtcollins commentedon Jul 30, 2024
using regular iterators doing chain.peekable will trigger this.
currently seeing if I can figure out an appropriate type_hint for this as there are no closures involved in my code at least
0x8f701 commentedon Aug 19, 2024
encountered this issue in a completely different case:
3 remaining items