-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rebalancing coherence. #1023
Rebalancing coherence. #1023
Conversation
|
||
## Summary | ||
|
||
This RFC proposes two rule changes: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You list three things after this.
I don't know that I have thought through the implications enough to be strongly for or against, but I do want to point out that without higher-kinded types, it's sometimes hard to work generically over types of references. This encourages library developers to define interfaces that use mainly Question on a different topic: Should |
I like the general idea, but there are some corner cases, especially with BTW, I believe that the specifics of |
with the following meaning: | ||
|
||
- A `#[fundamental]` type `Foo` is one where implementing a blanket | ||
impl over `Foo` is a breaking change. As described, `&` and `&mut` are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly is a "blanket impl"? Does something like impl<T> SomeTrait for Foo<T, Bar> {...}
count?
cc me |
Just to answer the question that was asked a few times as to why the specific set of "fundamental" traits was chosen:
That said, I could certainly see some logic for marking all the "overload" traits ( |
I noticed in the alternative sections, you talk about specialization and bring up the problem of associated types (brilliant catch by the way). I'm curious about this paragraph (my emphasis):
My use case of specialisation, like you mention earlier in that doc, would be to provide optimised implementations, like your zip example. In that case we would certainly want associated types to match (or at least be covariant). Essentially we want it to be transparent that you're using a specialised impl and adding specialisations should not be a breaking change. I can't think of any of the "numerous trait patterns" that you mention. I'm sure you're actually right, but could you please elaborate for posterity? The specialisation solution would have made me really happy as it seems both less ad-hoc and less restrictive than the solution proposed in the RFC. |
@nikomatsakis The main reason I asked about the overloading traits is that some operators perform autoderef / autoref (to be precise, PS You still have not answered about "what is a blanket impl". |
After much discussion internally, on the internals post, this thread, and the weekly meeting, this RFC has been approved. It is unfortunate to have to move so quickly on a deep change like this, but the existing system of coherence was simply not in a shippable state without it. The design presented here manages to avoid breaking code while not making strong commitments -- the proposed attribute can be left feature-gated, and eventually replaced with an entirely different mechanism or stabilized as-is, depending on our experience. |
…pnkfelix This PR implements rust-lang/rfcs#1023. In the process it fixes rust-lang#23086 and rust-lang#23516. A few impls in libcore had to be updated, but the impact is generally pretty minimal. Most of the fallout is in the tests that probed the limits of today's coherence. I tested and we were able to build the most popular crates along with iron (modulo errors around errors being sendable). Fixes rust-lang#23918.
…dd-impls, r=pnkfelix The primary purpose of this PR is to add blanket impls for the `Fn` traits of the following (simplified) form: impl<F:Fn> Fn for &F impl<F:FnMut> FnMut for &mut F However, this wound up requiring two changes: 1. A slight hack so that `x()` where `x: &mut F` is translated to `FnMut::call_mut(&mut *x, ())` vs `FnMut::call_mut(&mut x, ())`. This is achieved by just autoderef'ing one time when calling something whose type is `&F` or `&mut F`. 2. Making the infinite recursion test in trait matching a bit more tailored. This involves adding a notion of "matching" types that looks to see if types are potentially unifiable (it's an approximation). The PR also includes various small refactorings to the inference code that are aimed at moving the unification and other code into a library (I've got that particular change in a branch, these changes just lead the way there by removing unnecessary dependencies between the compiler and the more general unification code). Note that per rust-lang/rfcs#1023, adding impls like these would be a breaking change in the future. cc @japaric cc @alexcrichton cc @aturon Fixes rust-lang#23015.
This PR implements rust-lang/rfcs#1023. In the process it fixes rust-lang#23086 and rust-lang#23516. A few impls in libcore had to be updated, but the impact is generally pretty minimal. Most of the fallout is in the tests that probed the limits of today's coherence. I tested and we were able to build the most popular crates along with iron (modulo errors around errors being sendable). Fixes rust-lang#23918.
I found some typos in the upcoming 1.1 release note. I corrected them, but I wanted to go further. So I wrote a script that checks the integrity of the Markdown references, and ran it against `RELEASES.md`. This commit fixes some trivial cases, but also removes the following "unused" references: - [`Iterator::cloned`](http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cloned) - [`thread::scoped`](http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html) - [`Debug` improvements](https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md) - [Rebalancing coherence.](rust-lang/rfcs#1023) However, I think there's a possibility that these features might need to get descriptions as well. How do you feel about it?
I found some typos in the upcoming 1.1 release note. I corrected them, but I wanted to go further. So I wrote a script that checks the integrity of the Markdown references, and ran it against `RELEASES.md`. This commit fixes some trivial cases, but also removes the following "unused" references: - [`Iterator::cloned`](http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cloned) - [`thread::scoped`](http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html) - [`Debug` improvements](https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md) - [Rebalancing coherence.](rust-lang/rfcs#1023) However, I think there's a possibility that these features might need to get descriptions as well. How do you feel about it?
I found some typos in the upcoming 1.1 release note. I corrected them, but I wanted to go further. So I wrote a script that checks the integrity of the Markdown references, and ran it against `RELEASES.md`. This commit fixes some trivial cases, but also removes the following "unused" references: - [`Iterator::cloned`](http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cloned) - [`thread::scoped`](http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html) - [`Debug` improvements](https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md) - [Rebalancing coherence.](rust-lang/rfcs#1023) However, I think there's a possibility that these features might need to get descriptions as well. How do you feel about it?
RFC rust-lang#1023 introduced rules that exclude impls which should clearly be valid. It also used some ambiguous language around what is a breaking change, that ended up being completely ignored and contradicted by rust-lang#1105. This RFC seeks to clarify what is or isn't a breaking change when it comes to implementing an existing trait, and conservatively expands the orphan rules to allow impls which do not violate coherence, and fit within the original goals of rust-lang#1023. [Rendered]
RFC rust-lang#1023 introduced rules that exclude impls which should clearly be valid. It also used some ambiguous language around what is a breaking change, that ended up being completely ignored and contradicted by rust-lang#1105. This RFC seeks to clarify what is or isn't a breaking change when it comes to implementing an existing trait, and conservatively expands the orphan rules to allow impls which do not violate coherence, and fit within the original goals of rust-lang#1023.
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.
This RFC is 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).
Some prior discussion is on this internals thread, although it's mostly me talking to myself.
Rendered view
[edited to link to final rendered version]