[Idea] Explicitly imported orphan impls


#1

I’ve been thinking a bit on the troubles with orphan impls. There were multiple ideas on how to make them work automagically. But why don’t we simply allow them to be normal module members, with ability to use or not use in certain scope?

  • Unlike current situation, allow trait impl to be declared anywhere
  • Trait impl gets into action only if either:
    • It’s explicitly imported into scope via something like use othercrate::impl Ord;
    • It resides in the same crate as either trait or type

As a possible modification, we may make current impl rules a bit more consistent (albeit, it requires to carefully check current codebase so that nothing would break):

  • Do not make arbitrarily located impl visible, even if it’s located in the same crate as its trait or target (that’s the breaking change)
  • But make impls “stick” to their trait or target, if they’re in the same module. Such “sticky” impl is implicitly visible when the thing it sticks to is used.

This should keep everything nicely coherent - and leave room for manual resolution.

Thoughts?


#2

It’s been proposed a few times:


#3

Okay, I suspected it to be too simple and obvious to be overlooked by core team.


#4

Maybe someone knows how Golang handles such coherence? They basically have duck-typed interfaces, based on functions currently in scope. So this could be as well issue for them too. Couldn’t google out anything reasonable.


#5

Looks like you can’t extend the behavior of existing types in Go: https://stackoverflow.com/questions/28800672/how-to-add-new-methods-to-an-existing-type-in-go

They have an “alias” functionality which acts like our newtype pattern.


#6

So they have something similar to Rust orphan rules I guess.