How to "impl<T> A for T {}"?

As said in the title, how do I implement something for each struct?

What I want is something similar to:

trait Identifiable {
  fn get_id(&self) -> &str;
}

impl<T : Identifiable> Debug for T {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}({})", std::any::type_name::<T>(), self.get_id())
    }
}

I know about default methods in traits but I don't want to add anything to each struct implementing Identifiable and still to make it work.

Rust doesn't have any sort of reflection or dynamic type introspection, so you can't avoid implementing the trait for each struct individually if you want to have struct-specific data.

If the boilerplate is the problem, then create a derive macro.

The problem with your example is that you don't own the Debug trait or all types (the uncovered T parameter), so your implementation of Debug can't be accepted as it would result in multiple implementations for the same type (e.g. str already has a Debug implementation which you cannot override). The particular rules around what blanket implementations you can and can't write are known as the orphan rules.

You could wrap T in a local newtype. Or you could put the functionality in your own trait.

trait Identifiable {
    fn get_id(&self) -> &str;
    fn fmt_id(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}({})", std::any::type_name::<Self>(), self.get_id())
    }
}
1 Like

str doesn't implement Identifiable :slight_smile:

I understand orphan rule (at least I think so) but why isn't it possible to overcome orphan rule when my trait is private? In that case only I can be the owner of all types implementing my trait, so there should be no conflicts with apps/libs using my library.

In that case compiler should just forbid implementing Debug for all structs that implement Identifiable.

Problem is, what if you implement Identifiable for type A and another crate, with no relation with your crate, implements Debug for A. This means that whoever tries to use both crates at the same time will get a compile error, and avoiding this was deemed more important than lifting the limitations of the orphan rule (which is what's preventing your impl).

1 Like

To elaborate a little bit,

is untrue as you can implement your private trait for types you don't own (like str).

I have also wished for some way to specify my blanket implementation should only apply to local types, but that doesn't exist. In those cases I generally fall back to some sort of macro.

1 Like

is untrue as you can implement your private trait for types you don't own (like str ).

well... in that case compiler should throw an error (aka my last sentence). Also str can't implement private Identifiable outside of my crate, so all errors are on me.

Problem is, what if you implement Identifiable for type A and another crate, with no relation with your crate, implements Debug for A .

another crate can't implement Debug for type A because of the orphan rule. Both type A and Debug are not part of external crate.

What I mean is something like:

crate a:

pub struct A;

crate b, depends on crate a:

trait B {} // no pub, so it's private
impl B for a::A {}
impl<T: B> Debug for T {}

crate c, depends on crate a:

trait C {} // no pub, so it's private
impl C for a::A {}
impl<T: C> Debug for T {}

Under your proposal both crate b and crate c compile alone because they essentially do the same thing, however the moment crate d depends on both of them it gets a compile error due to two implementations of Debug for a::A.

So, when you say

this is the same reason you can't write the implementation in the first post.

2 Likes

yeah... I didn't think of this scenario :frowning:
It is probably possible to allow when both private trait + private struct but it is way to niche case to worth the effort...

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.