Slight relaxation of the orphan rules

The orphan rules currently forbid trait impls of this form:

impl<T: LocalTrait> ForeignTrait for T { /* ... */ }

But, we could allow it without risking incoherence as long as the crate only implements LocalTrait for local types.

It would have the same pitfalls as a blanket impl impl<T> LocalTrait for T, of course, meaning that such an impl can't be added except in the version that introduces LocalTrait, but this does seem reasonably useful.

On the other hand, though, Rust generally prefers to avoid reasoning about involved impl disjointness, as that can easily introduce errors at a distance.

A different idea that I had previously is to introduce #[fundamental] trait, with the logical semantics being that adding impls of the trait is considered a breaking change just like removing an impl is. This means that a blanket impl over a fundamental trait can be treated for the purpose of coherence to be identical to an impl using each impl block for the fundamental trait. (Well, at least if it's also sealed; I haven't fully considered what coherence reasoning needs to look like when downstream crates can impl the fundamental trait for their types.)

1 Like

That already exists (unstably); Sized and the Fn traits are fundamental, and coherence takes that into account.

3 Likes

To go well this would also need to keep LocalTrait from having blanket impls from OtherForeignTrait and to keep other foreign crates from implementing LocalTrait on their own types, so I think it needs something on the trait too in order to allowed.

IIRC the #[sealed] trait discussions talked about potentially doing something like this.

1 Like

No, it should not prevent this. Downstream crates should be able to implement LocalTrait for their own types, as long as they don’t also provide a conflicting ForeignTrait impl. (As @CAD97 said, the impl<T: LocalTrait> ForeignTrait for T would be a breaking change to add except in the version that introduces LocalTrait, but that’s fine.)

There doesn't seem to be a tracking issue for stabilising fundamental. The linked issue from there is a closed issue about the problem, not the tracking issue.

Is it intended to be perma-unstable for some reason? If so why (I could see custom smart pointers wanting to opt in)?

2 Likes

This tracking issue exists, but I don't know the answers to your questions.

1 Like