I have a structure Foo
which is composed of some other types and I implement a trait on some container of those various types (Rust playground):
struct MyType1 {}
struct MyType2 {}
struct Foo {
field1: MyType1,
field2: MyType2,
}
trait MyTrait {
/// Just a simple default implementation to keep things simple
fn do_something(&self) {
println!("Hello world");
}
}
struct MyContainer<T> {
val: T,
}
// Use the default implementation for brevity.
impl MyTrait for MyContainer<Foo> {}
impl MyTrait for MyContainer<MyType1> {}
impl MyTrait for MyContainer<MyType2> {}
This should be fine.
Noting that Foo
is really a composition of MyType1
and MyType2
, what I actually want to do is this, which doesn't work:
impl MyTrait for MyContainer<Foo> {
fn do_something(&self) {
// clearly this won't work as MyType1 and MyType2 are not `Copy`, nor
// do I want to clone them.
MyContainer {
val: self.val.field1,
}
.do_something();
MyContainer {
val: self.val.field2,
}
.do_something();
}
}
I can create a blanket implementation that covers the reference case:
impl<'a, T> MyTrait for MyContainer<&'a T>
where
MyContainer<T>: MyTrait,
{
fn do_something(&self) {
println!("Inside ref trait")
}
}
such that I can create a MyContainer
around the reference:
impl MyTrait for MyContainer<Foo> {
fn do_something(&self) {
MyContainer {
val: &self.val.field1,
}
.do_something();
MyContainer {
val: &self.val.field2,
}
.do_something();
}
}
This doesn't address my problem because I want to run the implementation on MyContainer<T>
, not MyContainer<&T>
. MyContainer
is a verification marker structure that denotes correct completion of a verification method on T
. That is, putting a T
in MyContainer
denotes that T
is somehow "verified". The composing structure implements the necessary verification trait. It's really part of the API in which it's not overly onerous to implement new T
s, just a couple of traits is enough to have it work.
Since MyContainer
is trivial, it seems to me that it ought to be possible to coerce this to create a transient representation of MyContainer<T>
that does the right thing.
I'd prefer to do this with safe code, but unsafe might be the way to go. Is it possible to do what I want? Is there a better way to handle a wrapped composition structure?
This is different to other questions I've seen in which the trait is implemented on T
and it is desired to implement it on &T
without any extra effort. In this case, we have it implemented on MyContainer<T>
, and I want it implemented on MyContainer<&T>
to act like it was a MyContainer<T>
without any extra effort on the part of the implementers of MyType1
and MyType2
and any future MyTypeN
.
As per my understanding of the comments, I tried flipping the logic around, so that the implementation is made on the wrapped reference and the blanket implementation is imposed on the wrapped value, but I'm having trouble getting the trait bounds correct. The rust playground shows the compiler recursing infinitely before it gives up.