Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRemove the remaining uses of `old_orphan_rules` #19470
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@arielb1 that is definitely a hole! Nominating. Interesting, have to think a bit about what the best way is to patch the rules for this case. |
nikomatsakis
added
the
I-nominated
label
Dec 2, 2014
This comment has been minimized.
This comment has been minimized.
|
By the way, the ambiguity can also occur between the receiver and one of the trait's type parameters: base.rs: pub trait Base<T> { /* ... */}foo.rs: extern crate base;
pub struct Foo;
impl<T> base::Base<Foo> for T {}bar.rs: extern crate base;
pub struct Bar;
impl base::Base<T> for Bar {}With |
This comment has been minimized.
This comment has been minimized.
|
Some relevant comments from @arielb1 on IRC: https://botbot.me/mozilla/rust-internals/2014-12-03/?msg=26759795&page=7 |
This comment has been minimized.
This comment has been minimized.
|
I thought this through. I am mildly uncomfortable with @arielb1's proposed rules in that I do not expect the ordering of type parameters to be significant (which is not to say that those rules would not solve the problem). @aturon and I worked through some examples and we felt like these rules captured our intution reasonably well:
This can be summarized as "type parameters can only appear as parameters of a local type/trait". This seems to cover the various cases I can think of. I have not tried to prove it sound but I believe it is. Of course I thought that before. :) Once I've had some more coffee, I might take a crack at that, seems like it should be a simple inductive exercise. |
This comment has been minimized.
This comment has been minimized.
|
The version you wrote is broken: // Crate a:
struct A;
impl<T> Base for Pair<Option<T>, Option<A>> {}
// Crate b:
struct B;
impl<T> Base for Pair<Option<B>, Option<T>> {}Which follows the rules, as A working variant is my second version of the rule: let ≺ be the partial order on nodes in a trait-ref generated by Trait ≺ Self ≺ Tᵢ in the trait-ref 〈Trait〈Tᵢ〉 for Self〉, Type ≺ Tᵢ in a type Type〈Tᵢ〉, then for every type parameter node Q in the trait-ref there exists a local node L such that L ≺ Q. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 that does not follow the rules because of their recursion nature. Note that the |
This comment has been minimized.
This comment has been minimized.
|
(Not to say the rules are perfect, as I said, I have to go back through the list of examples I had and make sure they accept/reject correctly, I'm a bit nervous about the |
This comment has been minimized.
This comment has been minimized.
|
(Or maybe that's the point, perhaps you are correct and I haven't quite formulated the rules the way I wanted them) |
This comment has been minimized.
This comment has been minimized.
|
By the way, the partial-order rules in sequent form:
|
This comment has been minimized.
This comment has been minimized.
|
I created btw a repository for experimenting with rules and their effects on various scenarios: |
brson
added this to the 1.0 milestone
Dec 11, 2014
brson
added
the
P-backcompat-lang
label
Dec 11, 2014
This comment has been minimized.
This comment has been minimized.
|
1.0 P-backcompat-lang |
brson
removed
the
I-nominated
label
Dec 11, 2014
This comment has been minimized.
This comment has been minimized.
|
The repository now contains an encoding of the rules that I think more accurately captures what I was going for, and has the side benefit of being (afaik) sound. An impl of some trait
A type
A type
If you find that textual definition confusing, see the code. In any case, I think this is a subset of @arielb1's definition (as expected). The reason is that @arielb1's requirement was that, when iterating @arielb1 let me know what you think! |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 points out that this rule prohibits Note in particular that if we permit
then there is a potential coherence conflict for However, it may be that we can avoid ordering dependency by permitting "uncovered" type parameters as long as they are covered somewhere. I have to try and prove this. |
This comment has been minimized.
This comment has been minimized.
|
An argument in favor of the "must be covered somewhere" is that I think you can always reduce it to an ordered set (pre-order) by reordering the parameters in a given trait/type. |
This comment has been minimized.
This comment has been minimized.
|
Never mind, that is truly for one impl. Still, I think the rule is sound, though I haven't written up a full proof (of course, I thought the original was sound too). The intuition is that you will ultimately require a cyclic type to violate it. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 writes a proposed proof of the "all type parameters must be covered" rule in IRC here: https://botbot.me/mozilla/rust-internals/2014-12-12/?msg=27397345&page=5 I haven't read it deeply enough to comment yet. |
This comment has been minimized.
This comment has been minimized.
|
Prettier Proof: Substitution - written as Ty[{Tₖ←Sₖ|k}], substitutes the an impl is treated as defid-of(Type) = def-id of the root (e.g. Type/TraitRef contains-defid DefId : lexical containment Type/TraitRef contains-type Type : structural containment Q contains-type Ty is true when there exists a P that These 3 overloaded relations will be labeled as Lemmas I'm using: Substitution: Combinatorics: Main Theorem: And, for all i, if Tᵢ⪯R₁, then there exists a Then for no i and j, Tᵢ⪯Rⱼ (neither trait-ref contains Proof: Let i be such that Tᵢ⪯R₁. There exists a Ty such Let G be the graph of the partial order ≺ restricted to Q.E.D. |
This comment has been minimized.
This comment has been minimized.
|
I implemented this check. Interestingly, like so many things I have in progress, it seems to be somewhat blocked on associated types, in that the
For now I plan to land the new check with a (deprecated) feature-gate that disables it, so that old code can continue to work until everything else is in place. |
This comment has been minimized.
This comment has been minimized.
|
This is the actual example where I encountered a problem: impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> |
This comment has been minimized.
This comment has been minimized.
|
Another interesting example that fails (from libgraphviz): impl<'a, T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for MaybeOwnedVector<'a, T>This seems to be a pattern that is just inexpressible? (That is, relating a local type to any type that implements some trait). |
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 26, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 26, 2014
This comment has been minimized.
This comment has been minimized.
|
These do work with the "privileged self" variant of the order-based rules. Maybe we can find a mix of the covering-based and ordering-based rules that supports this? |
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 29, 2014
brson
modified the milestones:
1.0 beta,
1.0
Jan 15, 2015
alexcrichton
removed
the
I-nominated
label
Jan 15, 2015
nikomatsakis
referenced this issue
Jan 31, 2015
Merged
Update the coherence rules to "covered first" #21792
nikomatsakis
changed the title
Orphan checking isn't strict enough with multidispatch
Remove the remaining uses of `old_orphan_rules`
Jan 31, 2015
This comment has been minimized.
This comment has been minimized.
|
I updated the issue to better highlight what remains to be done, and made a checklist of traits that are still using |
bors
added a commit
that referenced
this issue
Feb 1, 2015
pnkfelix
assigned
aturon
Feb 12, 2015
This comment has been minimized.
This comment has been minimized.
|
Nominating to move to P-backcompat-libs. This will largely go away with the stabilization of |
aturon
added
the
I-nominated
label
Feb 16, 2015
This comment has been minimized.
This comment has been minimized.
|
P-backcompat-libs, 1.0 beta. |
arielb1 commentedDec 2, 2014
UPDATED ISSUE:
The original issue that was reported by @arielb1 has largely been resolved. However, there remain some traits that were added before the new rules were completed, and which do not conform. Those traits are currently distinguished with
old_orphan_checkmarkers. The remaining work is to fix these traits:BorrowFromBorrowFromMutIntoCowToOwnedPartialEq- @nikomatsakis
ORIGINAL ISSUE:
The current version of orphan checking does not prevent me from break coherence if impls from different crates are non-orphan because of different type parameters of the same type, for example:
base.rs:
foo.rs:
bar.rs:
foobar.rs:
Which of course ICE-s with a trans ambiguity.