Open DCNick3 opened 1 year ago
The error now becomes
error: implementation of `FnOnce` is not general enough
--> src/main.rs:41:5
|
41 | check_fn(beba);
| ^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'0 (i32, i32)) -> String` must implement `FnOnce<(&'1 (i32, i32),)>`, for any two lifetimes `'0` and `'1`...
= note: ...but it actually implements `FnOnce<(&(i32, i32),)>`
error: implementation of `Iterator` is not general enough
--> src/main.rs:41:5
|
41 | check_fn(beba);
| ^^^^^^^^^^^^^^ implementation of `Iterator` is not general enough
|
= note: `Iterator` would have to be implemented for the type `std::slice::Iter<'0, (i32, i32)>`, for any lifetime `'0`...
= note: ...but `Iterator` is actually implemented for the type `std::slice::Iter<'1, (i32, i32)>`, for some specific lifetime `'1`
It's still not clear what happened. But I'll mimimize as follows which emits the same errors implementation of `FnOnce`/`Iterator` is not general enough
.
use std::future::Future;
pub async fn get_by_id<I>(ids: I)
where
I: IntoIterator<Item = String>,
{
for s in ids {
async { s.as_bytes() }.await;
}
}
async fn beba() {
get_by_id([1].iter().map(|_| String::new())).await;
}
trait FnTrait {}
impl<F, Fut> FnTrait for F
where
F: Fn() -> Fut + Send + Sync + 'static,
Fut: Future<Output = ()> + Send + 'static,
{
}
fn check_fn<F: FnTrait>(_f: F) {}
fn main() {
check_fn(beba);
}
To make the code above compile (in some sense), you can do one of these
Send
bound on Fut
[1].into_iter()
manually desugar async fn
as impl Future
, but with with some twists and turns: I'll go along with this
pub fn get_by_id<I>(ids: I) -> impl Future<Output = ()>
where
I: IntoIterator<Item = String>,
{
async move {
for s in ids {
async { s.as_bytes() }.await;
}
}
}
// same errors: implementation of `FnOnce`/`Iterator` is not general enough
first try: -> impl Future<Output = ()>
pub fn get_by_id<I>(ids: I) -> impl Send + Future<Output = ()> { ... }
error: future cannot be sent between threads safely
--> src/main.rs:3:32
|
3 | pub fn get_by_id<I>(ids: I) -> impl Send + Future<Output = ()>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: captured value is not `Send`
--> src/main.rs:8:18
|
8 | for s in ids {
| ^^^ has type `I` which is not `Send`
help: consider further restricting this bound
|
5 | I: IntoIterator<Item = String> + std::marker::Send,
| +++++++++++++++++++
second try: -> impl Send + Future<Output = ()>
, cool, the error becomes friendlier and tells us what to do
// success
pub fn get_by_id<I>(ids: I) -> impl Send + Future<Output = ()>
where
I: Send + IntoIterator<Item = String>, // the compiler suggests
<I as IntoIterator>::IntoIter: Send // also the compiler suggests
third try (or maybe forth if you add one of the two bounds at a time): success.
For OP in question, by applying the third way, it compiles.
I have a similar case, where a mysterious error, triggered while the compiler is trying to prove something is Send
, is presented without that context.
This one doesn't have any dependencies. Same behavior in Stable and Nightly.
Compiling playground v0.0.1 (/playground)
error: implementation of `From` is not general enough
--> src/lib.rs:67:5
|
67 | spawn(handle_connection());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `From` is not general enough
|
= note: `Box<(dyn std::error::Error + Send + Sync + 'static)>` must implement `From<Box<(dyn std::error::Error + Send + Sync + '0)>>`, for any lifetime `'0`...
= note: ...but it actually implements `From<Box<(dyn std::error::Error + Send + Sync + 'static)>>`
error: could not compile `playground` (lib) due to 1 previous error
This one can be solved by refactoring the body of handle_connection
a little. But the issue is the error message.
...Mine at least is probably a duplicate of #102211.
Code
main.rs:
Cargo.toml:
Current output
Desired output
I am not sure of the exact wording, but it should explain that the failure is due to the
Future
returned from the function not implementingSend
andSync
Rationale and extra context
Without explanation of why does the passed function not implement the required trait, it is not immediately clear what the issue is.
Other cases
The error output is the same on stable and nightly
Anything else?
Originally minimized from this code using reqwest and teloxide