-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Default impls cannot reliably expose type inequality #29499
Comments
I think that being able to express type inequality at all is just a side-effect. Default impls like that aren't stable and the semantics aren't concrete right now. @rust-lang/lang might have some input? |
It looks like this just interacts badly with type inference. |
If it would compile, type inequality gives you ad-hoc specialization (code example). The specialization passes trait coherence checks, and both can be called, but indeed it does not infer to the right implementation in a regular method call. Edit: Oh wow, making the iterator the Self type instead, the “dream specialization” for extend works. |
I believe that the fact that that impl is accepted is a known bug. (In particular, the first point of #13231.) |
I agree with Aatch, this is a side effect. I do wish we had a way of expressing type inequality, but this isn't the way to go about it. |
Additionally, this lead to an ICE when I tried to take it to the next step: tuples where every type is different. #![feature(optin_builtin_traits)]
trait NotSame {}
impl NotSame for .. {}
impl<A> !NotSame for (A, A) {}
trait OneOfEach {}
impl <A> OneOfEach for (A) { }
impl <A, B> OneOfEach for (A, B) where (B): OneOfEach, (A, B): NotSame { }
impl <A, B, C> OneOfEach for (A, B, C) where (B, C): OneOfEach, (A, B): NotSame,
(A, C): NotSame {}
fn main() {}
On rustc 1.6.0-nightly (1a2eaff 2015-10-31) |
File a separate bug? |
Will default impls will be expressive enough if they aren't capable of expressing type inequality in this way? It seemed like a no-brainer when I wrote it. Obviously the language should support it with native syntax as well-- sooner rather than later, to avoid hacks like this from becoming commonplace. |
I don't think that this impl:
is intended to work. I thought we had some restrictions to this effect, but perhaps we only placed them on positive impls. This is in a sense a kind of coherence violation -- there is a default, builtin impl for tuples that this interacts with. But in general the expressive power of negative impls is not firmly settled and will be changing. It's something that we need to make firmer decisions on (and there is also clear interaction with ongoing design, such as specialization, rust-lang/rfcs#1148, and catch panic). |
Did you mean |
You don't exactly have specialization, because you can't have a generic method use extend. Anyway, OIBITs were basically intended as "structural impls with negative impls for opt-out". |
@Ms2ger As I addressed in the separate issue, I am aware that (A) is not correct, strictly speaking. When you compile it with the trailing comma, it works (mostly) as expected. The important point is that the ICE occurs at all. |
Triage: no discussion on this bug in almost four years! The code is slightly different now: #![feature(optin_builtin_traits)]
auto trait NotSame { }
impl<A> !NotSame for (A, A) { }
fn f<T, U>(_: T, _: U) where (T, U): NotSame {}
struct S;
struct Z;
fn main() {
f(S, Z); // error: the trait `NotSame` is not implemented for the type `(_, _)`
f(S, S); // error: the trait `NotSame` is not implemented for the type `(_, _)`
} The errors are spiritually similar, though different:
My understanding is that auto traits won't be stable any time soon, if ever. I'm not sure, but I think we should close this. |
Yes, I think this is correctly returning an error / we somewhat expect this to not work, indeed "type inequality" is generally something that I believe we try to make impossible to represent with traits today, so I agree that we can close this. |
Note that this works, if you'll specify the types explicitly (but not for lifetimes, idk why is that): fn main() {
f::<S, Z>(S, Z); // ok
f::<S, S>(S, S); // error[E0277]: the trait bound `(S, S): NotSame` is not satisfied
}
fn a<'a>() {
f::<&'a (), &'static ()>(&(), &()); // error[E0277]: the trait bound `(&'a (), &'static ()): NotSame` is not satisfied
}
@Mark-Simulacrum why we are trying to avoid that? What kind of problems can bring "type inequality"? |
The type inequality magic was forbidden by core conclave of magicians, see [1] and [2] for more. This commit removes everything that depends on type inequality including: `Exclude`, `Uniq` (that's all actually) [1]: rust-lang/rust#29499 (comment) [2]: rust-lang/rust#13231 (comment)
If I understand default impls right, it should be possible to express
S != T
using(S, T): NotSame
. In fact this does work in some situations, but not generally.doesn't work:
but this does:
Perhaps it only works when trying to ensure there are no conflicting impls? Perhaps it's not meant to work, and the second example is a hole?
The text was updated successfully, but these errors were encountered: