Skip to content

Commit 63c4f22

Browse files
committed
auto merge of #18486 : nikomatsakis/rust/operator-dispatch, r=pcwalton
This branch cleans up overloaded operator resolution so that it is strictly based on the traits in `ops`, rather than going through the normal method lookup mechanism. It also adds full support for autoderef to overloaded index (whereas before autoderef only worked for non-overloaded index) as well as for the slicing operators. This is a [breaking-change]: in the past, we were accepting combinations of operands that were not intended to be accepted. For example, it was possible to compare a fixed-length array and a slice, or apply the `!` operator to a `&int`. See the first two commits in this pull-request for examples. One downside of this change is that comparing fixed-length arrays doesn't always work as smoothly as it did before. Before this, comparisons sometimes worked due to various coercions to slices. I've added impls for `Eq`, `Ord`, etc for fixed-lengths arrays up to and including length 32, but if the array is longer than that you'll need to either newtype the array or convert to slices. Note that this plays better with deriving in any case than the previous scheme. Fixes #4920. Fixes #16821. Fixes #15757. cc @alexcrichton cc @aturon
2 parents 5c1fd5f + 81c00e6 commit 63c4f22

31 files changed

+1009
-263
lines changed

src/doc/guide.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -4601,20 +4601,24 @@ returns `true` or `false`. The new iterator `filter()` produces
46014601
only the elements that that closure returns `true` for:
46024602

46034603
```{rust}
4604-
for i in range(1i, 100i).filter(|x| x % 2 == 0) {
4604+
for i in range(1i, 100i).filter(|&x| x % 2 == 0) {
46054605
println!("{}", i);
46064606
}
46074607
```
46084608

46094609
This will print all of the even numbers between one and a hundred.
4610+
(Note that because `filter` doesn't consume the elements that are
4611+
being iterated over, it is passed a reference to each element, and
4612+
thus the filter predicate uses the `&x` pattern to extract the integer
4613+
itself.)
46104614

46114615
You can chain all three things together: start with an iterator, adapt it
46124616
a few times, and then consume the result. Check it out:
46134617

46144618
```{rust}
46154619
range(1i, 1000i)
4616-
.filter(|x| x % 2 == 0)
4617-
.filter(|x| x % 3 == 0)
4620+
.filter(|&x| x % 2 == 0)
4621+
.filter(|&x| x % 3 == 0)
46184622
.take(5)
46194623
.collect::<Vec<int>>();
46204624
```

