Both generic and concrete function implementations for generic structs

Hey all! I am trying to understand the following behavior. If I define a generic struct and I intend to implement a method or associated function for it, I can do either of the two, but not bot at the same time. So for example, for

struct Struct<T> {
    field: T,
}

This compiles

impl Struct<u8> {
    fn method(self) {}
    fn associated_fn() {}
}

impl Struct<u16> {
    fn method(self) {}
    fn associated_fn() {}
}

And so does

impl<T> Struct<T> {
    fn method(self) {}
    fn associated_fn() {}
}

But if I mix the two, I get a duplicate name (E0592) error.

I tried to find more information about this in the documentation but didn't manage. I understand it might have something to do with what is also discussed in the specialization RFC (1210) but that seems to be mostly relevant for trait implementation.

Could someone please explain this to me and/or point me to the relevant documentation?
Thanks.

You have already found it. Nobody have found a way to do what you want to do guaranteed-safely and Rust developers are reluctant to implement “but your are holding it wrong” strategy (even if issues may all be detected during compile-time they have be detected very far away from place where these functions are implemented).

I don't know if it's documented beyond the error page. A concrete type can't have two inherent things with the same name and that's pretty much it.

Rust doesn't have actual specialization yet, and I think it's a long way off. (It can't be as general as the original RFC and still be sound.) Specialization of inherent methods can be considered a special case of the general version, in a sense.

You can emulate it very coarsely by exploiting method resolution precedence, which favors inherent methods (and similarly for associated function calls). But note that it does not work in a generic context and is thus of limited utility (and may be confusing).

1 Like

Thanks for the replies!

@quinedot I understand that there cannot be more than one inherent impl for the same generic struct with the same name, but then how come that the following does compile?

impl Struct<u8> {
    fn method(self) {}
    fn associated_fn() {}
}

impl Struct<u16> {
    fn method(self) {}
    fn associated_fn() {}
}

I'm more surprised that that would work, than by the fact that the generic and the specific impls alongside each other don't.

For the same concrete type. A Struct<u8> is not a Struct<u16>. The implementations don't overlap. The generic plus specific implementations do overlap. The compiler will error if it can't infer which method/function to call or if the function definition may not exist (no matter which approach is taken -- generic implementation or a set of non-generic implementations).

(Granted, there are scenarios where the implementations don't overlap but the compiler fails to recognize it. It might be as simple as "one generic impl or any number of non-generic impls (per parameter), but I'm not 100% confident about that. Sometimes this is for purposes of forward compatibility,[1] and sometimes it's just the lack of a feature -- sometimes intentional,[2] sometimes incidental.)


  1. it shouldn't be a breaking change to implement a new trait ↩︎

  2. for example ↩︎

3 Likes

Thank you, now that's clear! With your input I was able to find:

  • Coherence in Chalk by Sunjay Varma
  • rustc_hir_analysis crate, which explains that it's the coherence checking mechanism who's responsible for checking non-overlapping impls
  • Lastly, the check_item method for the InherentOverlapChecker seems to be responsible for the compiler error, either in check_for_duplicate_items_in_impl or in check_for_common_items_in_impls - I would say the first, but this section is above my pay grade and I cannot find more documentation about it at the moment

I guess I'll circle back to this when (and if) I look into the rustc internals.

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.