Hello, thanks for taking a look! Don't worry, I'm not trying to violate the orphan rule
Let's say I have a trait A with some implementation for a generic type T that implements B. I would like to "override" this "default" implementation for a specific type Special that also implements B.
Currently I am archiving this by introducing an empty marker trait UsesDefaultImplementation and adding an additional trait bound on T: B + UsesDefaultImplementation in my "default" implementation and just implementing the marker trait for every type except for Special (see below). However as
I am aware that UsesDefaultImplementation is a very good candidate for an auto trait, but I am afraid of auto traits never hitting the stable channel.
I was wondering if anybody knows some better syntax I could make use of. Ideally I was hoping for something like this:
trait A {..}
trait B {..}
impl<T> A for T where T: B {
...
}
impl A for Special {
//conflicting implementation with the one above,
// since Special also implements B
}
but unfortunately it raises an conflicting implementation error.
Current solution:
trait A {..}
trait B {..}
trait UsesDefaultImplementation;
impl<T> A for T where T: B + UsesDefaultImplementation {
...
}
impl A for Special {
}
// **This** is the cumbersome part I was hoping to avoid:
impl UsesDefaultImplementation for SomeTypeThatImplementsB {}
impl UsesDefaultImplementation for AnotherTypeThatImplementsB {}
// ... many more impl statements
Shorter nightly channel solution:
#![feature(negative_impls)]
#![feature(auto_traits)]
trait A {..}
trait B {..}
auto trait UsesDefaultImplementation {}
impl !UsesDefaultImplementation for Special {}
impl<T> A for T where T: B + UsesDefaultImplementation {
...
}
impl A for Special {
}
Is there another solution that I am not aware of that might be of interest?
Thanks for helping!
Is trait B under your control? If so, maybe it's possible to extend it such that the specialty becomes part of the trait.
E.g. you could add methods with default implementations to B, and specialize those for that specific type. Hard to say more without knowing any details, though.
The UnsafeCells are part of structs that refer to each other via the UnsafeCells in a graph like datastructure. While being a zero-cost abstraction wrapping all of the struct fields during their creation would be a lot of work in my case I'm afraid :')
Note that CopyOfDebugTraitToOverrideImplementations::fmt should be unsafe if you implement it like that, as it may not be safe to access the contents of an arbitrary UnsafeCell at an arbitrary time.