src/libarena/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl Drop for Arena {
132132

133133
#[inline]
134134
fn round_up(base: uint, align: uint) -> uint {
135-
(base.checked_add(&(align - 1))).unwrap() & !(&(align - 1))
135+
(base.checked_add(&(align - 1))).unwrap() & !(align - 1)
136136
}
137137

138138
// Walk down a chunk, running the destructors for any objects stored

src/libcollections/slice.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1598,15 +1598,15 @@ mod tests {
15981598
#[test]
15991599
fn test_total_ord() {
16001600
let c: &[int] = &[1, 2, 3];
1601-
[1, 2, 3, 4].cmp(& c) == Greater;
1601+
[1, 2, 3, 4][].cmp(& c) == Greater;
16021602
let c: &[int] = &[1, 2, 3, 4];
1603-
[1, 2, 3].cmp(& c) == Less;
1603+
[1, 2, 3][].cmp(& c) == Less;
16041604
let c: &[int] = &[1, 2, 3, 6];
1605-
[1, 2, 3, 4].cmp(& c) == Equal;
1605+
[1, 2, 3, 4][].cmp(& c) == Equal;
16061606
let c: &[int] = &[1, 2, 3, 4, 5, 6];
1607-
[1, 2, 3, 4, 5, 5, 5, 5].cmp(& c) == Less;
1607+
[1, 2, 3, 4, 5, 5, 5, 5][].cmp(& c) == Less;
16081608
let c: &[int] = &[1, 2, 3, 4];
1609-
[2, 2].cmp(& c) == Greater;
1609+
[2, 2][].cmp(& c) == Greater;
16101610
}
16111611

16121612
#[test]
@@ -1980,15 +1980,15 @@ mod tests {
19801980
let (left, right) = values.split_at_mut(2);
19811981
{
19821982
let left: &[_] = left;
1983-
assert!(left[0..left.len()] == [1, 2]);
1983+
assert!(left[0..left.len()] == [1, 2][]);
19841984
}
19851985
for p in left.iter_mut() {
19861986
*p += 1;
19871987
}
19881988

19891989
{
19901990
let right: &[_] = right;
1991-
assert!(right[0..right.len()] == [3, 4, 5]);
1991+
assert!(right[0..right.len()] == [3, 4, 5][]);
19921992
}
19931993
for p in right.iter_mut() {
19941994
*p += 2;

src/libcollections/vec.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ impl<T> Vec<T> {
919919
///
920920
/// ```
921921
/// let mut vec = vec![1i, 2, 3, 4];
922-
/// vec.retain(|x| x%2 == 0);
922+
/// vec.retain(|&x| x%2 == 0);
923923
/// assert_eq!(vec, vec![2, 4]);
924924
/// ```
925925
#[unstable = "the closure argument may become an unboxed closure"]
@@ -1800,15 +1800,15 @@ mod tests {
18001800
let (left, right) = values.split_at_mut(2);
18011801
{
18021802
let left: &[_] = left;
1803-
assert!(left[0..left.len()] == [1, 2]);
1803+
assert!(left[0..left.len()] == [1, 2][]);
18041804
}
18051805
for p in left.iter_mut() {
18061806
*p += 1;
18071807
}
18081808

18091809
{
18101810
let right: &[_] = right;
1811-
assert!(right[0..right.len()] == [3, 4, 5]);
1811+
assert!(right[0..right.len()] == [3, 4, 5][]);
18121812
}
18131813
for p in right.iter_mut() {
18141814
*p += 2;
@@ -1863,7 +1863,7 @@ mod tests {
18631863
#[test]
18641864
fn test_retain() {
18651865
let mut vec = vec![1u, 2, 3, 4];
1866-
vec.retain(|x| x%2 == 0);
1866+
vec.retain(|&x| x % 2 == 0);
18671867
assert!(vec == vec![2u, 4]);
18681868
}
18691869

src/libcore/array.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
/*!
12+
* Implementations of things like `Eq` for fixed-length arrays
13+
* up to a certain length. Eventually we should able to generalize
14+
* to all lengths.
15+
*/
16+
17+
#![stable]
18+
#![experimental] // not yet reviewed
19+
20+
use cmp::*;
21+
use option::{Option};
22+
23+
// macro for implementing n-ary tuple functions and operations
24+
macro_rules! array_impls {
25+
($($N:expr)+) => {
26+
$(
27+
#[unstable = "waiting for PartialEq to stabilize"]
28+
impl<T:PartialEq> PartialEq for [T, ..$N] {
29+
#[inline]
30+
fn eq(&self, other: &[T, ..$N]) -> bool {
31+
self[] == other[]
32+
}
33+
#[inline]
34+
fn ne(&self, other: &[T, ..$N]) -> bool {
35+
self[] != other[]
36+
}
37+
}
38+
39+
#[unstable = "waiting for Eq to stabilize"]
40+
impl<T:Eq> Eq for [T, ..$N] { }
41+
42+
#[unstable = "waiting for PartialOrd to stabilize"]
43+
impl<T:PartialOrd> PartialOrd for [T, ..$N] {
44+
#[inline]
45+
fn partial_cmp(&self, other: &[T, ..$N]) -> Option<Ordering> {
46+
PartialOrd::partial_cmp(&self[], &other[])
47+
}
48+
#[inline]
49+
fn lt(&self, other: &[T, ..$N]) -> bool {
50+
PartialOrd::lt(&self[], &other[])
51+
}
52+
#[inline]
53+
fn le(&self, other: &[T, ..$N]) -> bool {
54+
PartialOrd::le(&self[], &other[])
55+
}
56+
#[inline]
57+
fn ge(&self, other: &[T, ..$N]) -> bool {
58+
PartialOrd::ge(&self[], &other[])
59+
}
60+
#[inline]
61+
fn gt(&self, other: &[T, ..$N]) -> bool {
62+
PartialOrd::gt(&self[], &other[])
63+
}
64+
}
65+
66+
#[unstable = "waiting for Ord to stabilize"]
67+
impl<T:Ord> Ord for [T, ..$N] {
68+
#[inline]
69+
fn cmp(&self, other: &[T, ..$N]) -> Ordering {
70+
Ord::cmp(&self[], &other[])
71+
}
72+
}
73+
)+
74+
}
75+
}
76+
77+
array_impls! {
78+
0 1 2 3 4 5 6 7 8 9
79+
10 11 12 13 14 15 16 17 18 19
80+
20 21 22 23 24 25 26 27 28 29
81+
30 31 32
82+
}
83+

src/libcore/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ pub mod tuple;
126126
pub mod unit;
127127
pub mod fmt;
128128

129+
// note: does not need to be public
130+
#[cfg(not(stage0))]
131+
mod array;
132+
129133
#[doc(hidden)]
130134
mod core {
131135
pub use panicking;

src/libcore/option.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,8 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
787787
/// use std::uint;
788788
///
789789
/// let v = vec!(1u, 2u);
790-
/// let res: Option<Vec<uint>> = v.iter().map(|x: &uint|
791-
/// if *x == uint::MAX { None }
790+
/// let res: Option<Vec<uint>> = v.iter().map(|&x: &uint|
791+
/// if x == uint::MAX { None }
792792
/// else { Some(x + 1) }
793793
/// ).collect();
794794
/// assert!(res == Some(vec!(2u, 3u)));

src/libcore/result.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,8 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
894894
/// use std::uint;
895895
///
896896
/// let v = vec!(1u, 2u);
897-
/// let res: Result<Vec<uint>, &'static str> = v.iter().map(|x: &uint|
898-
/// if *x == uint::MAX { Err("Overflow!") }
897+
/// let res: Result<Vec<uint>, &'static str> = v.iter().map(|&x: &uint|
898+
/// if x == uint::MAX { Err("Overflow!") }
899899
/// else { Ok(x + 1) }
900900
/// ).collect();
901901
/// assert!(res == Ok(vec!(2u, 3u)));

src/libcoretest/iter.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ fn test_iterator_size_hint() {
356356
assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
357357
assert_eq!(vi.scan(0i, |_,_| Some(0i)).size_hint(), (0, Some(10)));
358358
assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
359-
assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10)));
359+
assert_eq!(vi.map(|&i| i+1).size_hint(), (10, Some(10)));
360360
assert_eq!(vi.filter_map(|_| Some(0i)).size_hint(), (0, Some(10)));
361361
}
362362

@@ -388,9 +388,9 @@ fn test_any() {
388388
#[test]
389389
fn test_find() {
390390
let v: &[int] = &[1i, 3, 9, 27, 103, 14, 11];
391-
assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14);
392-
assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3);
393-
assert!(v.iter().find(|x| *x % 12 == 0).is_none());
391+
assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14);
392+
assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3);
393+
assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
394394
}
395395

396396
#[test]

src/librustc/middle/ty.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -1167,25 +1167,25 @@ impl cmp::PartialEq for InferRegion {
11671167

11681168
impl fmt::Show for TyVid {
11691169
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
1170-
write!(f, "<generic #{}>", self.index)
1170+
write!(f, "_#{}t", self.index)
11711171
}
11721172
}
11731173

11741174
impl fmt::Show for IntVid {
11751175
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1176-
write!(f, "<generic integer #{}>", self.index)
1176+
write!(f, "_#{}i", self.index)
11771177
}
11781178
}
11791179

11801180
impl fmt::Show for FloatVid {
11811181
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1182-
write!(f, "<generic float #{}>", self.index)
1182+
write!(f, "_#{}f", self.index)
11831183
}
11841184
}
11851185

11861186
impl fmt::Show for RegionVid {
11871187
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1188-
write!(f, "'<generic lifetime #{}>", self.index)
1188+
write!(f, "'_#{}r", self.index)
11891189
}
11901190
}
11911191

@@ -5566,3 +5566,18 @@ pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T)
55665566
Some(d) => f(d.as_slice())
55675567
}
55685568
}
5569+
5570+
impl AutoAdjustment {
5571+
pub fn is_identity(&self) -> bool {
5572+
match *self {
5573+
AdjustAddEnv(..) => false,
5574+
AdjustDerefRef(ref r) => r.is_identity(),
5575+
}
5576+
}
5577+
}
5578+
5579+
impl AutoDerefRef {
5580+
pub fn is_identity(&self) -> bool {
5581+
self.autoderefs == 0 && self.autoref.is_none()
5582+
}
5583+
}

0 commit comments

Comments
 (0)