From 167683da230c9685d31b9e6155b18740f9fe858e Mon Sep 17 00:00:00 2001 From: Alex Crichton <alex@alexcrichton.com> Date: Thu, 1 Jan 2015 12:16:49 -0800 Subject: [PATCH 1/9] Register new snapshots --- src/snapshots.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/snapshots.txt b/src/snapshots.txt index 6a9bfa07cf7..34beb53bd07 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,12 @@ +S 2015-01-01 7d4f487 + freebsd-x86_64 5dc87adb17bc33abc08f1bf4c092e0b5b92a6ca4 + linux-i386 63bf82a5b540d8acbbf1e445ce48be0fa0f003fc + linux-x86_64 b1a414355ef5d2feff18ab9d008a2e9afc7b4625 + macos-i386 26042e3e648eb40848bf02f3e05ba31fd686179c + macos-x86_64 f01d7c6faf5db480a18a521c6971364f4ce8ddca + winnt-i386 6f04af045d26a0c87d487ba7254d4ad0c166ecaf + winnt-x86_64 392ab49482ec926de6a167afe920518b9a502a3f + S 2014-12-30 023dfb0 freebsd-x86_64 41ecd0ac557c823831c46696c7d78dc250398f25 linux-i386 fe6b59bf70a397e18629cb82264f7c6a70df34d4 From cc5ecaf76589a83e40136e31d211246204767465 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio <japaricious@gmail.com> Date: Fri, 2 Jan 2015 09:12:27 -0500 Subject: [PATCH 2/9] merge `*SliceExt` traits, use assoc types in `SliceExt`, `Raw[Mut]Ptr` --- src/libcollections/lib.rs | 4 +- src/libcollections/slice.rs | 551 +++++++++++++++++---------------- src/libcollections/string.rs | 3 +- src/libcollections/vec.rs | 4 +- src/libcore/prelude.rs | 1 - src/libcore/ptr.rs | 24 +- src/libcore/slice.rs | 365 ++++++++++------------ src/libstd/c_str.rs | 2 +- src/libstd/io/comm_adapters.rs | 2 +- src/libstd/io/mem.rs | 2 +- src/libstd/io/mod.rs | 2 +- src/libstd/io/net/ip.rs | 2 +- src/libstd/lib.rs | 1 + src/libstd/macros.rs | 3 +- src/libstd/num/strconv.rs | 2 +- src/libstd/os.rs | 1 - src/libstd/path/mod.rs | 3 +- src/libstd/path/posix.rs | 5 +- src/libstd/path/windows.rs | 2 +- src/libstd/prelude.rs | 4 +- 20 files changed, 489 insertions(+), 494 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cbd8d4955b2..09cff4bc5ad 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -25,6 +25,7 @@ #![feature(macro_rules, default_type_params, phase, globs)] #![feature(unsafe_destructor, slicing_syntax)] #![feature(unboxed_closures)] +#![feature(associated_types)] #![no_std] #[phase(plugin, link)] extern crate core; @@ -120,7 +121,6 @@ mod prelude { pub use core::result::Result::{Ok, Err}; // in core and collections (may differ). - pub use slice::{PartialEqSliceExt, OrdSliceExt}; pub use slice::{AsSlice, SliceExt}; pub use str::{from_str, Str, StrExt}; @@ -129,7 +129,7 @@ mod prelude { pub use unicode::char::UnicodeChar; // from collections. - pub use slice::{CloneSliceExt, SliceConcatExt}; + pub use slice::SliceConcatExt; pub use str::IntoMaybeOwned; pub use string::{String, ToString}; pub use vec::Vec; diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 61111d96bd0..ac271e75ea1 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -96,7 +96,7 @@ use core::mem::size_of; use core::mem; use core::ops::{FnMut,SliceMut}; use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; -use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result}; +use core::prelude::{Ord, Ordering, PartialEq, PtrExt, Some, range, IteratorCloneExt, Result}; use core::ptr; use core::slice as core_slice; use self::Direction::*; @@ -104,7 +104,7 @@ use self::Direction::*; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; -pub use core::slice::{Iter, IterMut, PartialEqSliceExt}; +pub use core::slice::{Iter, IterMut}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; @@ -122,7 +122,9 @@ pub type MutItems<'a, T:'a> = IterMut<'a, T>; /// Allocating extension methods for slices. #[unstable = "needs associated types, may merge with other traits"] -pub trait SliceExt<T> for Sized? { +pub trait SliceExt for Sized? { + type Item; + /// Sorts the slice, in place, using `compare` to compare /// elements. /// @@ -141,7 +143,7 @@ pub trait SliceExt<T> for Sized? { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[stable] - fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; + fn sort_by<F>(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; /// Consumes `src` and moves as many elements as it can into `self` /// from the range [start,end). @@ -165,7 +167,7 @@ pub trait SliceExt<T> for Sized? { /// assert!(a == [6i, 7, 8, 4, 5]); /// ``` #[experimental = "uncertain about this API approach"] - fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint; + fn move_from(&mut self, src: Vec<Self::Item>, start: uint, end: uint) -> uint; /// Returns a subslice spanning the interval [`start`, `end`). /// @@ -174,7 +176,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice(&self, start: uint, end: uint) -> &[T]; + fn slice(&self, start: uint, end: uint) -> &[Self::Item]; /// Returns a subslice from `start` to the end of the slice. /// @@ -182,7 +184,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from(&self, start: uint) -> &[T]; + fn slice_from(&self, start: uint) -> &[Self::Item]; /// Returns a subslice from the start of the slice to `end`. /// @@ -190,7 +192,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to(&self, end: uint) -> &[T]; + fn slice_to(&self, end: uint) -> &[Self::Item]; /// Divides one slice into two at an index. /// @@ -200,32 +202,32 @@ pub trait SliceExt<T> for Sized? { /// /// Panics if `mid > len`. #[stable] - fn split_at(&self, mid: uint) -> (&[T], &[T]); + fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]); /// Returns an iterator over the slice #[stable] - fn iter(&self) -> Iter<T>; + fn iter(&self) -> Iter<Self::Item>; /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. #[stable] - fn split<F>(&self, pred: F) -> Split<T, F> - where F: FnMut(&T) -> bool; + fn split<F>(&self, pred: F) -> Split<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F> - where F: FnMut(&T) -> bool; + fn splitn<F>(&self, n: uint, pred: F) -> SplitN<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F> - where F: FnMut(&T) -> bool; + fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over all contiguous windows of length /// `size`. The windows overlap. If the slice is shorter than @@ -247,7 +249,7 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn windows(&self, size: uint) -> Windows<T>; + fn windows(&self, size: uint) -> Windows<Self::Item>; /// Returns an iterator over `size` elements of the slice at a /// time. The chunks do not overlap. If `size` does not divide the @@ -270,41 +272,41 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn chunks(&self, size: uint) -> Chunks<T>; + fn chunks(&self, size: uint) -> Chunks<Self::Item>; /// Returns the element of a slice at the given index, or `None` if the /// index is out of bounds. #[stable] - fn get(&self, index: uint) -> Option<&T>; + fn get(&self, index: uint) -> Option<&Self::Item>; /// Returns the first element of a slice, or `None` if it is empty. #[stable] - fn first(&self) -> Option<&T>; + fn first(&self) -> Option<&Self::Item>; /// Deprecated: renamed to `first`. #[deprecated = "renamed to `first`"] - fn head(&self) -> Option<&T> { self.first() } + fn head(&self) -> Option<&Self::Item> { self.first() } /// Returns all but the first element of a slice. #[experimental = "likely to be renamed"] - fn tail(&self) -> &[T]; + fn tail(&self) -> &[Self::Item]; /// Returns all but the last element of a slice. #[experimental = "likely to be renamed"] - fn init(&self) -> &[T]; + fn init(&self) -> &[Self::Item]; /// Returns the last element of a slice, or `None` if it is empty. #[stable] - fn last(&self) -> Option<&T>; + fn last(&self) -> Option<&Self::Item>; /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable] - unsafe fn get_unchecked(&self, index: uint) -> &T; + unsafe fn get_unchecked(&self, index: uint) -> &Self::Item; /// Deprecated: renamed to `get_unchecked`. #[deprecated = "renamed to get_unchecked"] - unsafe fn unsafe_get(&self, index: uint) -> &T { + unsafe fn unsafe_get(&self, index: uint) -> &Self::Item { self.get_unchecked(index) } @@ -316,7 +318,7 @@ pub trait SliceExt<T> for Sized? { /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[stable] - fn as_ptr(&self) -> *const T; + fn as_ptr(&self) -> *const Self::Item; /// Binary search a sorted slice with a comparator function. /// @@ -352,7 +354,7 @@ pub trait SliceExt<T> for Sized? { /// ``` #[stable] fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where - F: FnMut(&T) -> Ordering; + F: FnMut(&Self::Item) -> Ordering; /// Return the number of elements in the slice /// @@ -379,12 +381,12 @@ pub trait SliceExt<T> for Sized? { /// Returns a mutable reference to the element at the given index, /// or `None` if the index is out of bounds #[stable] - fn get_mut(&mut self, index: uint) -> Option<&mut T>; + fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>; /// Work with `self` as a mut slice. /// Primarily intended for getting a &mut [T] from a [T; N]. #[stable] - fn as_mut_slice(&mut self) -> &mut [T]; + fn as_mut_slice(&mut self) -> &mut [Self::Item]; /// Returns a mutable subslice spanning the interval [`start`, `end`). /// @@ -393,7 +395,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; + fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from `start` to the end of the slice. /// @@ -401,7 +403,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from_mut(&mut self, start: uint) -> &mut [T]; + fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from the start of the slice to `end`. /// @@ -409,54 +411,54 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to_mut(&mut self, end: uint) -> &mut [T]; + fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; /// Returns an iterator that allows modifying each value #[stable] - fn iter_mut(&mut self) -> IterMut<T>; + fn iter_mut(&mut self) -> IterMut<Self::Item>; /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty #[stable] - fn first_mut(&mut self) -> Option<&mut T>; + fn first_mut(&mut self) -> Option<&mut Self::Item>; /// Depreated: renamed to `first_mut`. #[deprecated = "renamed to first_mut"] - fn head_mut(&mut self) -> Option<&mut T> { + fn head_mut(&mut self) -> Option<&mut Self::Item> { self.first_mut() } /// Returns all but the first element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn tail_mut(&mut self) -> &mut [T]; + fn tail_mut(&mut self) -> &mut [Self::Item]; /// Returns all but the last element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn init_mut(&mut self) -> &mut [T]; + fn init_mut(&mut self) -> &mut [Self::Item]; /// Returns a mutable pointer to the last item in the slice. #[stable] - fn last_mut(&mut self) -> Option<&mut T>; + fn last_mut(&mut self) -> Option<&mut Self::Item>; /// Returns an iterator over mutable subslices separated by elements that /// match `pred`. The matched element is not contained in the subslices. #[stable] - fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> - where F: FnMut(&T) -> bool; + fn split_mut<F>(&mut self, pred: F) -> SplitMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F> - where F: FnMut(&T) -> bool; + fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn_mut<F>(&mut self, n: uint, pred: F) -> RSplitNMut<T, F> - where F: FnMut(&T) -> bool; + fn rsplitn_mut<F>(&mut self, n: uint, pred: F) -> RSplitNMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over `chunk_size` elements of the slice at a time. /// The chunks are mutable and do not overlap. If `chunk_size` does @@ -467,7 +469,7 @@ pub trait SliceExt<T> for Sized? { /// /// Panics if `chunk_size` is 0. #[stable] - fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>; + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<Self::Item>; /// Swaps two elements in a slice. /// @@ -525,7 +527,7 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); + fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]); /// Reverse the order of elements in a slice, in place. /// @@ -541,11 +543,11 @@ pub trait SliceExt<T> for Sized? { /// Returns an unsafe mutable pointer to the element in index #[stable] - unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T; + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item; /// Deprecated: renamed to `get_unchecked_mut`. #[deprecated = "renamed to get_unchecked_mut"] - unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T { + unsafe fn unchecked_mut(&mut self, index: uint) -> &mut Self::Item { self.get_unchecked_mut(index) } @@ -558,11 +560,179 @@ pub trait SliceExt<T> for Sized? { /// would also make any pointers to it invalid. #[inline] #[stable] - fn as_mut_ptr(&mut self) -> *mut T; + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + /// Copies `self` into a new `Vec`. + #[stable] + fn to_vec(&self) -> Vec<Self::Item> where Self::Item: Clone; + + /// Deprecated: use `iter().cloned().partition(f)` instead. + #[deprecated = "use iter().cloned().partition(f) instead"] + fn partitioned<F>(&self, f: F) -> (Vec<Self::Item>, Vec<Self::Item>) where + Self::Item: Clone, + F: FnMut(&Self::Item) -> bool; + + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); + /// ``` + #[unstable] + fn permutations(&self) -> Permutations<Self::Item> where Self::Item: Clone; + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0i, 0, 0]; + /// let src = [1i, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3i, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3i, 4, 5]); + /// ``` + #[experimental] + fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; + + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5i, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5i, -3, 1, 2, 4]); + /// ``` + #[stable] + fn sort(&mut self) where Self::Item: Ord; + + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable] + fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord; + + /// Deprecated: use `binary_search` instead. + #[deprecated = "use binary_search instead"] + fn binary_search_elem(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0i, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1i, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn next_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1i, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Find the first index containing a matching value. + #[experimental] + fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + /// Find the last index containing a matching value. + #[experimental] + fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + /// Return true if the slice contains an element with the given value. + #[stable] + fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a prefix of the slice. + #[stable] + fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a suffix of the slice. + #[stable] + fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Convert `self` into a vector without clones or allocation. + #[experimental] + fn into_vec(self: Box<Self>) -> Vec<Self::Item>; } #[unstable = "trait is unstable"] -impl<T> SliceExt<T> for [T] { +impl<T> SliceExt for [T] { + type Item = T; + #[inline] fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { merge_sort(self, compare) @@ -777,23 +947,71 @@ impl<T> SliceExt<T> for [T] { fn as_mut_ptr(&mut self) -> *mut T { core_slice::SliceExt::as_mut_ptr(self) } -} -//////////////////////////////////////////////////////////////////////////////// -// Extension traits for slices over specifc kinds of data -//////////////////////////////////////////////////////////////////////////////// + /// Returns a copy of `v`. + #[inline] + fn to_vec(&self) -> Vec<T> where T: Clone { + let mut vector = Vec::with_capacity(self.len()); + vector.push_all(self); + vector + } -/// Extension methods for boxed slices. -#[experimental = "likely to merge into SliceExt if it survives"] -pub trait BoxedSliceExt<T> { - /// Convert `self` into a vector without clones or allocation. - #[experimental] - fn into_vec(self) -> Vec<T>; -} -#[experimental = "trait is experimental"] -impl<T> BoxedSliceExt<T> for Box<[T]> { - fn into_vec(mut self) -> Vec<T> { + #[inline] + fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool, T: Clone { + self.iter().cloned().partition(f) + } + + /// Returns an iterator over all permutations of a vector. + fn permutations(&self) -> Permutations<T> where T: Clone { + Permutations{ + swaps: ElementSwaps::new(self.len()), + v: self.to_vec(), + } + } + + fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) + } + + #[inline] + fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } + + fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord { + core_slice::SliceExt::binary_search(self, x) + } + + fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) + } + + fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } + + fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } + + fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) + } + + fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) + } + + fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) + } + + fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) + } + + fn into_vec(mut self: Box<Self>) -> Vec<T> { unsafe { let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); mem::forget(self); @@ -802,204 +1020,9 @@ impl<T> BoxedSliceExt<T> for Box<[T]> { } } -/// Allocating extension methods for slices containing `Clone` elements. -#[unstable = "likely to be merged into SliceExt"] -pub trait CloneSliceExt<T> for Sized? { - /// Copies `self` into a new `Vec`. - #[stable] - fn to_vec(&self) -> Vec<T>; - - /// Deprecated: use `iter().cloned().partition(f)` instead. - #[deprecated = "use iter().cloned().partition(f) instead"] - fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool; - - /// Creates an iterator that yields every possible permutation of the - /// vector in succession. - /// - /// # Examples - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// for p in perms { - /// println!("{}", p); - /// } - /// ``` - /// - /// Iterating through permutations one by one. - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); - /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); - /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); - /// ``` - #[unstable] - fn permutations(&self) -> Permutations<T>; - - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. - /// - /// # Example - /// - /// ```rust - /// let mut dst = [0i, 0, 0]; - /// let src = [1i, 2]; - /// - /// assert!(dst.clone_from_slice(&src) == 2); - /// assert!(dst == [1, 2, 0]); - /// - /// let src2 = [3i, 4, 5, 6]; - /// assert!(dst.clone_from_slice(&src2) == 3); - /// assert!(dst == [3i, 4, 5]); - /// ``` - #[experimental] - fn clone_from_slice(&mut self, &[T]) -> uint; -} - - -#[unstable = "trait is unstable"] -impl<T: Clone> CloneSliceExt<T> for [T] { - /// Returns a copy of `v`. - #[inline] - fn to_vec(&self) -> Vec<T> { - let mut vector = Vec::with_capacity(self.len()); - vector.push_all(self); - vector - } - - - #[inline] - fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool { - self.iter().cloned().partition(f) - } - - /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations<T> { - Permutations{ - swaps: ElementSwaps::new(self.len()), - v: self.to_vec(), - } - } - - fn clone_from_slice(&mut self, src: &[T]) -> uint { - core_slice::CloneSliceExt::clone_from_slice(self, src) - } -} - -/// Allocating extension methods for slices on Ord values. -#[unstable = "likely to merge with SliceExt"] -pub trait OrdSliceExt<T> for Sized? { - /// Sorts the slice, in place. - /// - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [-5i, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v == [-5i, -3, 1, 2, 4]); - /// ``` - #[stable] - fn sort(&mut self); - - /// Binary search a sorted slice for a given element. - /// - /// If the value is found then `Ok` is returned, containing the - /// index of the matching element; if the value is not found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Example - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. - /// - /// ```rust - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); - /// - /// assert_eq!(s.binary_search(&13), Ok(9)); - /// assert_eq!(s.binary_search(&4), Err(7)); - /// assert_eq!(s.binary_search(&100), Err(13)); - /// let r = s.binary_search(&1); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable] - fn binary_search(&self, x: &T) -> Result<uint, uint>; - - /// Deprecated: use `binary_search` instead. - #[deprecated = "use binary_search instead"] - fn binary_search_elem(&self, x: &T) -> Result<uint, uint> { - self.binary_search(x) - } - - /// Mutates the slice to the next lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// last-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [0i, 1, 2]; - /// v.next_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.next_permutation(); - /// let b: &mut [_] = &mut [1i, 0, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn next_permutation(&mut self) -> bool; - - /// Mutates the slice to the previous lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// first-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [1i, 0, 2]; - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 1, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn prev_permutation(&mut self) -> bool; -} - -#[unstable = "trait is unstable"] -impl<T: Ord> OrdSliceExt<T> for [T] { - #[inline] - fn sort(&mut self) { - self.sort_by(|a, b| a.cmp(b)) - } - - fn binary_search(&self, x: &T) -> Result<uint, uint> { - core_slice::OrdSliceExt::binary_search(self, x) - } - - fn next_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::next_permutation(self) - } - - fn prev_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::prev_permutation(self) - } -} - +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specifc kinds of data +//////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices pub trait SliceConcatExt<Sized? T, U> for Sized? { @@ -1419,7 +1442,7 @@ mod tests { use std::boxed::Box; use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; - use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; + use prelude::AsSlice; use prelude::{RandomAccessIterator, Ord, SliceConcatExt}; use core::cell::Cell; use core::default::Default; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 37a6e690f5d..b69db8b00b5 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -27,7 +27,6 @@ use core::raw::Slice as RawSlice; use unicode::str as unicode_str; use unicode::str::Utf16Item; -use slice::CloneSliceExt; use str::{mod, CharRange, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; @@ -94,7 +93,7 @@ impl String { #[inline] #[experimental = "needs investigation to see if to_string() can match perf"] pub fn from_str(string: &str) -> String { - String { vec: string.as_bytes().to_vec() } + String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) } } /// Returns the vector as a string buffer, if possible, taking care not to diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a1952352bad..ce0519a2395 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -63,8 +63,6 @@ use core::ptr; use core::raw::Slice as RawSlice; use core::uint; -use slice::CloneSliceExt; - /// A growable list type, written `Vec<T>` but pronounced 'vector.' /// /// # Examples @@ -1218,7 +1216,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: uint) { #[unstable] impl<T:Clone> Clone for Vec<T> { - fn clone(&self) -> Vec<T> { self.as_slice().to_vec() } + fn clone(&self) -> Vec<T> { ::slice::SliceExt::to_vec(self.as_slice()) } fn clone_from(&mut self, other: &Vec<T>) { // drop anything in self that will not be overwritten diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index cecb4938153..19301cc2d9e 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -64,5 +64,4 @@ pub use str::{Str, StrExt}; pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; -pub use slice::{PartialEqSliceExt, OrdSliceExt}; pub use slice::{AsSlice, SliceExt}; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index faf1d781465..09c78d4bc2a 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -243,7 +243,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// Methods on raw pointers #[stable] -pub trait PtrExt<T> { +pub trait PtrExt { + type Target; + /// Returns the null pointer. #[deprecated = "call ptr::null instead"] fn null() -> Self; @@ -271,7 +273,7 @@ pub trait PtrExt<T> { /// memory. #[unstable = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer"] - unsafe fn as_ref<'a>(&self) -> Option<&'a T>; + unsafe fn as_ref<'a>(&self) -> Option<&'a Self::Target>; /// Calculates the offset from a pointer. `count` is in units of T; e.g. a /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes. @@ -287,7 +289,9 @@ pub trait PtrExt<T> { /// Methods on mutable raw pointers #[stable] -pub trait MutPtrExt<T>{ +pub trait MutPtrExt { + type Target; + /// Returns `None` if the pointer is null, or else returns a mutable /// reference to the value wrapped in `Some`. /// @@ -297,11 +301,13 @@ pub trait MutPtrExt<T>{ /// of the returned pointer. #[unstable = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer"] - unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>; + unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>; } #[stable] -impl<T> PtrExt<T> for *const T { +impl<T> PtrExt for *const T { + type Target = T; + #[inline] #[deprecated = "call ptr::null instead"] fn null() -> *const T { null() } @@ -333,7 +339,9 @@ impl<T> PtrExt<T> for *const T { } #[stable] -impl<T> PtrExt<T> for *mut T { +impl<T> PtrExt for *mut T { + type Target = T; + #[inline] #[deprecated = "call ptr::null instead"] fn null() -> *mut T { null_mut() } @@ -365,7 +373,9 @@ impl<T> PtrExt<T> for *mut T { } #[stable] -impl<T> MutPtrExt<T> for *mut T { +impl<T> MutPtrExt for *mut T { + type Target = T; + #[inline] #[unstable = "return value does not necessarily convey all possible \ information"] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 7d894ac697b..07addf7a569 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -64,57 +64,77 @@ use raw::Slice as RawSlice; /// Extension methods for slices. #[allow(missing_docs)] // docs in libcollections -pub trait SliceExt<T> for Sized? { - fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T]; - fn slice_from<'a>(&'a self, start: uint) -> &'a [T]; - fn slice_to<'a>(&'a self, end: uint) -> &'a [T]; - fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]); - fn iter<'a>(&'a self) -> Iter<'a, T>; - fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> - where P: FnMut(&T) -> bool; - fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> - where P: FnMut(&T) -> bool; - fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> - where P: FnMut(&T) -> bool; - fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>; - fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>; - fn get<'a>(&'a self, index: uint) -> Option<&'a T>; - fn first<'a>(&'a self) -> Option<&'a T>; - fn tail<'a>(&'a self) -> &'a [T]; - fn init<'a>(&'a self) -> &'a [T]; - fn last<'a>(&'a self) -> Option<&'a T>; - unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T; - fn as_ptr(&self) -> *const T; +pub trait SliceExt for Sized? { + type Item; + + fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item]; + fn slice_from<'a>(&'a self, start: uint) -> &'a [Self::Item]; + fn slice_to<'a>(&'a self, end: uint) -> &'a [Self::Item]; + fn split_at<'a>(&'a self, mid: uint) -> (&'a [Self::Item], &'a [Self::Item]); + fn iter<'a>(&'a self) -> Iter<'a, Self::Item>; + fn split<'a, P>(&'a self, pred: P) -> Split<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn windows<'a>(&'a self, size: uint) -> Windows<'a, Self::Item>; + fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, Self::Item>; + fn get<'a>(&'a self, index: uint) -> Option<&'a Self::Item>; + fn first<'a>(&'a self) -> Option<&'a Self::Item>; + fn tail<'a>(&'a self) -> &'a [Self::Item]; + fn init<'a>(&'a self) -> &'a [Self::Item]; + fn last<'a>(&'a self) -> Option<&'a Self::Item>; + unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a Self::Item; + fn as_ptr(&self) -> *const Self::Item; fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where - F: FnMut(&T) -> Ordering; + F: FnMut(&Self::Item) -> Ordering; fn len(&self) -> uint; fn is_empty(&self) -> bool { self.len() == 0 } - fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>; - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T]; - fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T]; - fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T]; - fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T]; - fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>; - fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>; - fn tail_mut<'a>(&'a mut self) -> &'a mut [T]; - fn init_mut<'a>(&'a mut self) -> &'a mut [T]; - fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>; - fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> - where P: FnMut(&T) -> bool; - fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<T, P> - where P: FnMut(&T) -> bool; - fn rsplitn_mut<P>(&mut self, n: uint, pred: P) -> RSplitNMut<T, P> - where P: FnMut(&T) -> bool; - fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>; + fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut Self::Item>; + fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [Self::Item]; + fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [Self::Item]; + fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [Self::Item]; + fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; + fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; + fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn init_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; + fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn rsplitn_mut<P>(&mut self, n: uint, pred: P) -> RSplitNMut<Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, Self::Item>; fn swap(&mut self, a: uint, b: uint); - fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]); + fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [Self::Item], &'a mut [Self::Item]); fn reverse(&mut self); - unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T; - fn as_mut_ptr(&mut self) -> *mut T; + unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut Self::Item; + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + + fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord; + fn next_permutation(&mut self) -> bool where Self::Item: Ord; + fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + + fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; } #[unstable] -impl<T> SliceExt<T> for [T] { +impl<T> SliceExt for [T] { + type Item = T; + #[inline] fn slice(&self, start: uint, end: uint) -> &[T] { assert!(start <= end); @@ -404,6 +424,111 @@ impl<T> SliceExt<T> for [T] { fn as_mut_ptr(&mut self) -> *mut T { self.repr().data as *mut T } + + #[inline] + fn position_elem(&self, x: &T) -> Option<uint> where T: PartialEq { + self.iter().position(|y| *x == *y) + } + + #[inline] + fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq { + self.iter().rposition(|x| *x == *t) + } + + #[inline] + fn contains(&self, x: &T) -> bool where T: PartialEq { + self.iter().any(|elt| *x == *elt) + } + + #[inline] + fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + let n = needle.len(); + self.len() >= n && needle == self[..n] + } + + #[inline] + fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + let (m, n) = (self.len(), needle.len()); + m >= n && needle == self[m-n..] + } + + #[unstable] + fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord { + self.binary_search_by(|p| p.cmp(x)) + } + + #[experimental] + fn next_permutation(&mut self) -> bool where T: Ord { + // These cases only have 1 permutation each, so we can't do anything. + if self.len() < 2 { return false; } + + // Step 1: Identify the longest, rightmost weakly decreasing part of the vector + let mut i = self.len() - 1; + while i > 0 && self[i-1] >= self[i] { + i -= 1; + } + + // If that is the entire vector, this is the last-ordered permutation. + if i == 0 { + return false; + } + + // Step 2: Find the rightmost element larger than the pivot (i-1) + let mut j = self.len() - 1; + while j >= i && self[j] <= self[i-1] { + j -= 1; + } + + // Step 3: Swap that element with the pivot + self.swap(j, i-1); + + // Step 4: Reverse the (previously) weakly decreasing part + self.slice_from_mut(i).reverse(); + + true + } + + #[experimental] + fn prev_permutation(&mut self) -> bool where T: Ord { + // These cases only have 1 permutation each, so we can't do anything. + if self.len() < 2 { return false; } + + // Step 1: Identify the longest, rightmost weakly increasing part of the vector + let mut i = self.len() - 1; + while i > 0 && self[i-1] <= self[i] { + i -= 1; + } + + // If that is the entire vector, this is the first-ordered permutation. + if i == 0 { + return false; + } + + // Step 2: Reverse the weakly increasing part + self.slice_from_mut(i).reverse(); + + // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1) + let mut j = self.len() - 1; + while j >= i && self[j-1] < self[i-1] { + j -= 1; + } + + // Step 4: Swap that element with the pivot + self.swap(i-1, j); + + true + } + + #[inline] + fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { + let min = cmp::min(self.len(), src.len()); + let dst = self.slice_to_mut(min); + let src = src.slice_to(min); + for i in range(0, min) { + dst[i].clone_from(&src[i]); + } + min + } } impl<T> ops::Index<uint, T> for [T] { @@ -479,160 +604,6 @@ impl<T> ops::SliceMut<uint, [T]> for [T] { } } -/// Extension methods for slices containing `PartialEq` elements. -#[unstable = "may merge with SliceExt"] -pub trait PartialEqSliceExt<T: PartialEq> for Sized? { - /// Find the first index containing a matching value. - #[experimental] - fn position_elem(&self, t: &T) -> Option<uint>; - - /// Find the last index containing a matching value. - #[experimental] - fn rposition_elem(&self, t: &T) -> Option<uint>; - - /// Return true if the slice contains an element with the given value. - #[stable] - fn contains(&self, x: &T) -> bool; - - /// Returns true if `needle` is a prefix of the slice. - #[stable] - fn starts_with(&self, needle: &[T]) -> bool; - - /// Returns true if `needle` is a suffix of the slice. - #[stable] - fn ends_with(&self, needle: &[T]) -> bool; -} - -#[unstable = "trait is unstable"] -impl<T: PartialEq> PartialEqSliceExt<T> for [T] { - #[inline] - fn position_elem(&self, x: &T) -> Option<uint> { - self.iter().position(|y| *x == *y) - } - - #[inline] - fn rposition_elem(&self, t: &T) -> Option<uint> { - self.iter().rposition(|x| *x == *t) - } - - #[inline] - fn contains(&self, x: &T) -> bool { - self.iter().any(|elt| *x == *elt) - } - - #[inline] - fn starts_with(&self, needle: &[T]) -> bool { - let n = needle.len(); - self.len() >= n && needle == self[..n] - } - - #[inline] - fn ends_with(&self, needle: &[T]) -> bool { - let (m, n) = (self.len(), needle.len()); - m >= n && needle == self[m-n..] - } -} - -/// Extension methods for slices containing `Ord` elements. -#[unstable = "may merge with other traits"] -#[allow(missing_docs)] // docs in libcollections -pub trait OrdSliceExt<T: Ord> for Sized? { - fn binary_search(&self, x: &T) -> Result<uint, uint>; - fn next_permutation(&mut self) -> bool; - fn prev_permutation(&mut self) -> bool; -} - -#[unstable = "trait is unstable"] -impl<T: Ord> OrdSliceExt<T> for [T] { - #[unstable] - fn binary_search(&self, x: &T) -> Result<uint, uint> { - self.binary_search_by(|p| p.cmp(x)) - } - - #[experimental] - fn next_permutation(&mut self) -> bool { - // These cases only have 1 permutation each, so we can't do anything. - if self.len() < 2 { return false; } - - // Step 1: Identify the longest, rightmost weakly decreasing part of the vector - let mut i = self.len() - 1; - while i > 0 && self[i-1] >= self[i] { - i -= 1; - } - - // If that is the entire vector, this is the last-ordered permutation. - if i == 0 { - return false; - } - - // Step 2: Find the rightmost element larger than the pivot (i-1) - let mut j = self.len() - 1; - while j >= i && self[j] <= self[i-1] { - j -= 1; - } - - // Step 3: Swap that element with the pivot - self.swap(j, i-1); - - // Step 4: Reverse the (previously) weakly decreasing part - self.slice_from_mut(i).reverse(); - - true - } - - #[experimental] - fn prev_permutation(&mut self) -> bool { - // These cases only have 1 permutation each, so we can't do anything. - if self.len() < 2 { return false; } - - // Step 1: Identify the longest, rightmost weakly increasing part of the vector - let mut i = self.len() - 1; - while i > 0 && self[i-1] <= self[i] { - i -= 1; - } - - // If that is the entire vector, this is the first-ordered permutation. - if i == 0 { - return false; - } - - // Step 2: Reverse the weakly increasing part - self.slice_from_mut(i).reverse(); - - // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1) - let mut j = self.len() - 1; - while j >= i && self[j-1] < self[i-1] { - j -= 1; - } - - // Step 4: Swap that element with the pivot - self.swap(i-1, j); - - true - } -} - -/// Extension methods for slices on Clone elements -#[unstable = "may merge with other traits"] -#[allow(missing_docs)] // docs in libcollections -pub trait CloneSliceExt<T> for Sized? { - fn clone_from_slice(&mut self, &[T]) -> uint; -} - -#[unstable = "trait is unstable"] -impl<T: Clone> CloneSliceExt<T> for [T] { - #[inline] - fn clone_from_slice(&mut self, src: &[T]) -> uint { - let min = cmp::min(self.len(), src.len()); - let dst = self.slice_to_mut(min); - let src = src.slice_to(min); - for i in range(0, min) { - dst[i].clone_from(&src[i]); - } - min - } -} - //////////////////////////////////////////////////////////////////////////////// // Common traits //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 46498610e56..a11a4408019 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -539,7 +539,7 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char, #[cfg(test)] mod tests { use super::*; - use prelude::{spawn, Some, None, Option, FnOnce, ToString, CloneSliceExt}; + use prelude::{spawn, Some, None, Option, FnOnce, ToString}; use prelude::{Clone, PtrExt, Iterator, SliceExt, StrExt}; use ptr; use thread::Thread; diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 077f75e2edd..dda37765b4a 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -14,7 +14,7 @@ use comm::{Sender, Receiver}; use io; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use slice::{bytes, CloneSliceExt, SliceExt}; +use slice::{bytes, SliceExt}; use super::{Buffer, Reader, Writer, IoResult}; use vec::Vec; diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index f8ea373f8f4..af5d1630ca6 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -401,7 +401,7 @@ mod test { extern crate "test" as test_crate; use super::*; use io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; - use prelude::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt, IteratorExt, CloneSliceExt}; + use prelude::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt, IteratorExt}; use io; use self::test_crate::Bencher; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index e8b852ee492..d01840b6da0 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1919,7 +1919,7 @@ impl fmt::Show for FilePermission { mod tests { use self::BadReaderBehavior::*; use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; - use prelude::{Ok, Vec, Buffer, CloneSliceExt}; + use prelude::{Ok, Vec, Buffer, SliceExt}; use uint; #[deriving(Clone, PartialEq, Show)] diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 49ab9ddb924..78d8ac307c2 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -25,7 +25,7 @@ use ops::FnOnce; use option::Option; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use slice::{CloneSliceExt, SliceExt}; +use slice::SliceExt; use str::{FromStr, StrExt}; use vec::Vec; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 74c387c5eea..654096ce49d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -107,6 +107,7 @@ #![feature(macro_rules, globs, linkage, thread_local, asm)] #![feature(default_type_params, phase, lang_items, unsafe_destructor)] #![feature(slicing_syntax, unboxed_closures)] +#![feature(associated_types)] // Don't link to std. We are std. #![no_std] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index ebb64bc2f2d..34693be39b3 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -317,9 +317,8 @@ macro_rules! try { #[macro_export] macro_rules! vec { ($($x:expr),*) => ({ - use std::slice::BoxedSliceExt; let xs: ::std::boxed::Box<[_]> = box [$($x),*]; - xs.into_vec() + ::std::slice::SliceExt::into_vec(xs) }); ($($x:expr,)*) => (vec![$($x),*]) } diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index febdf5f6118..6c64251091a 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -20,7 +20,7 @@ use char::{mod, Char}; use num::{mod, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; -use slice::{SliceExt, CloneSliceExt}; +use slice::SliceExt; use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index df50b7f81af..7aea83a069a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -52,7 +52,6 @@ use ptr; use result::Result; use result::Result::{Err, Ok}; use slice::{AsSlice, SliceExt}; -use slice::CloneSliceExt; use str::{Str, StrExt}; use string::{String, ToString}; use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 30f3f56bc1c..fae90e8d393 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -71,8 +71,7 @@ use option::Option::{None, Some}; use str; use str::{CowString, MaybeOwned, Str, StrExt}; use string::String; -use slice::{AsSlice, CloneSliceExt}; -use slice::{PartialEqSliceExt, SliceExt}; +use slice::{AsSlice, SliceExt}; use vec::Vec; /// Typedef for POSIX file paths. diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index bd4031e6230..8718d509f00 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -22,8 +22,7 @@ use option::Option::{None, Some}; use kinds::Sized; use str::{FromStr, Str}; use str; -use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt, - PartialEqSliceExt, SliceExt}; +use slice::{Split, AsSlice, SliceConcatExt, SliceExt}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -449,7 +448,7 @@ static dot_dot_static: &'static [u8] = b".."; mod tests { use super::*; use prelude::Option::{mod, Some, None}; - use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt}; + use prelude::{Vec, Clone, AsSlice, SliceExt, IteratorExt}; use prelude::{DoubleEndedIteratorExt, Str, StrExt, ToString, GenericPath}; use str; diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 751ed4b70fb..10f4adbfe56 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1121,7 +1121,7 @@ fn prefix_len(p: Option<PathPrefix>) -> uint { mod tests { use super::*; use prelude::Option::{mod, Some, None}; - use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt}; + use prelude::{Vec, Clone, AsSlice, SliceExt, IteratorExt}; use prelude::{DoubleEndedIteratorExt, Str, ToString, GenericPath}; use super::PathPrefix::*; use super::parse_prefix; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index f016683e3d0..95b82959562 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -82,9 +82,7 @@ #[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12}; #[doc(no_inline)] pub use str::{Str, StrExt}; #[doc(no_inline)] pub use slice::AsSlice; -#[doc(no_inline)] pub use slice::{SliceConcatExt, PartialEqSliceExt}; -#[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt}; -#[doc(no_inline)] pub use slice::{BoxedSliceExt}; +#[doc(no_inline)] pub use slice::{SliceConcatExt, SliceExt}; #[doc(no_inline)] pub use string::{IntoString, String, ToString}; #[doc(no_inline)] pub use vec::Vec; From d55577255434d1a9969b74cc4ac5dff4c04d6054 Mon Sep 17 00:00:00 2001 From: Corey Richardson <corey@octayn.net> Date: Fri, 2 Jan 2015 08:26:55 -0500 Subject: [PATCH 3/9] rustdoc: fix rendering of associated types --- src/librustdoc/html/render.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f8a0b88b408..e95b8d3d8ab 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1811,6 +1811,18 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Ok(()) } +fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, + typ: &clean::TyParam) -> fmt::Result { + try!(write!(w, "type {}", it.name.as_ref().unwrap())); + if typ.bounds.len() > 0 { + try!(write!(w, ": {}", TyParamBounds(&*typ.bounds))) + } + if let Some(ref default) = typ.default { + try!(write!(w, " = {}", default)); + } + Ok(()) +} + fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety, g: &clean::Generics, selfty: &clean::SelfTy, @@ -1827,17 +1839,6 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { decl = Method(selfty, d), where_clause = WhereClause(g)) } - fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, - typ: &clean::TyParam) -> fmt::Result { - try!(write!(w, "type {}", it.name.as_ref().unwrap())); - if typ.bounds.len() > 0 { - try!(write!(w, ": {}", TyParamBounds(&*typ.bounds))) - } - if let Some(ref default) = typ.default { - try!(write!(w, " = {}", default)); - } - Ok(()) - } match meth.inner { clean::TyMethodItem(ref m) => { method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl) @@ -2122,6 +2123,15 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result { try!(write!(w, "type {} = {}", name, tydef.type_)); try!(write!(w, "</code></h4>\n")); } + clean::AssociatedTypeItem(ref typaram) => { + let name = item.name.as_ref().unwrap(); + try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>", + *name, + shortty(item), + ConciseStability(&item.stability))); + try!(assoc_type(w, item, typaram)); + try!(write!(w, "</code></h4>\n")); + } _ => panic!("can't make docs for trait item with name {}", item.name) } match item.doc_value() { From 64b7c22c46b204520a6fae1c5cd750a3d3c6a66a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio <japaricious@gmail.com> Date: Thu, 1 Jan 2015 14:53:20 -0500 Subject: [PATCH 4/9] core: use assoc types in `Deref[Mut]` --- src/liballoc/arc.rs | 4 +- src/liballoc/boxed.rs | 8 ++-- src/liballoc/lib.rs | 1 + src/liballoc/rc.rs | 4 +- src/libcollections/btree/map.rs | 6 ++- src/libcollections/btree/node.rs | 48 ++++++++++++------- src/libcollections/string.rs | 8 +++- src/libcollections/vec.rs | 10 ++-- src/libcore/array.rs | 4 +- src/libcore/borrow.rs | 4 +- src/libcore/cell.rs | 10 ++-- src/libcore/iter.rs | 8 ++-- src/libcore/nonzero.rs | 4 +- src/libcore/ops.rs | 32 +++++++++---- src/libcore/option.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 6 ++- src/librustc_resolve/check_unused.rs | 6 ++- src/librustc_resolve/lib.rs | 1 + src/librustc_resolve/record_exports.rs | 6 ++- src/libstd/collections/hash/map.rs | 2 +- src/libstd/collections/hash/table.rs | 16 +++---- src/libstd/io/stdio.rs | 6 ++- src/libstd/rt/exclusive.rs | 6 ++- src/libstd/sync/mutex.rs | 6 ++- src/libstd/sync/rwlock.rs | 10 ++-- src/libsyntax/lib.rs | 1 + src/libsyntax/owned_slice.rs | 4 +- src/libsyntax/parse/token.rs | 4 +- src/libsyntax/ptr.rs | 4 +- src/libsyntax/util/interner.rs | 4 +- src/test/auxiliary/overloaded_autoderef_xc.rs | 6 ++- ...rrowck-borrow-overloaded-auto-deref-mut.rs | 8 +++- .../borrowck-borrow-overloaded-auto-deref.rs | 6 ++- .../borrowck-borrow-overloaded-deref-mut.rs | 8 +++- .../borrowck-borrow-overloaded-deref.rs | 6 ++- src/test/compile-fail/infinite-autoderef.rs | 6 ++- src/test/compile-fail/issue-18566.rs | 6 ++- src/test/run-pass/deref-mut-on-ref.rs | 2 +- src/test/run-pass/deref-on-ref.rs | 2 +- src/test/run-pass/dst-deref-mut.rs | 8 +++- src/test/run-pass/dst-deref.rs | 6 ++- src/test/run-pass/fixup-deref-mut.rs | 8 +++- src/test/run-pass/issue-13264.rs | 10 +++- src/test/run-pass/issue-16774.rs | 8 ++-- .../run-pass/overloaded-autoderef-count.rs | 8 +++- .../run-pass/overloaded-autoderef-indexing.rs | 6 ++- .../run-pass/overloaded-autoderef-order.rs | 10 +++- .../run-pass/overloaded-autoderef-vtable.rs | 6 ++- src/test/run-pass/overloaded-deref-count.rs | 8 +++- 49 files changed, 256 insertions(+), 107 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 820a3838978..d38b77eb6fd 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -247,7 +247,9 @@ impl<T> BorrowFrom<Arc<T>> for T { } #[experimental = "Deref is experimental."] -impl<T> Deref<T> for Arc<T> { +impl<T> Deref for Arc<T> { + type Target = T; + #[inline] fn deref(&self) -> &T { &self.inner().data diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 74f0599e486..0d6ada4b229 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -153,11 +153,13 @@ impl fmt::Show for Box<Any+'static> { } } -impl<Sized? T> Deref<T> for Box<T> { +impl<Sized? T> Deref for Box<T> { + type Target = T; + fn deref(&self) -> &T { &**self } } -impl<Sized? T> DerefMut<T> for Box<T> { +impl<Sized? T> DerefMut for Box<T> { fn deref_mut(&mut self) -> &mut T { &mut **self } } @@ -210,7 +212,7 @@ mod test { #[test] fn deref() { - fn homura<T: Deref<i32>>(_: T) { } + fn homura<T: Deref<Target=i32>>(_: T) { } homura(box 765i32); } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 61b5d43d1cb..c4858aea022 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -65,6 +65,7 @@ #![no_std] #![feature(lang_items, phase, unsafe_destructor, default_type_params)] +#![feature(associated_types)] #[phase(plugin, link)] extern crate core; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index bd250938836..c57231fc434 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -355,7 +355,9 @@ impl<T> BorrowFrom<Rc<T>> for T { } #[experimental = "Deref is experimental."] -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + #[inline(always)] fn deref(&self) -> &T { &self.inner().value diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 87b40aa1cee..4b85d2da4ac 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -515,13 +515,15 @@ mod stack { marker: marker::InvariantLifetime<'id> } - impl<'id, T> Deref<T> for IdRef<'id, T> { + impl<'id, T> Deref for IdRef<'id, T> { + type Target = T; + fn deref(&self) -> &T { &*self.inner } } - impl<'id, T> DerefMut<T> for IdRef<'id, T> { + impl<'id, T> DerefMut for IdRef<'id, T> { fn deref_mut(&mut self) -> &mut T { &mut *self.inner } diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 3907f28092a..d1a2916a140 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -455,7 +455,9 @@ impl<K: Clone, V: Clone> Clone for Node<K, V> { /// flag: &'a Cell<bool>, /// } /// -/// impl<'a> Deref<Node<uint, uint>> for Nasty<'a> { +/// impl<'a> Deref for Nasty<'a> { +/// type Target = Node<uint, uint>; +/// /// fn deref(&self) -> &Node<uint, uint> { /// if self.flag.get() { /// &*self.second @@ -511,7 +513,7 @@ impl<K: Ord, V> Node<K, V> { /// Searches for the given key in the node. If it finds an exact match, /// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `GoDown` will be yielded with the index of the subtree the key must lie in. - pub fn search<Sized? Q, NodeRef: Deref<Node<K, V>>>(node: NodeRef, key: &Q) + pub fn search<Sized? Q, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q) -> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord { // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // For the B configured as of this writing (B = 6), binary search was *significantly* @@ -588,7 +590,7 @@ impl <K, V> Node<K, V> { } } -impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { /// Returns a reference to the node that contains the pointed-to edge or key/value pair. This /// is very different from `edge` and `edge_mut` because those return children of the node /// returned by `node`. @@ -597,7 +599,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, Nod } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { +impl<K, V, NodeRef, Type, NodeType> Handle<NodeRef, Type, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Converts a handle into one that stores the same information using a raw pointer. This can /// be useful in conjunction with `from_raw` when the type system is insufficient for /// determining the lifetimes of the nodes. @@ -653,7 +657,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a mut Node<K, V>, handle::Edge, handle::Internal } } -impl<K, V, NodeRef: Deref<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { // This doesn't exist because there are no uses for it, // but is fine to add, analagous to edge_mut. // @@ -667,7 +671,7 @@ pub enum ForceResult<NodeRef, Type> { Internal(Handle<NodeRef, Type, handle::Internal>) } -impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> { /// Figure out whether this handle is pointing to something in a leaf node or to something in /// an internal node, clarifying the type according to the result. pub fn force(self) -> ForceResult<NodeRef, Type> { @@ -684,8 +688,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafO } } } - -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Leaf> { +impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Leaf> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Tries to insert this key-value pair at the given index in this leaf node /// If the node is full, we have to split it. /// @@ -717,7 +722,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle:: } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { +impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Internal> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Returns a mutable reference to the edge pointed-to by this handle. This should not be /// confused with `node`, which references the parent node of what is returned here. pub fn edge_mut(&mut self) -> &mut Node<K, V> { @@ -800,7 +807,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle:: } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::Edge, NodeType> { +impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge. /// This is unsafe because the handle might point to the first edge in the node, which has no /// pair to its left. @@ -862,7 +871,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType } } -impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, +impl<'a, K: 'a, V: 'a, NodeRef: Deref<Target=Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, NodeType> { // These are fine to include, but are currently unneeded. // @@ -881,8 +890,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef // } } -impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, - NodeType> { +impl<'a, K: 'a, V: 'a, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where + NodeRef: 'a + Deref<Target=Node<K, V>> + DerefMut, +{ /// Returns a mutable reference to the key pointed-to by this handle. This doesn't return a /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the /// handle. @@ -898,7 +908,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<Node } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV, NodeType> { +impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Gets the handle pointing to the edge immediately to the left of the key/value pair pointed /// to by this handle. pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> { @@ -918,7 +930,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV, } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Leaf> { +impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Leaf> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Removes the key/value pair at the handle's location. /// /// # Panics (in debug build) @@ -929,7 +943,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Le } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Internal> { +impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Internal> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut +{ /// Steal! Stealing is roughly analogous to a binary tree rotation. /// In this case, we're "rotating" right. unsafe fn steal_rightward(&mut self) { diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index b69db8b00b5..c52993ff353 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -935,7 +935,9 @@ impl ops::Slice<uint, str> for String { } #[experimental = "waiting on Deref stabilization"] -impl ops::Deref<str> for String { +impl ops::Deref for String { + type Target = str; + fn deref<'a>(&'a self) -> &'a str { unsafe { mem::transmute(self.vec[]) } } @@ -947,7 +949,9 @@ pub struct DerefString<'a> { x: DerefVec<'a, u8> } -impl<'a> Deref<String> for DerefString<'a> { +impl<'a> Deref for DerefString<'a> { + type Target = String; + fn deref<'b>(&'b self) -> &'b String { unsafe { mem::transmute(&*self.x) } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index ce0519a2395..140c15b2f7f 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1301,12 +1301,14 @@ impl<T> ops::SliceMut<uint, [T]> for Vec<T> { } #[experimental = "waiting on Deref stability"] -impl<T> ops::Deref<[T]> for Vec<T> { +impl<T> ops::Deref for Vec<T> { + type Target = [T]; + fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() } } #[experimental = "waiting on DerefMut stability"] -impl<T> ops::DerefMut<[T]> for Vec<T> { +impl<T> ops::DerefMut for Vec<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() } } @@ -1716,7 +1718,9 @@ pub struct DerefVec<'a, T> { } #[experimental] -impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> { +impl<'a, T> Deref for DerefVec<'a, T> { + type Target = Vec<T>; + fn deref<'b>(&'b self) -> &'b Vec<T> { &self.x } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 28563a60b61..ba7714ad9bc 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -54,7 +54,7 @@ macro_rules! array_impls { #[stable] impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where A: PartialEq<B>, - Rhs: Deref<[B]>, + Rhs: Deref<Target=[B]>, { #[inline(always)] fn eq(&self, other: &Rhs) -> bool { PartialEq::eq(self[], &**other) } @@ -65,7 +65,7 @@ macro_rules! array_impls { #[stable] impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where A: PartialEq<B>, - Lhs: Deref<[A]> + Lhs: Deref<Target=[A]> { #[inline(always)] fn eq(&self, other: &[B; $N]) -> bool { PartialEq::eq(&**self, other[]) } diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 3a2cb8ea7d9..7e4d73d598d 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -191,7 +191,9 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> { } } -impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> { +impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned<T> { + type Target = B; + fn deref(&self) -> &B { match *self { Borrowed(borrowed) => borrowed, diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 4b246860006..4939fc49958 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -422,7 +422,9 @@ pub struct Ref<'b, T:'b> { } #[unstable = "waiting for `Deref` to become stable"] -impl<'b, T> Deref<T> for Ref<'b, T> { +impl<'b, T> Deref for Ref<'b, T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { self._value @@ -478,7 +480,9 @@ pub struct RefMut<'b, T:'b> { } #[unstable = "waiting for `Deref` to become stable"] -impl<'b, T> Deref<T> for RefMut<'b, T> { +impl<'b, T> Deref for RefMut<'b, T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { self._value @@ -486,7 +490,7 @@ impl<'b, T> Deref<T> for RefMut<'b, T> { } #[unstable = "waiting for `DerefMut` to become stable"] -impl<'b, T> DerefMut<T> for RefMut<'b, T> { +impl<'b, T> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut<'a>(&'a mut self) -> &'a mut T { self._value diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 7c53503b1ce..64bbc248ee1 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1174,7 +1174,7 @@ pub trait IteratorCloneExt<A> { } #[unstable = "trait is unstable"] -impl<A: Clone, D: Deref<A>, I: Iterator<D>> IteratorCloneExt<A> for I { +impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> IteratorCloneExt<A> for I { fn cloned(self) -> Cloned<I> { Cloned { it: self } } @@ -1185,7 +1185,7 @@ pub struct Cloned<I> { it: I, } -impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> { +impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> Iterator<A> for Cloned<I> { fn next(&mut self) -> Option<A> { self.it.next().cloned() } @@ -1195,7 +1195,7 @@ impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> { } } -impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>> +impl<A: Clone, D: Deref<Target=A>, I: DoubleEndedIterator<D>> DoubleEndedIterator<A> for Cloned<I> { fn next_back(&mut self) -> Option<A> { self.it.next_back().cloned() @@ -1203,7 +1203,7 @@ impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>> } #[unstable = "trait is unstable"] -impl<A: Clone, D: Deref<A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {} +impl<A: Clone, D: Deref<Target=A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {} #[unstable = "recently renamed for extension trait conventions"] /// An extension trait for cloneable iterators. diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index c429e4b8212..ba9103520d8 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -44,7 +44,9 @@ impl<T: Zeroable> NonZero<T> { } } -impl<T: Zeroable> Deref<T> for NonZero<T> { +impl<T: Zeroable> Deref for NonZero<T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { let NonZero(ref inner) = *self; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index af07869e95f..17a3c93d980 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -827,11 +827,14 @@ pub struct RangeTo<Idx> { /// struct. /// /// ``` +/// #![feature(associated_types)] /// struct DerefExample<T> { /// value: T /// } /// -/// impl<T> Deref<T> for DerefExample<T> { +/// impl<T> Deref for DerefExample<T> { +/// type Target = T; +/// /// fn deref<'a>(&'a self) -> &'a T { /// &self.value /// } @@ -843,16 +846,22 @@ pub struct RangeTo<Idx> { /// } /// ``` #[lang="deref"] -pub trait Deref<Sized? Result> for Sized? { +pub trait Deref for Sized? { + type Sized? Target; + /// The method called to dereference a value - fn deref<'a>(&'a self) -> &'a Result; + fn deref<'a>(&'a self) -> &'a Self::Target; } -impl<'a, Sized? T> Deref<T> for &'a T { +impl<'a, Sized? T> Deref for &'a T { + type Target = T; + fn deref(&self) -> &T { *self } } -impl<'a, Sized? T> Deref<T> for &'a mut T { +impl<'a, Sized? T> Deref for &'a mut T { + type Target = T; + fn deref(&self) -> &T { *self } } @@ -865,17 +874,20 @@ impl<'a, Sized? T> Deref<T> for &'a mut T { /// struct. /// /// ``` +/// #![feature(associated_types)] /// struct DerefMutExample<T> { /// value: T /// } /// -/// impl<T> Deref<T> for DerefMutExample<T> { +/// impl<T> Deref for DerefMutExample<T> { +/// type Target = T; +/// /// fn deref<'a>(&'a self) -> &'a T { /// &self.value /// } /// } /// -/// impl<T> DerefMut<T> for DerefMutExample<T> { +/// impl<T> DerefMut for DerefMutExample<T> { /// fn deref_mut<'a>(&'a mut self) -> &'a mut T { /// &mut self.value /// } @@ -888,12 +900,12 @@ impl<'a, Sized? T> Deref<T> for &'a mut T { /// } /// ``` #[lang="deref_mut"] -pub trait DerefMut<Sized? Result> for Sized? : Deref<Result> { +pub trait DerefMut for Sized? : Deref { /// The method called to mutably dereference a value - fn deref_mut<'a>(&'a mut self) -> &'a mut Result; + fn deref_mut<'a>(&'a mut self) -> &'a mut <Self as Deref>::Target; } -impl<'a, Sized? T> DerefMut<T> for &'a mut T { +impl<'a, Sized? T> DerefMut for &'a mut T { fn deref_mut(&mut self) -> &mut T { *self } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index d831a57893b..b9749f57d58 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -699,7 +699,7 @@ impl<T> Option<T> { } } -impl<'a, T: Clone, D: Deref<T>> Option<D> { +impl<'a, T: Clone, D: Deref<Target=T>> Option<D> { /// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option. /// Useful for converting an Option<&T> to an Option<T>. #[unstable = "recently added as part of collections reform"] diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7dbcc810b57..56459b72225 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -95,13 +95,15 @@ struct GraphBuilder<'a, 'b:'a, 'tcx:'b> { resolver: &'a mut Resolver<'b, 'tcx> } -impl<'a, 'b:'a, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> { +impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref(&self) -> &Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b:'a, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> { +impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> { fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 78527315199..4395bb05040 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -33,13 +33,15 @@ struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> { fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 10756f21551..75731b5e7cd 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -18,6 +18,7 @@ #![feature(globs, phase, slicing_syntax)] #![feature(rustc_diagnostic_macros)] +#![feature(associated_types)] #[phase(plugin, link)] extern crate log; #[phase(plugin, link)] extern crate syntax; diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 9c2437c376d..9bfed1e8eb9 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -34,13 +34,15 @@ struct ExportRecorder<'a, 'b:'a, 'tcx:'b> { } // Deref and DerefMut impls allow treating ExportRecorder as Resolver. -impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> Deref for ExportRecorder<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> { fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f6063df5434..e61b9af5a12 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -311,7 +311,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> SearchResult<K, V, M> where - M: Deref<RawTable<K, V>>, + M: Deref<Target=RawTable<K, V>>, F: FnMut(&K) -> bool, { let size = table.size(); diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 6938ab9b0b6..a687ba3da8d 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -210,7 +210,7 @@ impl<K, V, M> Bucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> Bucket<K, V, M> { pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> { Bucket::at_index(table, hash.inspect() as uint) } @@ -279,7 +279,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> EmptyBucket<K, V, M> { #[inline] pub fn next(self) -> Bucket<K, V, M> { let mut bucket = self.into_bucket(); @@ -315,7 +315,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> { } } -impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> EmptyBucket<K, V, M> { /// Puts given key and value pair, along with the key's hash, /// into this bucket in the hashtable. Note how `self` is 'moved' into /// this function, because this slot will no longer be empty when @@ -337,7 +337,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> FullBucket<K, V, M> { #[inline] pub fn next(self) -> Bucket<K, V, M> { let mut bucket = self.into_bucket(); @@ -384,7 +384,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> { } } -impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> FullBucket<K, V, M> { /// Removes this bucket's key and value from the hashtable. /// /// This works similarly to `put`, building an `EmptyBucket` out of the @@ -428,7 +428,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> { } } -impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> { +impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + 't> FullBucket<K, V, M> { /// Exchange a bucket state for immutable references into the table. /// Because the underlying reference to the table is also consumed, /// no further changes to the structure of the table are possible; @@ -442,7 +442,7 @@ impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> { } } -impl<'t, K, V, M: DerefMut<RawTable<K, V>> + 't> FullBucket<K, V, M> { +impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + DerefMut + 't> FullBucket<K, V, M> { /// This works similarly to `into_refs`, exchanging a bucket state /// for mutable references into the table. pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) { @@ -463,7 +463,7 @@ impl<K, V, M> BucketState<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> GapThenFull<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> GapThenFull<K, V, M> { #[inline] pub fn full(&self) -> &FullBucket<K, V, M> { &self.full diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index b7d069eb19e..e58ff1c3ac4 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -117,13 +117,15 @@ pub struct StdinReaderGuard<'a> { inner: MutexGuard<'a, RaceBox>, } -impl<'a> Deref<BufferedReader<StdReader>> for StdinReaderGuard<'a> { +impl<'a> Deref for StdinReaderGuard<'a> { + type Target = BufferedReader<StdReader>; + fn deref(&self) -> &BufferedReader<StdReader> { &self.inner.0 } } -impl<'a> DerefMut<BufferedReader<StdReader>> for StdinReaderGuard<'a> { +impl<'a> DerefMut for StdinReaderGuard<'a> { fn deref_mut(&mut self) -> &mut BufferedReader<StdReader> { &mut self.inner.0 } diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs index 88bdb29caec..e44511169ab 100644 --- a/src/libstd/rt/exclusive.rs +++ b/src/libstd/rt/exclusive.rs @@ -74,10 +74,12 @@ impl<'a, T: Send> ExclusiveGuard<'a, T> { } } -impl<'a, T: Send> Deref<T> for ExclusiveGuard<'a, T> { +impl<'a, T: Send> Deref for ExclusiveGuard<'a, T> { + type Target = T; + fn deref(&self) -> &T { &*self._data } } -impl<'a, T: Send> DerefMut<T> for ExclusiveGuard<'a, T> { +impl<'a, T: Send> DerefMut for ExclusiveGuard<'a, T> { fn deref_mut(&mut self) -> &mut T { &mut *self._data } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 52004bb4a8f..08980eb01c6 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -288,12 +288,14 @@ impl<'mutex, T> MutexGuard<'mutex, T> { } } -impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> { +impl<'mutex, T> Deref for MutexGuard<'mutex, T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.__data.get() } } } -impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> { +impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.__data.get() } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 7f3c77c97ad..7478e903355 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -326,13 +326,17 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { } } -impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index d5093c5055c..d86db4e177e 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -26,6 +26,7 @@ #![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)] #![feature(quote, unsafe_destructor)] #![feature(unboxed_closures)] +#![feature(associated_types)] extern crate arena; extern crate fmt_macros; diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 3023c547fb0..8c00aaf9bee 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -54,7 +54,9 @@ impl<T> OwnedSlice<T> { } } -impl<T> Deref<[T]> for OwnedSlice<T> { +impl<T> Deref for OwnedSlice<T> { + type Target = [T]; + fn deref(&self) -> &[T] { self.as_slice() } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index f22a4b5c6ed..61da1c25926 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -606,7 +606,9 @@ impl InternedString { } } -impl Deref<str> for InternedString { +impl Deref for InternedString { + type Target = str; + fn deref(&self) -> &str { &*self.string } } diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 1b3ebde2461..5d4f50f5fd2 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -75,7 +75,9 @@ impl<T: 'static> P<T> { } } -impl<T> Deref<T> for P<T> { +impl<T> Deref for P<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { &*self.ptr } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 97eb4316583..5dde8db6155 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -124,7 +124,9 @@ impl BorrowFrom<RcStr> for str { } } -impl Deref<str> for RcStr { +impl Deref for RcStr { + type Target = str; + fn deref(&self) -> &str { self.string[] } } diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs index 26d61e166f2..05960a5b8e1 100644 --- a/src/test/auxiliary/overloaded_autoderef_xc.rs +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::ops::Deref; struct DerefWithHelper<H, T> { @@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> { } } -impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> { +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + fn deref(&self) -> &T { self.helper.helper_borrow() } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs index 05bc0d1e13b..7cd170f7773 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -11,19 +11,23 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. +#![feature(associated_types)] + use std::ops::{Deref, DerefMut}; struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs index 5aaefd01739..759467aeda3 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs @@ -11,13 +11,17 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. +#![feature(associated_types)] + use std::ops::Deref; struct Rc<T> { value: *const T } -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs index 974fe3bc5d5..74dceab18ea 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs @@ -11,19 +11,23 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. +#![feature(associated_types)] + use std::ops::{Deref, DerefMut}; struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs index 5397c5b8a56..635e440c6fe 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs @@ -11,13 +11,17 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. +#![feature(associated_types)] + use std::ops::Deref; struct Rc<T> { value: *const T } -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } diff --git a/src/test/compile-fail/infinite-autoderef.rs b/src/test/compile-fail/infinite-autoderef.rs index e4c6fa7d47f..ab770c099e1 100644 --- a/src/test/compile-fail/infinite-autoderef.rs +++ b/src/test/compile-fail/infinite-autoderef.rs @@ -10,11 +10,15 @@ // error-pattern: reached the recursion limit while auto-dereferencing +#![feature(associated_types)] + use std::ops::Deref; struct Foo; -impl Deref<Foo> for Foo { +impl Deref for Foo { + type Target = Foo; + fn deref(&self) -> &Foo { self } diff --git a/src/test/compile-fail/issue-18566.rs b/src/test/compile-fail/issue-18566.rs index f64d8fee2d8..1ccd1753c76 100644 --- a/src/test/compile-fail/issue-18566.rs +++ b/src/test/compile-fail/issue-18566.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + struct MyPtr<'a>(&'a mut uint); -impl<'a> Deref<uint> for MyPtr<'a> { +impl<'a> Deref for MyPtr<'a> { + type Target = uint; + fn deref<'b>(&'b self) -> &'b uint { self.0 } } diff --git a/src/test/run-pass/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs index dcf7c483b2c..03848b2d820 100644 --- a/src/test/run-pass/deref-mut-on-ref.rs +++ b/src/test/run-pass/deref-mut-on-ref.rs @@ -10,7 +10,7 @@ // Test that `&mut T` implements `DerefMut<T>` -fn inc<T:DerefMut<int>>(mut t: T) { +fn inc<T:Deref<Target=int> + DerefMut>(mut t: T) { *t += 1; } diff --git a/src/test/run-pass/deref-on-ref.rs b/src/test/run-pass/deref-on-ref.rs index 27e7d8f3ba2..7ebf7a9cd30 100644 --- a/src/test/run-pass/deref-on-ref.rs +++ b/src/test/run-pass/deref-on-ref.rs @@ -10,7 +10,7 @@ // Test that `&T` and `&mut T` implement `Deref<T>` -fn deref<U:Copy,T:Deref<U>>(t: T) -> U { +fn deref<U:Copy,T:Deref<Target=U>>(t: T) -> U { *t } diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs index c2707a1ae6e..72a07ca7d35 100644 --- a/src/test/run-pass/dst-deref-mut.rs +++ b/src/test/run-pass/dst-deref-mut.rs @@ -10,17 +10,21 @@ // Test that a custom deref with a fat pointer return type does not ICE +#![feature(associated_types)] + pub struct Arr { ptr: Box<[uint]> } -impl Deref<[uint]> for Arr { +impl Deref for Arr { + type Target = [uint]; + fn deref(&self) -> &[uint] { panic!(); } } -impl DerefMut<[uint]> for Arr { +impl DerefMut for Arr { fn deref_mut(&mut self) -> &mut [uint] { &mut *self.ptr } diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs index 43b7d116d30..8d32216697d 100644 --- a/src/test/run-pass/dst-deref.rs +++ b/src/test/run-pass/dst-deref.rs @@ -10,11 +10,15 @@ // Test that a custom deref with a fat pointer return type does not ICE +#![feature(associated_types)] + pub struct Arr { ptr: Box<[uint]> } -impl Deref<[uint]> for Arr { +impl Deref for Arr { + type Target = [uint]; + fn deref(&self) -> &[uint] { &*self.ptr } diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs index d2812ce1d2c..9c2a8575bb9 100644 --- a/src/test/run-pass/fixup-deref-mut.rs +++ b/src/test/run-pass/fixup-deref-mut.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + // Generic unique/owned smaht pointer. struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.value } } diff --git a/src/test/run-pass/issue-13264.rs b/src/test/run-pass/issue-13264.rs index 06ab67f2f3e..aac33f3d8a6 100644 --- a/src/test/run-pass/issue-13264.rs +++ b/src/test/run-pass/issue-13264.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + struct Root { jsref: JSRef } -impl Deref<JSRef> for Root { +impl Deref for Root { + type Target = JSRef; + fn deref<'a>(&'a self) -> &'a JSRef { &self.jsref } @@ -23,7 +27,9 @@ struct JSRef { node: *const Node } -impl Deref<Node> for JSRef { +impl Deref for JSRef { + type Target = Node; + fn deref<'a>(&'a self) -> &'a Node { self.get() } diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs index ebc879d82fb..1b5016d198d 100644 --- a/src/test/run-pass/issue-16774.rs +++ b/src/test/run-pass/issue-16774.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +#![feature(associated_types, unboxed_closures)] struct X(Box<int>); @@ -23,14 +23,16 @@ impl Drop for X { } } -impl Deref<int> for X { +impl Deref for X { + type Target = int; + fn deref(&self) -> &int { let &X(box ref x) = self; x } } -impl DerefMut<int> for X { +impl DerefMut for X { fn deref_mut(&mut self) -> &mut int { let &X(box ref mut x) = self; x diff --git a/src/test/run-pass/overloaded-autoderef-count.rs b/src/test/run-pass/overloaded-autoderef-count.rs index 4cf5e074139..5b105646dac 100644 --- a/src/test/run-pass/overloaded-autoderef-count.rs +++ b/src/test/run-pass/overloaded-autoderef-count.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::cell::Cell; use std::ops::{Deref, DerefMut}; @@ -32,14 +34,16 @@ impl<T> DerefCounter<T> { } } -impl<T> Deref<T> for DerefCounter<T> { +impl<T> Deref for DerefCounter<T> { + type Target = T; + fn deref(&self) -> &T { self.count_imm.set(self.count_imm.get() + 1); &self.value } } -impl<T> DerefMut<T> for DerefCounter<T> { +impl<T> DerefMut for DerefCounter<T> { fn deref_mut(&mut self) -> &mut T { self.count_mut += 1; &mut self.value diff --git a/src/test/run-pass/overloaded-autoderef-indexing.rs b/src/test/run-pass/overloaded-autoderef-indexing.rs index 5c4befcd0c8..7d550c925b7 100644 --- a/src/test/run-pass/overloaded-autoderef-indexing.rs +++ b/src/test/run-pass/overloaded-autoderef-indexing.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + struct DerefArray<'a, T:'a> { inner: &'a [T] } -impl<'a, T> Deref<&'a [T]> for DerefArray<'a, T> { +impl<'a, T> Deref for DerefArray<'a, T> { + type Target = &'a [T]; + fn deref<'b>(&'b self) -> &'b &'a [T] { &self.inner } diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index f0daf371ca7..5b45413e760 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::rc::Rc; struct DerefWrapper<X, Y> { @@ -23,7 +25,9 @@ impl<X, Y> DerefWrapper<X, Y> { } } -impl<X, Y> Deref<Y> for DerefWrapper<X, Y> { +impl<X, Y> Deref for DerefWrapper<X, Y> { + type Target = Y; + fn deref(&self) -> &Y { &self.y } @@ -46,7 +50,9 @@ mod priv_test { } } - impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> { + impl<X, Y> Deref for DerefWrapperHideX<X, Y> { + type Target = Y; + fn deref(&self) -> &Y { &self.y } diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index f71afb96507..23efba15749 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::ops::Deref; struct DerefWithHelper<H, T> { @@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> { } } -impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> { +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + fn deref(&self) -> &T { self.helper.helper_borrow() } diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs index 7645500c02f..b6fb38d5cc2 100644 --- a/src/test/run-pass/overloaded-deref-count.rs +++ b/src/test/run-pass/overloaded-deref-count.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::cell::Cell; use std::ops::{Deref, DerefMut}; use std::vec::Vec; @@ -32,14 +34,16 @@ impl<T> DerefCounter<T> { } } -impl<T> Deref<T> for DerefCounter<T> { +impl<T> Deref for DerefCounter<T> { + type Target = T; + fn deref(&self) -> &T { self.count_imm.set(self.count_imm.get() + 1); &self.value } } -impl<T> DerefMut<T> for DerefCounter<T> { +impl<T> DerefMut for DerefCounter<T> { fn deref_mut(&mut self) -> &mut T { self.count_mut += 1; &mut self.value From cddb41dd1fd7ace99fbc653b8aca48a0feba9c48 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 2 Jan 2015 04:20:34 -0500 Subject: [PATCH 5/9] Do not ICE when projecting out of a value with type `ty::ty_err` --- src/librustc/middle/traits/project.rs | 45 +++++++++++++------ src/librustc/middle/ty.rs | 2 +- ...ed-types-ICE-when-projecting-out-of-err.rs | 34 ++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c84f31bf6c3..125f39b1a43 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -21,8 +21,10 @@ use super::VtableImplData; use middle::infer; use middle::subst::Subst; -use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty}; +use middle::ty::{mod, AsPredicate, ReferencesError, RegionEscape, + HasProjectionTypes, ToPolyTraitRef, Ty}; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; +use std::rc::Rc; use util::ppaux::Repr; pub type PolyProjectionObligation<'tcx> = @@ -372,6 +374,15 @@ fn project_type<'cx,'tcx>( return Err(ProjectionTyError::TraitSelectionError(Overflow)); } + let obligation_trait_ref = + selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref); + + debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx())); + + if obligation_trait_ref.references_error() { + return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!())); + } + let mut candidates = ProjectionTyCandidateSet { vec: Vec::new(), ambiguous: false, @@ -379,15 +390,18 @@ fn project_type<'cx,'tcx>( assemble_candidates_from_object_type(selcx, obligation, + &obligation_trait_ref, &mut candidates); if candidates.vec.is_empty() { assemble_candidates_from_param_env(selcx, obligation, + &obligation_trait_ref, &mut candidates); if let Err(e) = assemble_candidates_from_impls(selcx, obligation, + &obligation_trait_ref, &mut candidates) { return Err(ProjectionTyError::TraitSelectionError(e)); } @@ -421,17 +435,20 @@ fn project_type<'cx,'tcx>( /// there that can answer this question. fn assemble_candidates_from_param_env<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { let env_predicates = selcx.param_env().caller_bounds.predicates.clone(); let env_predicates = env_predicates.iter().cloned().collect(); - assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates); + assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, + candidate_set, env_predicates); } fn assemble_candidates_from_predicates<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>, env_predicates: Vec<ty::Predicate<'tcx>>) { @@ -445,7 +462,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( let is_match = infcx.probe(|_| { let origin = infer::Misc(obligation.cause.span); let obligation_poly_trait_ref = - obligation.predicate.trait_ref.to_poly_trait_ref(); + obligation_trait_ref.to_poly_trait_ref(); let data_poly_trait_ref = data.to_poly_trait_ref(); infcx.sub_poly_trait_refs(false, @@ -466,14 +483,14 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( fn assemble_candidates_from_object_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { let infcx = selcx.infcx(); - let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref); debug!("assemble_candidates_from_object_type(trait_ref={})", - trait_ref.repr(infcx.tcx)); - let self_ty = trait_ref.self_ty(); + obligation_trait_ref.repr(infcx.tcx)); + let self_ty = obligation_trait_ref.self_ty(); let data = match self_ty.sty { ty::ty_trait(ref data) => data, _ => { return; } @@ -482,21 +499,21 @@ fn assemble_candidates_from_object_type<'cx,'tcx>( let env_predicates = projection_bounds.iter() .map(|p| p.as_predicate()) .collect(); - assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates) + assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, + candidate_set, env_predicates) } fn assemble_candidates_from_impls<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) -> Result<(), SelectionError<'tcx>> { // If we are resolving `<T as TraitRef<...>>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: - let trait_ref = - obligation.predicate.trait_ref.to_poly_trait_ref(); - let trait_obligation = - obligation.with(trait_ref.to_poly_trait_predicate()); + let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); let vtable = match selcx.select(&trait_obligation) { Ok(Some(vtable)) => vtable, Ok(None) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7bc5d3d0708..399d537088c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -7269,7 +7269,7 @@ impl<T:ReferencesError> ReferencesError for Binder<T> { impl<T:ReferencesError> ReferencesError for Rc<T> { fn references_error(&self) -> bool { - (&*self).references_error() + (&**self).references_error() } } diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs new file mode 100644 index 00000000000..5743216b6ca --- /dev/null +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not ICE when the self type is `ty::err`, but rather +// just propagate the error. + +#![crate_type = "lib"] +#![feature(associated_types, default_type_params, lang_items)] +#![no_std] + +#[lang="sized"] +pub trait Sized for Sized? { + // Empty. +} + +#[lang = "add"] +trait Add<RHS=Self> { + type Output; + + fn add(self, RHS) -> Self::Output; +} + +fn ice<A>(a: A) { + let r = loop {}; + r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error. + //~^ ERROR type of this value must be known +} From ea1ad792f9c182f18d865d5ff34a86a8ef0e4421 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 2 Jan 2015 11:39:47 -0500 Subject: [PATCH 6/9] Evaluate projection predicates during trait selection. Fixes #20296. --- src/librustc/middle/traits/select.rs | 46 +++++++++--- .../associated-types-conditional-dispatch.rs | 73 +++++++++++++++++++ 2 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/associated-types-conditional-dispatch.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f9dced088f8..ef8fbdfaa6c 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -289,6 +289,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn evaluate_predicates_recursively<'a,'o,I>(&mut self, + stack: Option<&TraitObligationStack<'o, 'tcx>>, + mut predicates: I) + -> EvaluationResult<'tcx> + where I : Iterator<&'a PredicateObligation<'tcx>>, 'tcx:'a + { + let mut result = EvaluatedToOk; + for obligation in predicates { + match self.evaluate_predicate_recursively(stack, obligation) { + EvaluatedToErr(e) => { return EvaluatedToErr(e); } + EvaluatedToAmbig => { result = EvaluatedToAmbig; } + EvaluatedToOk => { } + } + } + result + } + fn evaluate_predicate_recursively<'o>(&mut self, previous_stack: Option<&TraitObligationStack<'o, 'tcx>>, obligation: &PredicateObligation<'tcx>) @@ -320,9 +337,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { EvaluatedToOk } - ty::Predicate::Projection(..) => { - // FIXME(#20296) -- we should be able to give a more precise answer here - EvaluatedToAmbig + ty::Predicate::Projection(ref data) => { + let result = self.infcx.probe(|_| { + let project_obligation = obligation.with(data.clone()); + project::poly_project_and_unify_type(self, &project_obligation) + }); + match result { + Ok(Some(subobligations)) => { + self.evaluate_predicates_recursively(previous_stack, subobligations.iter()) + } + Ok(None) => { + EvaluatedToAmbig + } + Err(_) => { + EvaluatedToErr(Unimplemented) + } + } } } } @@ -1026,15 +1056,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { selection: Selection<'tcx>) -> EvaluationResult<'tcx> { - let mut result = EvaluatedToOk; - for obligation in selection.iter_nested() { - match self.evaluate_predicate_recursively(stack, obligation) { - EvaluatedToErr(e) => { return EvaluatedToErr(e); } - EvaluatedToAmbig => { result = EvaluatedToAmbig; } - EvaluatedToOk => { } - } - } - result + self.evaluate_predicates_recursively(stack, selection.iter_nested()) } /// Returns true if `candidate_i` should be dropped in favor of `candidate_j`. diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs new file mode 100644 index 00000000000..4efd0ef348d --- /dev/null +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -0,0 +1,73 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we evaluate projection predicates to winnow out +// candidates during trait selection and method resolution (#20296). +// If we don't properly winnow out candidates based on the output type +// `Output=[A]`, then the impl marked with `(*)` is seen to conflict +// with all the others. + +#![feature(associated_types, default_type_params)] + +use std::ops::Deref; + +pub trait MyEq<Sized? U=Self> for Sized? { + fn eq(&self, u: &U) -> bool; +} + +impl<A, B> MyEq<[B]> for [A] + where A : MyEq<B> +{ + fn eq(&self, other: &[B]) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()) + .all(|(a, b)| MyEq::eq(a, b)) + } +} + +// (*) This impl conflicts with everything unless the `Output=[A]` +// constraint is considered. +impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs + where A: MyEq<B>, Lhs: Deref<Output=[A]> +{ + fn eq(&self, other: &[B; 0]) -> bool { + MyEq::eq(&**self, other.as_slice()) + } +} + +struct DerefWithHelper<H, T> { + pub helper: H +} + +trait Helper<T> { + fn helper_borrow(&self) -> &T; +} + +impl<T> Helper<T> for Option<T> { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Output = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +pub fn check<T: MyEq>(x: T, y: T) -> bool { + let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) }; + d.eq(&y) +} + +pub fn main() { +} From 45468f37c85adb6e1339af33c2f18770b4ac9dac Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 2 Jan 2015 13:22:45 -0500 Subject: [PATCH 7/9] Temporarily do not evaluate subobligations. --- src/librustc/middle/traits/select.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ef8fbdfaa6c..5b5cb8ae13e 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -343,8 +343,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { project::poly_project_and_unify_type(self, &project_obligation) }); match result { - Ok(Some(subobligations)) => { - self.evaluate_predicates_recursively(previous_stack, subobligations.iter()) + Ok(Some(_subobligations)) => { + // TODO we should evaluate _subobligations, but doing so leads to an ICE + // self.evaluate_predicates_recursively(previous_stack, + // subobligations.iter()) + EvaluatedToAmbig } Ok(None) => { EvaluatedToAmbig From fc7d8faba87716bbcaa43c3747fb8a98dc0c041a Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 2 Jan 2015 13:59:32 -0500 Subject: [PATCH 8/9] Handle recursive obligations without exiting the inference probe Conflicts: src/librustc/middle/traits/select.rs --- src/librustc/middle/traits/select.rs | 29 +++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 5b5cb8ae13e..a7eb883f337 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -338,24 +338,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Predicate::Projection(ref data) => { - let result = self.infcx.probe(|_| { + self.infcx.probe(|_| { let project_obligation = obligation.with(data.clone()); - project::poly_project_and_unify_type(self, &project_obligation) - }); - match result { - Ok(Some(_subobligations)) => { - // TODO we should evaluate _subobligations, but doing so leads to an ICE - // self.evaluate_predicates_recursively(previous_stack, - // subobligations.iter()) - EvaluatedToAmbig + match project::poly_project_and_unify_type(self, &project_obligation) { + Ok(Some(subobligations)) => { + self.evaluate_predicates_recursively(previous_stack, + subobligations.iter()) + } + Ok(None) => { + EvaluatedToAmbig + } + Err(_) => { + EvaluatedToErr(Unimplemented) + } } - Ok(None) => { - EvaluatedToAmbig - } - Err(_) => { - EvaluatedToErr(Unimplemented) - } - } + }) } } } From 1abee08cbdbd62a83805aa5b5068df9e00471f06 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio <japaricious@gmail.com> Date: Fri, 2 Jan 2015 14:23:46 -0500 Subject: [PATCH 9/9] fix rpass test with s/Output/Target/g --- .../run-pass/associated-types-conditional-dispatch.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index 4efd0ef348d..3b53203d218 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -11,7 +11,7 @@ // Test that we evaluate projection predicates to winnow out // candidates during trait selection and method resolution (#20296). // If we don't properly winnow out candidates based on the output type -// `Output=[A]`, then the impl marked with `(*)` is seen to conflict +// `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. #![feature(associated_types, default_type_params)] @@ -32,10 +32,10 @@ impl<A, B> MyEq<[B]> for [A] } } -// (*) This impl conflicts with everything unless the `Output=[A]` +// (*) This impl conflicts with everything unless the `Target=[A]` // constraint is considered. impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs - where A: MyEq<B>, Lhs: Deref<Output=[A]> + where A: MyEq<B>, Lhs: Deref<Target=[A]> { fn eq(&self, other: &[B; 0]) -> bool { MyEq::eq(&**self, other.as_slice()) @@ -57,7 +57,7 @@ impl<T> Helper<T> for Option<T> { } impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { - type Output = T; + type Target = T; fn deref(&self) -> &T { self.helper.helper_borrow()