Is it possible to "patching" a trait's implementation for a custom type?

The "patching" word is kind of inaccurate but I have no better words, and this is not an actual problem in Rust (but in C#, it does.)

I just want to know whether it is possible to overcome such problem in case it happened with Rust.


Since C# has a very poor .ToString() support, I want to write a .ToDetailedString() manually, which

  1. Calls .ToDetailedString() for some class that I want to know its parameter rather than just its default className
  2. Calls .ToString() as a fall-back to ensure we could got a string rather than an exception.

The problem is that, for all complex type that may contains the type I'm interested in, I have to implement a .ToDetailedString() for them, otherwise, since .ToString() call won't calling .ToDetailedString(), a fall-back .ToString() method won't show the detail of the interested data anymore.

In Rust, things seems very similar(except we already have a defailed output (with :?)), but I'm still curious about that, is it possible to write something that allow to modify an original trait Foo::bar that:

  1. calling a .modified_bar() if it is implemented
  2. calling a .bar() as a fallback, and
  3. if more .bar() is called within the fallback path, calling .modified_bar() instead if it is implemented.

It might be possible if we could "patching" a trait:

trait BaseTrait {
    fn foo(&self);
}
struct Patcher : patch BaseTrait {
    // in case we want to send extra parameter
    data: i32
}
impl Patcher for Ty for BaseTrait {
    fn foo(&self, &base) {
        base.foo(); // calling original foo
        self.patch(|&mut this|{
            base.foo()  // calling base.foo, but in case Patcher call is available, calling the patched one.
        });
    }
}

Such patch might helpful for controlling the ident.

Points 1 and 2 will be handled by specialization, whenever that gets stabilized.

For the third point, I doubt it would be possible to implement, since each type concretely defines its own methods. I suspect you'd more likely get what you want from one of the various proposals (we've had several here) to relax the orphan rule, such that you could implement .modified_bar() for your dependencies such that it has the behavior you want.

1 Like

I'm afraid orphan rule does not help.

I could easily define a wrapper struct to obey orphan rule:

struct Wrapper<T: BaseTrait, U>(T, extra_parameter: U);
trait MyTrait {...}
impl<T: BaseTrait> MyTrait for Wrapper<T, i32> {...}

Here, in case we want to patch a trait, we have to implement MyTrait for all struct that impl BaseTrait, and we may gain no benefit since in case we call a BaseTrait, that call will call BaseTrait rather than MyTrait recursively. In case to keep calling MyTrait, we have to rewrite all the trait implementations.

This is why I ask "is it possible to patch a trait."