Can I impl ForeignTrait for ForeignType<LocalType>?

Hello, hello!

trait Foo { /* ... */ }
struct Bar<T> { /* ... */ }

struct Baz;
impl Foo for Bar<Baz> { /* ... */ }

If Foo and Bar<T> are local, I can compile the above snippet. But if there aren't, the compiler is complaining that "only traits defined in the current crate can be implemented for arbitrary types". It feels weird because Bar<Baz> should be considered a local type since Baz is local, shouldn't it? Am I missing something?

If one of the upstream crates added impl<T> Foo for Bar<T>, this would conflict with your impl. The rules are designed to allow libraries to add impls without breaking downstream crates.

2 Likes

Ah :frowning: So it would be possible only if rfcs/1210-impl-specialization.md at master · rust-lang/rfcs · GitHub is accepted? I was hoping it what I wanted to do didn't need specialization, but it look like I'm wrong.

The usual way to do this is to wrap the foreign type in a local type (usually a struct), on which you can then define whatever traits you want since, by making the type of the impl local, you avoid Rust's "orphan rule". There are probably hundreds of examples of this technique on crates.io.

The newtype is a widely used hack in Rust but it doesn't always work. In my case I was using the typestate pattern (more specifically the last variation in the arcticle) which explicitely test if Bar<T> implements Foo.

Given that I am written both the library and the user code, I will just move the user code into the library (so Foo and Bar<T> are no longer foreign types), but it means that client that don't have write access to my library will not be able to re-use it for their custom types.

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.