How to bypass or relax orphan rules

My requirements is as below, is there any workaround ?

impl ForeignTrait for Arc<dyn LocalTrait> {
// ...
}

And looks like Box can work, but why Arc does not work ?

impl ForeignTrait for Box<dyn LocalTrait> {
// ...
}

The difference is that Box<T>, along with &T and &mut T, is marked as #[fundamental], so impls like this are allowed. The same is not true for Arc.

Read more about #[fundamental] here.

There's a universally-applicable and pretty easy solution: you can always define a newtype wrapper around whatever foreign type you are trying to implement a trait for.

struct MyWrapper(Arc<dyn LocalTrait>);

impl ForeignTrait for MyWrapper {
    // ...
}
3 Likes

No, I can not use the newtype pattern. The reason is that, the LocalTrait implementations in my code base include some recursive structures like below:

type or paste code here

pub struct MyStruct {
first: Arc<dyn LocalTrait>,
second: Arc<dyn LocalTrait>,
..................
}

impl LocalTrait for MyStruct {
}

And the LocalTrait and ForeignTrait method need to access those structs, those methods do not accept a
wrapped new type.

But what exactly prevents you from declaring MyStruct with newtype fields? You are in control of that type, after all.

2 Likes

No, I can not do that, besides MyStruct, there are many structs implement the LocalTrait and have recursive fields.

Is there any reason you can’t impl ForeignTrait for dyn LocalTrait¹ and then rely on auto-dereferencing to bypass the Arcs?

Also, if the trait needs to be aware of the Arc, note that object-safe traits can use self: Arc<Self> as a method receiver.


¹ Alternatively, declare a supertrait: trait LocalTrait: ForeignTrait { … }

3 Likes