rust-lang/rust — pull request #18467 by japaric (2014-10-30 22:34:24+00:00)
Title: [WIP] DSTify PartialEq, PartialOrd, Eq, Ord

`eq`, `ne`, `cmp`, etc methods now require one less level of indirection when dealing with `&str`/`&[T]`

``` rust
"foo".ne(&"bar") -> "foo".ne("bar")
slice.cmp(&another_slice) -> slice.cmp(another_slice)
// slice and another_slice have type `&[T]`
```

[breaking-change]

---

The current expansion of `#[deriving(PartialEq)]` doesn't work on structs that contain `&str`/`&[T]`. I'll show why this is the case with an example:

Consider the expansion of `#[deriving(PartialEq)]` for `struct Foo(&'static str)`:

``` rust
impl ::std::cmp::PartialEq for Foo {
#[inline]
fn eq(&self, __arg_0: &Foo) -> ::bool {
match *__arg_0 {
Foo(ref __self_1_0) =>
match *self {
Foo(ref __self_0_0) =>
true && (*__self_0_0).eq(&(*__self_1_0)),
},
}
}
// ne method omitted for brevity
}
```

When compiling, the compiler errors with:

``` rust
error: mismatched types: expected &str, found &&'static str (expected str, found &-ptr)
```

and points to `(*__self_0_0).eq(&(*__self_1_0))` . The cause of the error is that:

- Both `__self_0_0`/`__self_1_0` have type `&&str`
- `(*__self_0_0).eq(&(*__self_1_0))` has type `(*&&str).eq(&(*&&str))`, or equivalently `(&str).eq(&&str)`
- The compiler uses `Self = str` as the receiver for the `eq` method call
- Since `eq` has signature `eq(&self, &Self)`, it expects the argument to have type `&str`
- The compiler errors because it expects `&str`, but finds `&&str` in the argument

To dealt with this issue, I've changed the expansion of `eq`/`ne` to use the operator sugar in the return expression. In the above example, the return expression changes to `true && (*__self_0_0) == (*__self_1_0)`. Note that the expansion of `#[deriving(PartialOrd)]` also uses the operator sugar instead of the operator methods, so in a way this change makes our expansions consistent.

Since the new `deriving` expansion is not available until `stage1`, all the DST changes have been properly `cfg(stage0)`ed.

This PR passes `make`, but fails to `make check` because the operator sugar doesn't seem to work with fixed-size arrays anymore, for example: `[0, 1] == [0, 1]` errors with:

``` rust
mismatched types: expected `[]`, found `[, ..2]` (expected unsized array, found array)
```

@nikomatsakis happens to be working on the operator dispatch as part of #4920, and [is aware of this issue](https://github.com/rust-lang/rust/issues/16918#issuecomment-61152129). Hopefully, his upcoming PR will solve this issue.

This PR is up for early review, but can't be merged until `[0, 1] == [0, 1]` is working again.

@alexcrichton Could you provide feedback on the use of `cfg(stage0)`/`NOTE(stage0)`s?
r? @aturon
cc #16918