I recently realized that our current trait system contains a forward compatibility hazard concerned with negative reasoning. The TL;DR is that negative reasoning (that is, the compiler saying that “doing X is legal if the trait T is NOT implemented for some type U”) can easily make it impossible to add impls of any traits in a backwards compatible way. The most obvious example of negative reasoning are negative trait bounds, which have been proposed in a rather nicely written RFC. However, even without negative bounds, the trait system as currently implemented already has some amount of negative reasoning, in the form of the coherence system.
I’ve come up with a fairly simple proposal that tries to strike a good balance between parent and child crates, in terms of permitting parent crates to expand but also giving child crates lots of freedom to define the impls they need. However, it does involve tightening coherence so it is somewhat more restrictive (the current rules are designed to permit as much as possible in the child crates; but this winds up limiting the parent crates).
In the process of developing this proposal, I also went through many iterations and wrote up a lot of background material. Therefore, I’ve embedded all of that into a gist with multiple sections:
- The problem: explains why negative reasoning is dangerous.
- A simple fix: a simple proposal that we can use to avoid the problem. This solution is somewhat limiting and we may wish to evolve it to more comprehensive solutions in the longer term.
- Alternatives: other avenues that I explored and which may be the kernel of a more permissive solution.
I plan on opening an RFC regarding the simple solution shortly, but I wanted to post this out first.