Home > Blockchain >  Multiple `impl`s satisfying `Arc<dyn DS>: Borrow<_>` found in the following crates: `all
Multiple `impl`s satisfying `Arc<dyn DS>: Borrow<_>` found in the following crates: `all

Time:12-08

My funciton's signature is something like:

pub fn execute<DS: Borrow<impl DataSet   ?Sized>> (
    data: DS)

Where DataSet is my Trait (object). I want to use Borrow to be able to use Arc, like Arc dyn DataSet or just &impl DataSet in this funciton. Compiler however doesn't like this. I get an error:

error[E0283]: type annotations needed
   --> driver\src\api\mod.rs:127:13
    |
127 |             base_engine::execute_aggregation(
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `impl DataSet   ?Sized` declared on the function `execute_aggregation`
    |
    = note: multiple `impl`s satisfying `Arc<dyn DataSet>: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl<T> Borrow<T> for Arc<T>
              where T: ?Sized;
            - impl<T> Borrow<T> for T
              where T: ?Sized;
note: required by a bound in `execute_aggregation`
   --> c:\rust\ultima\base_engine\src\api\execute_agg.rs:15:32
    |
15  | pub fn execute_aggregation<DS: Borrow<impl DataSet   ?Sized>> (
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `execute_aggregation`

Why are there conflicting implementations and what can I do to work around that?

A minimal reproducible example:

use std::{sync::Arc, borrow::Borrow};

pub fn test () {
    let tt = St{name: "Anatoly".into()};
    let att = Arc::new(tt);
    ppr(att);
}

fn ppr<T: Borrow<impl Namable>> (s: T) {
    let name = s.borrow();
    let n = name.my_name();
    println!("{}", n)
}

struct St {
    name: String
}

trait Namable {
    fn my_name(&self) -> &String;
}

impl Namable for St {
    fn my_name(&self) -> &String {
        &self.name
    }
}

CodePudding user response:

Okay I was not able to get it to work with Borrow, but I was able to get it to work two other ways:

pub fn test() {
    let tt = St { name: "Anatoly".into() };

    // both take a reference for a direct value
    ppr(&tt);
    ppr2(&tt);

    let att = Arc::new(tt);

    // in order to get a reference from the `Arc`
    // non-deref version requires the ref-deref pattern
    ppr(&*att);
    // deref version must take the `Arc` directly
    // which might mean it requires more `Arc` cloning
    ppr2(att);
    

    let tt = St { name: "Anatoly".into() };
    let att: Arc<dyn Namable> = Arc::new(tt);

    // `Arc<dyn Namable>` usage same as `Arc<T>` usage
    ppr(&*att);
    ppr2(att);
}

// I prefer this version
fn ppr<T: Namable   ?Sized>(s: &T) {
    let name = s.borrow();
    let n = name.my_name();
    println!("{}", n)
}

fn ppr2<T: Deref>(s: T)
where <T as Deref>::Target: Namable
{
    let name = s.deref();
    let n = name.my_name();
    println!("{}", n)
}
  • Related