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

Unexpected "one type is more general than the other" compiler error #144

Closed
gsson opened this issue Feb 27, 2021 · 4 comments
Closed

Unexpected "one type is more general than the other" compiler error #144

gsson opened this issue Feb 27, 2021 · 4 comments

Comments

@gsson
Copy link

gsson commented Feb 27, 2021

I have some async code with a collection of futures that I have called join_all on. It seems to work fine, but when I try to call that code call from an implementation from an #[async_trait], I am getting an error I don't quite understand;

error[E0308]: mismatched types
  --> src/lib.rs:50:39
   |
50 |       async fn create_trait(&self) -> V {
   |  _______________________________________^
51 | |         // This compiles
52 | |         // self.create_impl_join_all().await
53 | |         // This compiles
...  |
56 | |         self.create_impl_map_join_all().await
57 | |     }
   | |_____^ one type is more general than the other
   |
   = note: expected type `FnOnce<(V,)>`
              found type `FnOnce<(V<Box<dyn std::fmt::Display + std::marker::Send>>,)>`

The below code compiles if either of the map or join_all are called, but fails with the above error if both map and join_all are used.

In addition

  • changing T = Box<dyn Display + Send> into T = Box<usize> makes it compile
  • inlining the type, so V becomes pub struct V<T: ?Sized = dyn Display + Send + ?Sized> { _v: Box<T> } fails with the same message as above
  • inlining the type, so V becomes pub struct V { _v: Box<dyn Display + Send> } makes it compile
use async_trait::async_trait;
use futures::future::join_all;
use futures::FutureExt;
use std::fmt::Display;

pub struct V<T = Box<dyn Display + Send>> {
    _v: T
}

fn create_v(n: usize) -> V {
    V {
        _v: Box::new(n)
    }
}

async fn create_v_async(n: usize) -> V {
    create_v(n)
}

pub struct Test {}

impl Test {
    pub async fn create_impl_join_all(&self) -> V {
        let future = create_v_async(42);
        join_all(vec![future]).await.pop().unwrap()
    }

    pub async fn create_impl_map(&self) -> V {
        let future = create_v_async(42)
            .map(|rv| rv);
        future.await
    }

    pub async fn create_impl_map_join_all(&self) -> V {
        let future = create_v_async(42)
            .map(|rv| rv);
        join_all(vec![future]).await.pop().unwrap()
    }
}



#[async_trait]
pub trait Trait<T> {
    async fn create_trait(&self) -> T;
}

#[async_trait]
impl Trait<V> for Test {
    async fn create_trait(&self) -> V {
        // This compiles
        // self.create_impl_join_all().await
        // This compiles
        // self.create_impl_map().await
        // This fails to compile with a "one type is more general than the other" error
        self.create_impl_map_join_all().await
    }
}

Potentially related to #34 ?

@chpio
Copy link

chpio commented Mar 8, 2021

getting a similar error for this code

   --> crdt-enc-tokio/src/lib.rs:225:49
    |
225 |       ) -> Result<Vec<(Uuid, u64, VersionBytes)>> {
    |  _________________________________________________^
226 | |         async fn get_entry(
227 | |             path: &Path,
228 | |             actor: Uuid,
...   |
277 | |             .await
278 | |     }
    | |_____^ one type is more general than the other
    |
    = note: expected opaque type `impl futures::Future`
               found opaque type `impl futures::Future`

async-trait@0.1.42 seems to work for me, all newer versions (including 0.1.48) fail to build.

mzabaluev pushed a commit to input-output-hk/jormungandr that referenced this issue Mar 9, 2021
@tdyas
Copy link

tdyas commented Aug 3, 2021

I am seeing the same error when trying to upgrade async-trait in https://github.com/pantsbuild/pants from v0.1.42 to v0.1.43 and newer (starts to happen in v0.1.43).

   Compiling fs v0.0.1 (XXX/pants/src/rust/engine/fs)
error[E0308]: mismatched types
   --> fs/src/lib.rs:691:95
    |
691 |     async fn path_stats(&self, paths: Vec<PathBuf>) -> Result<Vec<Option<PathStat>>, io::Error> {
    |  _______________________________________________________________________________________________^
692 | |     future::try_join_all(
693 | |       paths
694 | |         .into_iter()
...   |
715 | |     .await
716 | |   }
    | |___^ one type is more general than the other
    |
   ::: /Users/XXX/.rustup/toolchains/1.54.0-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/future/mod.rs:61:43
    |
61  |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                             -------------------------------
    |                                             |
    |                                             the expected opaque type
    |                                             the found opaque type
    |
    = note: expected opaque type `impl futures::Future`
               found opaque type `impl futures::Future`

tdyas pushed a commit to pantsbuild/pants that referenced this issue Nov 1, 2021
…13445)

Upgrade `tonic` to v0.6.1 and `prost` to v0.9.0.

Note: `async-trait` has been pinned to the existing v0.1.42 in the Cargo.lock due to error referenced here:  #12486 (comment). See dtolnay/async-trait#144 for upstream discussion in `async-trait` repo.
@stuhood
Copy link

stuhood commented Apr 16, 2022

I am seeing the same error when trying to upgrade async-trait in https://github.com/pantsbuild/pants from v0.1.42 to v0.1.43 and newer (starts to happen in v0.1.43).

The above issue still reproduces in 0.1.53.

tdyas pushed a commit to pantsbuild/pants that referenced this issue Jul 29, 2022
Upgrade the `async-trait` crate to latest version. Refactor `PathStatGetter` to use a boxed future to work around upstream bug in the `async-trait` crate: dtolnay/async-trait#144
cczona pushed a commit to cczona/pants that referenced this issue Sep 1, 2022
Upgrade the `async-trait` crate to latest version. Refactor `PathStatGetter` to use a boxed future to work around upstream bug in the `async-trait` crate: dtolnay/async-trait#144
@dtolnay
Copy link
Owner

dtolnay commented Jan 22, 2023

Updated output on newer rustc:

error: higher-ranked lifetime error
  --> src/main.rs:50:39
   |
50 |       async fn create_trait(&self) -> V {
   |  _______________________________________^
51 | |         // This compiles
52 | |         // self.create_impl_join_all().await
53 | |         // This compiles
...  |
56 | |         self.create_impl_map_join_all().await
57 | |     }
   | |_____^
   |
   = note: could not prove `Pin<Box<[async block@src/main.rs:50:39: 57:6]>>: CoerceUnsized<Pin<Box<(dyn futures::Future<Output = V<Box<(dyn std::fmt::Display + std::marker::Send + 'e)>>> + std::marker::Send + 'f)>>>`

This is a rustc bug that is already reported in rust-lang/rust#82921.

@dtolnay dtolnay closed this as completed Jan 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants