Skip to content
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

Why implementation of iterator is not generic enough in async context? #71671

Open
Stargateur opened this issue Apr 29, 2020 · 2 comments
Open

Why implementation of iterator is not generic enough in async context? #71671

Stargateur opened this issue Apr 29, 2020 · 2 comments
Labels
A-async-await A-diagnostics AsyncAwait-Triaged C-bug D-confusing T-compiler

Comments

@Stargateur
Copy link
Contributor

@Stargateur Stargateur commented Apr 29, 2020

Cross posting stackoverflow because it's look like a compiler bug/limitation.


Given the following snippet:

use futures::stream::{self, StreamExt};

async fn from_bar(bar: &[Vec<&u8>]) {
    let x = bar.iter().flat_map(|i| i.iter().map(|_| async { 42 }));
    let foo: Vec<_> = stream::iter(x).collect().await;
}

#[tokio::main]
async fn main() {
    for bar in vec![] {
        tokio::spawn(async {
            from_bar(bar).await;
        });
    }
}

I get the following errors:

error[E0308]: mismatched types
  --> src/main.rs:11:9
   |
11 |         tokio::spawn(async {
   |         ^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected type `std::ops::FnOnce<(&&u8,)>`
              found type `std::ops::FnOnce<(&&u8,)>`

error: implementation of `std::iter::Iterator` is not general enough
    --> src/main.rs:11:9
     |
11   |           tokio::spawn(async {
     |           ^^^^^^^^^^^^ implementation of `std::iter::Iterator` is not general enough
     |
     = note: `std::iter::Iterator` would have to be implemented for the type `std::slice::Iter<'0, &u8>`, for any lifetime `'0`...
     = note: ...but `std::iter::Iterator` is actually implemented for the type `std::slice::Iter<'1, &u8>`, for some specific lifetime `'1`

I was expecting no error because the lifetimes seem to be correct to me. Note that removing main() or removing the code inside from_bar() both eliminate the errors. Not only that, the error messages are also very strange. They may be related to a regression in the compiler, though more than that they seem to be in the wrong place (maybe related).

Version rustc 1.43.0 (4fb7144ed 2020-04-20):

[dependencies]
futures = '0.3.1'

[dependencies.tokio]
version = '0.2'
features = ['full']

Maybe related #64650

@Stargateur Stargateur added the C-bug label Apr 29, 2020
@Alexendoo Alexendoo added A-async-await D-confusing T-compiler A-diagnostics labels Apr 29, 2020
@tmandry tmandry added this to On deck in wg-async work via automation May 12, 2020
@tmandry tmandry added the AsyncAwait-Triaged label May 12, 2020
@tmandry
Copy link
Contributor

@tmandry tmandry commented May 12, 2020

Triage: This error message is clearly confusing. We should see how we can improve it, or if this is already part of #64650 or #64552.

@jorendorff
Copy link
Contributor

@jorendorff jorendorff commented May 26, 2021

This bit me today. Reduced test case (playground):

pub trait Robot {
    type Id;
}

pub type DynRobot = Box<dyn Robot<Id = u32> + Send>;

impl Robot for DynRobot {
    type Id = u32;
}

struct IRobot<R: Robot> {
    id: R::Id,
    robot: R,
}

// stand-in for tokio::spawn
fn this_is_send<T: Send>(value: T) -> T {
    value
}

fn test(source: DynRobot) {
    let _my_task = this_is_send(async move {
        let _my_iter = IRobot {
            id: 32,
            robot: source,
        };
        tokio::task::yield_now().await;
    });
}

rustc output:

  Compiling playground v0.0.1 (/playground)
error: implementation of `Robot` is not general enough
  --> src/lib.rs:22:20
   |
22 |     let _my_task = this_is_send(async move {
   |                    ^^^^^^^^^^^^ implementation of `Robot` is not general enough
   |
   = note: `Box<(dyn Robot<Id = u32> + Send + '0)>` must implement `Robot`, for any lifetime `'0`...
   = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot<Id = u32> + Send + 'static)>`

error: aborting due to previous error

error: could not compile `playground`

To learn more, run the command again with --verbose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await A-diagnostics AsyncAwait-Triaged C-bug D-confusing T-compiler
Projects
None yet
Development

No branches or pull requests

4 participants