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)
}