Ixrec / rust-orphan-rules

An unofficial, experimental place for documenting and gathering feedback on the design problems around Rust's orphan rules

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Prior Art

Ixrec opened this issue · comments

commented

C++/Java/C#: The closest analogue to traits is interfaces and/or abstract base classes, which must be part of a type's definition, so there's simply no such thing as "orphan impls".

Haskell: Orphan impls are allowed, and you simply get an error if you ever import incoherent impls. GHC does have an IncoherentInstances language extension that permits GHC to do magic to select an impl for you, but no one should ever use that.


Obviously, this is very incomplete. Please comment if you're familiar with how any other language handles these problems

commented

One additional note regarding Java: version 8+ introduced default implementations for interfaces, which brought them a bit closer to Rust traits. If a class implements two interfaces which both have default implementations for the same method signature, the class must explicitly implement that method (and while doing so may choose to call one of the default methods to take care of the work).

In Go, interfaces are automatically implemented if the struct has matching method signatures. But you're not allowed to add methods to externally defined types, only to local ones, so a common workaround is to wrap the struct. This is roughly equivalent to the recommended workaround in Rust. Also the way interfaces are automatically implemented is practically identical to dynamically typed programming languages like Python or JavaScript.

The situation in Typescript is a bit more complicated. It uses the same syntax as C++/C#, which is interface implementation is part of a type's definition, but it also supports module augmentation, which allows one to change an externally defined type (in this case to implement an interface). However, it still checks interface implementations like Go does (which is by method signature), and so the end result is that it simply doesn't matter.

commented

Swift: At the time of writing, Swift is trying to add warning for the orphan implementation, or "retroactive conformance" in Swift parlance.

SE-0364 Warning for Retroactive Conformances of External Types

The academic programming language Genus has a very expressive solution to this problem, allowing the programmer to specify which implementation of the trait they want to use:

https://www.cs.cornell.edu/andru/papers/genus/