I have structs A and B, where B can be dereferenced into A.
A implements GetValue with the function .get_value(), and therefore B also indirectly implements GetValue.
Now I'd like to write a function print_value that can accept &A and &B, so it can internally call .get_value() on them. Technically this should be possible, because both of them can be dereferenced into &GetValue; &A by dereferencing once, and &B by dereferencing twice.
The question is: How do I specify the generic of print_value to achieve this?
Here is my attempt:
use std::ops::Deref;
//### external library code ######################
struct A(i32);
struct B(A);
impl Deref for B {
type Target = A;
fn deref(&self) -> &Self::Target {
&self.0
}
}
trait GetValue {
fn get_value(&self) -> i32;
}
impl GetValue for A {
fn get_value(&self) -> i32 {
self.0
}
}
//### my code ####################################
fn print_value<T: Deref>(val: T)
where
<T as Deref>::Target: GetValue,
{
println!("{}", val.get_value())
}
fn main() {
let a = A(1);
let b = B(A(2));
println!("{}", a.get_value());
println!("{}", b.get_value());
print_value(&a);
print_value(&b); // < fails with error "the trait bound `B: GetValue` is not satisfied"
}
The problem here is that <T as Deref>::Target: GetValue does not match &B, because &B would have to be dereferenced twice. The compiler automatically dereferences many times when a function is called, so is there a way to achieve the same through generics?
Note
I only have power over the implementation of print_value. I do not have the power over the other functions.
A more real-life example would be:
get_value=get_error_sourceA= an error typeB=Box<dyn A>GetValue=std::error::Error
I just wanted to keep it as abstract as possible to avoid confusion. I'm still quite certain that this is not an XY problem.