7

I just came across the problem of implementing a trait I do not own for a type I do not own. Then I googled the exact How do I implement a trait I don't own for a type I don't own? question.

The thing that confused me is the motivation behind such restriction. I came from Scala where it is possible to have an external typeclass instance for an external type.

Why does Rust restrict that?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Some Name
  • 8,555
  • 5
  • 27
  • 77
  • 6
    Opinion based, but suppose an occasion when crate A and crate B both make implementations of a trait `C::foo` for type `D::Bar`, which to choose? – Alexey S. Larionov Jul 25 '20 at 20:51
  • @AlexLarionov Makes sense. – Some Name Jul 25 '20 at 21:25
  • See also [Why is implementing an external trait using my type as a parameter for an external type legal?](https://stackoverflow.com/q/51236531/155423); [Is there a way for me to use #\[derive\] on a struct or enum from a library without editing the actual library's source code?](https://stackoverflow.com/q/48267016/155423) – Shepmaster Jul 29 '20 at 13:01
  • As far as I remember, some people involved in the design of Rust have a really bad experience with this from Haskell. In Haskell you can define existing typeclasses for existing types and some packages do it and it leads to difficult to understand bugs and errors. – Jan Hudec Jul 29 '20 at 13:55
  • @AlexeyLarionov What about impl traits for generics over types defined in your own crate? – Matias Pequeno Apr 01 '23 at 16:13

3 Answers3

2

As Alexey Larionov explains in the comments, if two crates could implement a trait for the same struct there would be a conflict of which trait implementation to use. With this restriction, Rust guarantees that every (struct, trait) pair will have at most one implementation across all crates.

If you find yourself needing to implement an external trait for an external struct you can leverage the Rust New Type Idiom.

By wrapping an external struct in a new type you are able implement any external trait on that new type.

While the new type won't be the same as the external struct, you can reference that wrapped type with the .0 syntax, as explained in the New Type Idiom documentation.

chris
  • 371
  • 3
  • 10
  • > if two crates could implement a trait for the same struct there would be a conflict of which trait implementation to use. Well, it would make perfect sense to "import the extension trait" in the scope of the file à la c# – Alexandre Daubricourt Jun 14 '23 at 06:27
1

I just read the Rust Book's chapter about implementing traits and, as @AlexLarionov suggested in the comment that it would be impossible to choose an appropriate implementation:

But we can’t implement external traits on external types. For example, we can’t implement the Display trait on Vec<T> within our aggregator crate, because Display and Vec<T> are defined in the standard library and aren’t local to our aggregator crate. This restriction is part of a property of programs called coherence, and more specifically the orphan rule, so named because the parent type is not present. This rule ensures that other people’s code can’t break your code and vice versa. Without the rule, two crates could implement the same trait for the same type, and Rust wouldn’t know which implementation to use.

Some Name
  • 8,555
  • 5
  • 27
  • 77
1

Unlike others have said, though it is currently impossible, I'm not going to agree that it is a good limitation, to my view.

If crate A and crate B impl crate C::struct with whatever::external_trait

Then within their own respective scope, A and B could use their own impl of external_trait.

A feature that looks like this might one day be available.

See Crates should allow private impl of external traits for external structs #493 to follow the progress.

Alexandre Daubricourt
  • 3,323
  • 1
  • 34
  • 33