Skip to content

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

Closed
@gsson

Description

@gsson

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 ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions