Skip to content

support default impl for specialization #37653

Open

Description

@nikomatsakis

View all comments

Update 2026-08-06

Some tests were added in #160520, but this issue needs review for completeness.


rust-lang/rfcs#1210 included support for default impl, which declared a set of defaults that other impls can inherit (if they correspond to a subset of the default impl's types). This was intended as a replacement/improvement of the existing default methods that appear in trait bodies (it was also originally called partial impl). Unfortunately, this feature is not yet implemented!

Some things to be sure of:

  • a default impl need not include all items from the trait
  • a default impl alone does not mean that a type implements the trait
  • all items in a default impl are (implicitly) default and hence specializable

cc #31844

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    on Nov 8, 2016
  2. nikomatsakis commented on Nov 8, 2016

    @nikomatsakis
    ContributorAuthor
  3. added a commit that references this issue on Apr 27, 2017
  4. giannicic commented on Apr 27, 2017

    @giannicic
    Contributor

    @nikomatsakis
    the PR addressing the 3rd task list item has been merged.
    Now i'm working on the first two points.

  5. nikomatsakis commented on Apr 28, 2017

    @nikomatsakis
    ContributorAuthor

    @giannicic awesome!

  6. Phlosioneer commented on Aug 1, 2017

    @Phlosioneer
    Contributor

    Any progress on this?

  7. giannicic commented on Aug 2, 2017

    @giannicic
    Contributor

    @Phlosioneer
    Yes, the first point is done. Currently I'm working on the second one.
    I've looked at the trait resolution and identified where to place the default impl trait implementation check, now I'm figuring out how to properly implement this check because i need to differentiate it based on the cause of the obligation.
    For example, if i have a default impl that doesn't implement all the methods of the trait Foo, like the following

    trait Foo {
        fn foo_one(&self) -> &'static str;
        fn foo_two(&self) -> &'static str;
    }
    
    default impl<T> Foo for T {
        fn foo_one(&self) -> &'static str {
            "generic"
        }
    }
    
    struct MyStruct;
    

    a call like MyStruct.foo_one() should pass the trait resolution because of the first point.
    Instead if i call foo(MyStruct) with foo like fn foo<T: Foo>(x: T) -> &'static str the trait resolution should fail because of the second point.
    It could pass if the default impl implements all the methods of the Trait

  8. petrochenkov commented on Dec 2, 2017

    @petrochenkov
    Contributor

    Can inherent impls be default?

    This currently compiles successfully, but the compiler has zero tests for it, so it's probably unintended.

    #![feature(specialization)]
    
    struct S;
    
    default impl S {}
    
    fn main() {}

    The general idea is reasonable though, e.g.

    struct S<T>(T);
    
    default impl<T> S<T> { fn f() { println!("Hello world!") } }
    impl S<u8> { fn f() { println!("Goodbye world!") } } // This currently errors
  9. petrochenkov commented on Dec 2, 2017

    @petrochenkov
    Contributor

    Can auto trait impls (including negative ones) be default?

    This is currently accepted:

    struct S;
    struct Z;
    default unsafe impl Send for S {}
    default impl !Send for Z {}
  10. petrochenkov commented on Dec 3, 2017

    @petrochenkov
    Contributor

    #46455 conservatively makes both #37653 (comment) and #37653 (comment) errors.

  11. Restioson commented on Dec 3, 2017

    @Restioson

    Really excited for full support of specialization (esp. point 2)! +1

  12. 5 remaining items

  13. nikomatsakis commented on Feb 27, 2018

    @nikomatsakis
    ContributorAuthor

    I am torn. On the one hand, I liked the "economy" of using default. I feel like having partial impl is its own sort of complexity. On the other hand, I think there is a kind of assumption that a default impl { .. } ought to be equivalent to impl { default ... }. I'm not sure though if that means that this is a natural rule that we ought to respect, or a matter of needing more education. Perhaps -- even -- it is the default keyword on functions and items that should be changed (e.g., to specializable or something).

  14. Restioson commented on Feb 27, 2018

    @Restioson

    Personally, I was slightly confused as to why partial impl was scrapped in favour of default impl - default impl doesn't really sound like it can be partial...

  15. RalfJung commented on Apr 19, 2020

    @RalfJung
    Member

    all items in a default impl are (implicitly) default and hence specializable

    I think this is a serious limitation, because it means there is no way to have a partial impl where some items are not specializable. I do not see that limitation discussed in the RFC, nor a motivation for why it might be required. It's a big RFC though, so maybe I missed it?

    Here is a short discussion with a use-case for a partial unspecializable impl. Basically the idea is to implement some associated types of the trait, and then provide some default implementations that require this particular choice of associated type. I think the current approach makes that kind of reuse fundamentally impossible.

  16. nikomatsakis commented on Apr 20, 2020

    @nikomatsakis
    ContributorAuthor

    @RalfJung it was a deliberate simplification, but one that I'm still not 100% sure was the right call. The initial version of the RFC had partial impl and default fn as two distinct concepts. They were merged because it seemed pretty clear that it was going to be confusing somehow, particularly if we had partial default impl, but that did imply giving up on the ability to have some things fixed and some things not. You're right that the use case you cited then becomes impossible.

  17. RalfJung commented on Apr 21, 2020

    @RalfJung
    Member

    @nikomatsakis I see. IMO that limitation should be lifted before stabilization, it's rather surprising and frustrating that what seems like a purely syntactic choice makes some interesting specialization use-cases fundamentally impossible. Having default impl have both of these effects (enable partial impl and make every item overwritable) violates orthogonality and compositionality, values that otherwise Rust considers very important.

    Could we get this listed as a concern to revisit in some tracking issue, maybe here?

  18. nikomatsakis commented on Apr 22, 2020

    @nikomatsakis
    ContributorAuthor

    @RalfJung I'd be willing to revisit this prior to stabilization, yes.

  19. nikomatsakis commented on Apr 22, 2020

    @nikomatsakis
    ContributorAuthor

    Actually, @RalfJung, it's already listed:

    • Should we have default impl (where all items are default) or partial impl (where default is opt-in)
  20. RalfJung commented on Apr 22, 2020

    @RalfJung
    Member

    Oh, I was checking the items in this issue but not the main one. oops
    Thanks for adding a pointer to this sub-discussion here. :)

  21. mankinskin commented on Dec 21, 2020

    @mankinskin

    Will it be possible to define different default impls for differently trait bounded type parameters? e.g.

    default impl<A: ToRoute> Routable for A {
        type Route = <A as ToRoute>::Route;
        fn route(&self) -> Self::Route {
            self.to_route()
        }
    }
    
    default impl<B: ToString> Routable for B {
        type Route = DefaultRoute;
        fn route(&self) -> Self::Route {
            DefaultRoute::from(self.to_string())
        }
    }

    In case of A: ToRoute and B: ToRoute + Debug, A should only match types not implementing Debug, i.e. the more specific trait bound has precedence.

  22. joergbrech commented on Dec 16, 2021

    @joergbrech

    I posted a suggestion on default impl in #31844 (comment) and just realized it would have been more appropriate here. I don't know if my suggestion makes sense at all and if it isn't too late, since this issue is already well on its way. But I would love to hear your thoughts.

  23. jplatte commented on Dec 16, 2021

    @jplatte
    Contributor
  24. joergbrech commented on Dec 16, 2021

    @joergbrech

    @jplatte, thanks for the link. Yes default groups would be much more flexible!

  25. added a commit that references this issue on Jan 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-specializationArea: Trait impl specializationA-trait-systemArea: Trait systemC-enhancementCategory: An issue proposing an enhancement or a PR with one.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.F-specialization`#![feature(specialization)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions