From ea6a1bdf6ba754f3b96e3a46f9173b17ff18ed07 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 1 Mar 2018 10:46:06 +0000 Subject: [PATCH 01/26] Compute each key only one during slice::sort_by_key --- src/liballoc/slice.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index dc40062ef13df..c57f1e7f57297 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1328,10 +1328,18 @@ impl [T] { /// ``` #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] - pub fn sort_by_key(&mut self, mut f: F) + pub fn sort_by_key(&mut self, f: F) where F: FnMut(&T) -> B, B: Ord { - merge_sort(self, |a, b| f(a).lt(&f(b))); + let mut indices: Vec<_> = self.iter().map(f).enumerate().map(|(i, k)| (k, i)).collect(); + indices.sort(); + for i in 0..self.len() { + let mut index = indices[i].1; + while index < i { + index = indices[index].1; + } + self.swap(i, index); + } } /// Sorts the slice, but may not preserve the order of equal elements. From 670e69e20753e2ef33ee61b0515092cace3fd716 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 1 Mar 2018 12:15:05 +0000 Subject: [PATCH 02/26] Update documentation for sort_by_key --- src/liballoc/slice.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index c57f1e7f57297..db3b14859dddb 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1302,11 +1302,9 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. - /// - /// When applicable, unstable sorting is preferred because it is generally faster than stable - /// sorting and it doesn't allocate auxiliary memory. - /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// During sorting, the key function is called only once per element. + /// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)` + /// worst-case, where the key function is `O(m)`. /// /// # Current implementation /// @@ -1315,8 +1313,7 @@ impl [T] { /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of /// two or more sorted sequences concatenated one after another. /// - /// Also, it allocates temporary storage half the size of `self`, but for short slices a - /// non-allocating insertion sort is used instead. + /// The algorithm allocates temporary storage the size of `self`. /// /// # Examples /// From b8452cc3266f2d9567b5c07ca3044b3960e10ebf Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 1 Mar 2018 12:22:11 +0000 Subject: [PATCH 03/26] Clarify behaviour of sort_unstable_by_key with respect to sort_by_key --- src/liballoc/slice.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index db3b14859dddb..63b22bd0f6d87 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1303,6 +1303,7 @@ impl [T] { /// Sorts the slice with a key extraction function. /// /// During sorting, the key function is called only once per element. + /// /// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)` /// worst-case, where the key function is `O(m)`. /// @@ -1329,7 +1330,10 @@ impl [T] { where F: FnMut(&T) -> B, B: Ord { let mut indices: Vec<_> = self.iter().map(f).enumerate().map(|(i, k)| (k, i)).collect(); - indices.sort(); + // The elements of `indices` are unique, as they are indexed, so any sort will be stable + // with respect to the original slice. We use `sort_unstable` here because it requires less + // memory allocation. + indices.sort_unstable(); for i in 0..self.len() { let mut index = indices[i].1; while index < i { @@ -1414,8 +1418,11 @@ impl [T] { /// Sorts the slice with a key extraction function, but may not preserve the order of equal /// elements. /// + /// Note that, currently, the key function for `sort_unstable_by_key` is called multiple times + /// per element, unlike `sort_stable_by_key`. + /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. + /// and `O(m n log m n)` worst-case, where the key function is `O(m)`. /// /// # Current implementation /// @@ -1425,8 +1432,8 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the - /// slice consists of several concatenated sorted sequences. + /// Due to its key calling strategy, `sort_unstable_by_key` is likely to be slower than + /// `sort_by_key` in cases where the key function is expensive. /// /// # Examples /// From 9fbee359d7eb3a621604bc2067a375f6d4b757e5 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 1 Mar 2018 13:39:52 +0000 Subject: [PATCH 04/26] Add a test for sort_by_key --- src/liballoc/tests/slice.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index d9e9d91cea88a..300f6abaa7f1b 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -425,6 +425,11 @@ fn test_sort() { v.sort_by(|a, b| b.cmp(a)); assert!(v.windows(2).all(|w| w[0] >= w[1])); + // Sort in lexicographic order. + let mut v = orig.clone(); + v.sort_by_key(|x| x.to_string()); + assert!(v.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); + // Sort with many pre-sorted runs. let mut v = orig.clone(); v.sort(); From 21fde0903b394ca4765b17321a736983c43886cb Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 1 Mar 2018 16:07:58 +0000 Subject: [PATCH 05/26] Update documentation --- src/liballoc/slice.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 63b22bd0f6d87..32ade0b017833 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1314,7 +1314,7 @@ impl [T] { /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of /// two or more sorted sequences concatenated one after another. /// - /// The algorithm allocates temporary storage the size of `self`. + /// The algorithm allocates temporary storage in a `Vec<(K, usize)` the length of the slice. /// /// # Examples /// @@ -1326,8 +1326,8 @@ impl [T] { /// ``` #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] - pub fn sort_by_key(&mut self, f: F) - where F: FnMut(&T) -> B, B: Ord + pub fn sort_by_key(&mut self, f: F) + where F: FnMut(&T) -> K, K: Ord { let mut indices: Vec<_> = self.iter().map(f).enumerate().map(|(i, k)| (k, i)).collect(); // The elements of `indices` are unique, as they are indexed, so any sort will be stable @@ -1418,8 +1418,8 @@ impl [T] { /// Sorts the slice with a key extraction function, but may not preserve the order of equal /// elements. /// - /// Note that, currently, the key function for `sort_unstable_by_key` is called multiple times - /// per element, unlike `sort_stable_by_key`. + /// Note that, currently, the key function for [`sort_unstable_by_key`] is called multiple times + /// per element, unlike [`sort_by_key`]. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), /// and `O(m n log m n)` worst-case, where the key function is `O(m)`. @@ -1432,8 +1432,8 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// Due to its key calling strategy, `sort_unstable_by_key` is likely to be slower than - /// `sort_by_key` in cases where the key function is expensive. + /// Due to its key calling strategy, [`sort_unstable_by_key`] is likely to be slower than + /// [`sort_by_key`] in cases where the key function is expensive. /// /// # Examples /// @@ -1444,12 +1444,13 @@ impl [T] { /// assert!(v == [1, 2, -3, 4, -5]); /// ``` /// + /// [`sort_by_key`]: #method.sort_by_key + /// [`sort_unstable_by_key`]: #method.sort_unstable_by_key /// [pdqsort]: https://github.com/orlp/pdqsort #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] - pub fn sort_unstable_by_key(&mut self, f: F) - where F: FnMut(&T) -> B, - B: Ord + pub fn sort_unstable_by_key(&mut self, f: F) + where F: FnMut(&T) -> K, K: Ord { core_slice::SliceExt::sort_unstable_by_key(self, f); } From 7dcfc07d2c441e6e18c34dfe844c7bdc1c0137fe Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 2 Mar 2018 15:51:20 +0000 Subject: [PATCH 06/26] Cull the quadratic --- src/liballoc/slice.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 32ade0b017833..3fa5e78c04f4e 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1339,6 +1339,7 @@ impl [T] { while index < i { index = indices[index].1; } + indices[i].1 = index; self.swap(i, index); } } From bdcc6f939a10bc23a434b2ef301238650841dec9 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 2 Mar 2018 16:28:55 +0000 Subject: [PATCH 07/26] Index enumeration by minimally sized type --- src/liballoc/slice.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 3fa5e78c04f4e..fbd8d87930842 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -102,6 +102,7 @@ use core::mem::size_of; use core::mem; use core::ptr; use core::slice as core_slice; +use core::{u8, u16, u32}; use borrow::{Borrow, BorrowMut, ToOwned}; use boxed::Box; @@ -1329,19 +1330,31 @@ impl [T] { pub fn sort_by_key(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord { - let mut indices: Vec<_> = self.iter().map(f).enumerate().map(|(i, k)| (k, i)).collect(); - // The elements of `indices` are unique, as they are indexed, so any sort will be stable - // with respect to the original slice. We use `sort_unstable` here because it requires less - // memory allocation. - indices.sort_unstable(); - for i in 0..self.len() { - let mut index = indices[i].1; - while index < i { - index = indices[index].1; - } - indices[i].1 = index; - self.swap(i, index); + // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. + macro_rules! sort_by_key { + ($t:ty, $slice:ident, $f:ident) => ({ + let mut indices: Vec<_> = + $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); + // The elements of `indices` are unique, as they are indexed, so any sort will be + // stable with respect to the original slice. We use `sort_unstable` here because it + // requires less memory allocation. + indices.sort_unstable(); + for i in 0..$slice.len() { + let mut index = indices[i].1; + while (index as usize) < i { + index = indices[index as usize].1; + } + indices[i].1 = index; + $slice.swap(i, index as usize); + } + }) } + + let len = self.len(); + if len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } + if len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } + if len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } + sort_by_key!(usize, self, f) } /// Sorts the slice, but may not preserve the order of equal elements. From f41a26f2040dfa752825a7d1fdfbd5a8ae3310cf Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 16 Mar 2018 14:37:17 +0000 Subject: [PATCH 08/26] Add sort_by_cached_key method --- src/liballoc/slice.rs | 61 ++++++++++++++++++++++++++++++------- src/liballoc/tests/slice.rs | 9 ++++-- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index fbd8d87930842..306c467f048cb 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1301,6 +1301,45 @@ impl [T] { merge_sort(self, |a, b| compare(a, b) == Less); } + /// Sorts the slice with a key extraction function. + /// + /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log m n)` + /// worst-case, where the key function is `O(m)`. + /// + /// For expensive key functions (e.g. functions that are not simple property accesses or + /// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be + /// significantly faster, as it does not recompute element keys. + /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. + /// + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 1, -3, 2]; + /// + /// v.sort_by_key(|k| k.abs()); + /// assert!(v == [1, 2, -3, 4, -5]); + /// ``` + #[stable(feature = "slice_sort_by_key", since = "1.7.0")] + #[inline] + pub fn sort_by_key(&mut self, mut f: F) + where F: FnMut(&T) -> K, K: Ord + { + merge_sort(self, |a, b| f(a).lt(&f(b))); + } + /// Sorts the slice with a key extraction function. /// /// During sorting, the key function is called only once per element. @@ -1308,6 +1347,10 @@ impl [T] { /// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)` /// worst-case, where the key function is `O(m)`. /// + /// For simple key functions (e.g. functions that are property accesses or + /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be + /// faster. + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1315,19 +1358,19 @@ impl [T] { /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of /// two or more sorted sequences concatenated one after another. /// - /// The algorithm allocates temporary storage in a `Vec<(K, usize)` the length of the slice. + /// The algorithm allocates temporary storage in a `Vec<(K, usize)>` the length of the slice. /// /// # Examples /// /// ``` /// let mut v = [-5i32, 4, 1, -3, 2]; /// - /// v.sort_by_key(|k| k.abs()); + /// v.sort_by_cached_key(|k| k.abs()); /// assert!(v == [1, 2, -3, 4, -5]); /// ``` - #[stable(feature = "slice_sort_by_key", since = "1.7.0")] + #[unstable(feature = "slice_sort_by_uncached_key", issue = "34447")] #[inline] - pub fn sort_by_key(&mut self, f: F) + pub fn sort_by_cached_key(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord { // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. @@ -1432,9 +1475,6 @@ impl [T] { /// Sorts the slice with a key extraction function, but may not preserve the order of equal /// elements. /// - /// Note that, currently, the key function for [`sort_unstable_by_key`] is called multiple times - /// per element, unlike [`sort_by_key`]. - /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), /// and `O(m n log m n)` worst-case, where the key function is `O(m)`. /// @@ -1446,8 +1486,9 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// Due to its key calling strategy, [`sort_unstable_by_key`] is likely to be slower than - /// [`sort_by_key`] in cases where the key function is expensive. + /// Due to its key calling strategy, [`sort_unstable_by_key`](#method.sort_unstable_by_key) + /// is likely to be slower than [`sort_by_cached_key`](#method.sort_by_uncached_key) in + /// cases where the key function is expensive. /// /// # Examples /// @@ -1458,8 +1499,6 @@ impl [T] { /// assert!(v == [1, 2, -3, 4, -5]); /// ``` /// - /// [`sort_by_key`]: #method.sort_by_key - /// [`sort_unstable_by_key`]: #method.sort_unstable_by_key /// [pdqsort]: https://github.com/orlp/pdqsort #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 300f6abaa7f1b..7d4dac1c5ec99 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -426,9 +426,12 @@ fn test_sort() { assert!(v.windows(2).all(|w| w[0] >= w[1])); // Sort in lexicographic order. - let mut v = orig.clone(); - v.sort_by_key(|x| x.to_string()); - assert!(v.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); + let mut v1 = orig.clone(); + let mut v2 = orig.clone(); + v1.sort_by_key(|x| x.to_string()); + v2.sort_by_cached_key(|x| x.to_string()); + assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); + assert!(v1 == v2); // Sort with many pre-sorted runs. let mut v = orig.clone(); From b430cba343743783cee517bf93c7f255827cccc5 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 16 Mar 2018 16:35:27 +0000 Subject: [PATCH 09/26] Fix use of unstable feature in test --- src/liballoc/lib.rs | 1 + src/liballoc/slice.rs | 4 ++-- src/liballoc/tests/lib.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b93e128d50819..253b8acc16c42 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -113,6 +113,7 @@ #![feature(slice_get_slice)] #![feature(slice_patterns)] #![feature(slice_rsplit)] +#![feature(slice_sort_by_cached_key)] #![feature(specialization)] #![feature(staged_api)] #![feature(str_internals)] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 306c467f048cb..db8900664476e 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1368,7 +1368,7 @@ impl [T] { /// v.sort_by_cached_key(|k| k.abs()); /// assert!(v == [1, 2, -3, 4, -5]); /// ``` - #[unstable(feature = "slice_sort_by_uncached_key", issue = "34447")] + #[unstable(feature = "slice_sort_by_cached_key", issue = "34447")] #[inline] pub fn sort_by_cached_key(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord @@ -1487,7 +1487,7 @@ impl [T] { /// deterministic behavior. /// /// Due to its key calling strategy, [`sort_unstable_by_key`](#method.sort_unstable_by_key) - /// is likely to be slower than [`sort_by_cached_key`](#method.sort_by_uncached_key) in + /// is likely to be slower than [`sort_by_cached_key`](#method.sort_by_cached_key) in /// cases where the key function is expensive. /// /// # Examples diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 285cba0270c03..27f3028a51343 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -23,6 +23,7 @@ #![feature(pattern)] #![feature(placement_in_syntax)] #![feature(rand)] +#![feature(slice_sort_by_cached_key)] #![feature(splice)] #![feature(str_escape)] #![feature(string_retain)] From ca3bed0c66d27fbf30eb48ae3eb5af235669364d Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 17 Mar 2018 20:18:08 +0000 Subject: [PATCH 10/26] Improve and fix documentation for sort_by_cached_key --- src/liballoc/slice.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index db8900664476e..bef50a733cc76 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1353,21 +1353,25 @@ impl [T] { /// /// # Current implementation /// - /// The current algorithm is an adaptive, iterative merge sort inspired by - /// [timsort](https://en.wikipedia.org/wiki/Timsort). - /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of - /// two or more sorted sequences concatenated one after another. + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. /// - /// The algorithm allocates temporary storage in a `Vec<(K, usize)>` the length of the slice. + /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the + /// length of the slice. /// /// # Examples /// /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; + /// let mut v = [-5i32, 4, 32, -3, 2]; /// - /// v.sort_by_cached_key(|k| k.abs()); - /// assert!(v == [1, 2, -3, 4, -5]); + /// v.sort_by_cached_key(|k| k.to_string()); + /// assert!(v == [-3, -5, 2, 32, 4]); /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort #[unstable(feature = "slice_sort_by_cached_key", issue = "34447")] #[inline] pub fn sort_by_cached_key(&mut self, f: F) From 9896b38f01c068abfe7170cb9ae2bfadb4aebbc4 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 17 Mar 2018 20:43:46 +0000 Subject: [PATCH 11/26] Clarify time complexity --- src/liballoc/lib.rs | 1 - src/liballoc/slice.rs | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 253b8acc16c42..b93e128d50819 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -113,7 +113,6 @@ #![feature(slice_get_slice)] #![feature(slice_patterns)] #![feature(slice_rsplit)] -#![feature(slice_sort_by_cached_key)] #![feature(specialization)] #![feature(staged_api)] #![feature(str_internals)] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index bef50a733cc76..cd212aa15baeb 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1303,7 +1303,7 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log m n)` + /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log(m n))` /// worst-case, where the key function is `O(m)`. /// /// For expensive key functions (e.g. functions that are not simple property accesses or @@ -1365,6 +1365,7 @@ impl [T] { /// # Examples /// /// ``` + /// #![feature(slice_sort_by_cached_key)] /// let mut v = [-5i32, 4, 32, -3, 2]; /// /// v.sort_by_cached_key(|k| k.to_string()); @@ -1480,7 +1481,7 @@ impl [T] { /// elements. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(m n log m n)` worst-case, where the key function is `O(m)`. + /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`. /// /// # Current implementation /// From 81edd1796b463776d111cd4fe48e866dd716dfab Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 18 Mar 2018 11:11:17 +0000 Subject: [PATCH 12/26] Check that the size optimisation is not redundant --- src/liballoc/slice.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index cd212aa15baeb..2b4ce9fe49c8e 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1384,8 +1384,8 @@ impl [T] { let mut indices: Vec<_> = $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); // The elements of `indices` are unique, as they are indexed, so any sort will be - // stable with respect to the original slice. We use `sort_unstable` here because it - // requires less memory allocation. + // stable with respect to the original slice. We use `sort_unstable` here because + // it requires less memory allocation. indices.sort_unstable(); for i in 0..$slice.len() { let mut index = indices[i].1; @@ -1398,10 +1398,15 @@ impl [T] { }) } + let sz_u8 = mem::size_of::<(K, u8)>(); + let sz_u16 = mem::size_of::<(K, u16)>(); + let sz_u32 = mem::size_of::<(K, u32)>(); + let sz_usize = mem::size_of::<(K, usize)>(); + let len = self.len(); - if len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } - if len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } - if len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } + if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } + if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } + if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } sort_by_key!(usize, self, f) } From 785e3c38fe6c49e39aec145c81e463ceb60d179e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 18 Mar 2018 12:37:06 +0000 Subject: [PATCH 13/26] Add lexicographic sorting benchmark --- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 2de0ffb4b2611..9cb5f558574c1 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -13,6 +13,7 @@ #![feature(i128_type)] #![feature(rand)] #![feature(repr_simd)] +#![feature(slice_sort_by_cached_key)] #![feature(test)] extern crate rand; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index ee5182a1d4663..a699ff9c0a76e 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -284,6 +284,17 @@ macro_rules! sort_expensive { } } +macro_rules! sort_lexicographic { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + b.iter(|| v.clone().$f(|x| x.to_string())); + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; + } + } +} + sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_descending, gen_descending, 10); sort!(sort, sort_small_random, gen_random, 10); @@ -312,6 +323,10 @@ sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); +sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000); + macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { #[bench] From eca1e18cd7021f01757640c0c5ef63717870686c Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 19 Mar 2018 00:11:47 +0000 Subject: [PATCH 14/26] Add stability test for sort_by_cached_key --- src/liballoc/tests/slice.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 7d4dac1c5ec99..66c7dd75c8740 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -485,7 +485,7 @@ fn test_sort_stability() { // the second item represents which occurrence of that // number this element is, i.e. the second elements // will occur in sorted order. - let mut v: Vec<_> = (0..len) + let mut orig: Vec<_> = (0..len) .map(|_| { let n = thread_rng().gen::() % 10; counts[n] += 1; @@ -493,16 +493,21 @@ fn test_sort_stability() { }) .collect(); - // only sort on the first element, so an unstable sort + let mut v = orig.clone(); + // Only sort on the first element, so an unstable sort // may mix up the counts. v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - // this comparison includes the count (the second item + // This comparison includes the count (the second item // of the tuple), so elements with equal first items // will need to be ordered with increasing // counts... i.e. exactly asserting that this sort is // stable. assert!(v.windows(2).all(|w| w[0] <= w[1])); + + let mut v = orig.clone(); + v.sort_by_cached_key(|&(x, _)| x); + assert!(v.windows(2).all(|w| w[0] <= w[1])); } } } From 1f51840db0d846c2370f7d726eb8e41424431850 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 20 Mar 2018 23:08:04 +0100 Subject: [PATCH 15/26] Propose a variant if it is an enum for E0599 --- src/librustc_typeck/check/method/suggest.rs | 17 +++++++++++++++-- src/test/ui/issue-23217.stderr | 2 ++ src/test/ui/issue-28971.stderr | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 61afac97d6409..06bec8f6ff659 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -22,12 +22,14 @@ use rustc::traits::{Obligation, SelectionContext}; use util::nodemap::FxHashSet; use syntax::ast; +use syntax::util::lev_distance::find_best_match_for_name; use errors::DiagnosticBuilder; use syntax_pos::Span; use rustc::hir; use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; +use rustc::ty::TyAdt; use std::cell; use std::cmp::Ordering; @@ -179,9 +181,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let actual = self.resolve_type_vars_if_possible(&rcvr_ty); let ty_string = self.ty_to_string(actual); let is_method = mode == Mode::MethodCall; + let mut suggestion = None; let type_str = if is_method { "method" } else if actual.is_enum() { + if let TyAdt(ref adt_def, _) = actual.sty { + let names = adt_def.variants.iter().map(|s| &s.name); + suggestion = find_best_match_for_name(names, + &item_name.as_str(), + None); + } "variant" } else { match (item_name.as_str().chars().next(), actual.is_fresh_ty()) { @@ -256,7 +265,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.emit(); return; } else { - struct_span_err!( + let mut err = struct_span_err!( tcx.sess, span, E0599, @@ -264,7 +273,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { type_str, item_name, ty_string - ) + ); + if let Some(suggestion) = suggestion { + err.note(&format!("did you mean `{}::{}`?", type_str, suggestion)); + } + err } } else { tcx.sess.diagnostic().struct_dummy() diff --git a/src/test/ui/issue-23217.stderr b/src/test/ui/issue-23217.stderr index be9ec9d73c21c..d542a10e9b605 100644 --- a/src/test/ui/issue-23217.stderr +++ b/src/test/ui/issue-23217.stderr @@ -5,6 +5,8 @@ LL | pub enum SomeEnum { | ----------------- variant `A` not found here LL | B = SomeEnum::A, | ^^^^^^^^^^^ variant not found in `SomeEnum` + | + = note: did you mean `variant::B`? error: aborting due to previous error diff --git a/src/test/ui/issue-28971.stderr b/src/test/ui/issue-28971.stderr index 81d8d97963bd0..df114351ff571 100644 --- a/src/test/ui/issue-28971.stderr +++ b/src/test/ui/issue-28971.stderr @@ -6,6 +6,8 @@ LL | enum Foo { ... LL | Foo::Baz(..) => (), | ^^^^^^^^^^^^ variant not found in `Foo` + | + = note: did you mean `variant::Bar`? error: aborting due to previous error From 4083bdff0b7550534d93712c85164cb287acb856 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Mar 2018 16:38:16 +0100 Subject: [PATCH 16/26] Fix impl assoc constant link not working --- src/librustdoc/clean/mod.rs | 14 ++++++-------- src/test/rustdoc/link-assoc-const.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 src/test/rustdoc/link-assoc-const.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1a42b02140cd2..73b3ae32cef65 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1022,11 +1022,12 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option .flat_map(|imp| cx.tcx.associated_items(*imp)) .find(|item| item.name == item_name); if let Some(item) = item { - if item.kind == ty::AssociatedKind::Method && is_val { - Ok((ty.def, Some(format!("method.{}", item_name)))) - } else { - Err(()) - } + let out = match item.kind { + ty::AssociatedKind::Method if is_val => "method", + ty::AssociatedKind::Const if is_val => "associatedconstant", + _ => return Err(()) + }; + Ok((ty.def, Some(format!("{}.{}", out, item_name)))) } else { Err(()) } @@ -1139,9 +1140,6 @@ impl Clean for [ast::Attribute] { &link[..] }.trim(); - // avoid resolving things (i.e. regular links) which aren't like paths - // FIXME(Manishearth) given that most links have slashes in them might be worth - // doing a check for slashes first if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ch == ':' || ch == '_')) { continue; diff --git a/src/test/rustdoc/link-assoc-const.rs b/src/test/rustdoc/link-assoc-const.rs new file mode 100644 index 0000000000000..aa7ef07d5c0c3 --- /dev/null +++ b/src/test/rustdoc/link-assoc-const.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/index.html '//a[@href="../foo/foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST' +// @has foo/index.html '//a[@href="../foo/struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST' + +//! We have here [`foo::FIRSTCONST`] and [`Bar::CONST`]. + +pub mod foo { + pub const FIRSTCONST: u32 = 42; +} + +pub struct Bar; + +impl Bar { + pub const CONST: u32 = 42; +} From 1e2458e1baf987ee67b4c48c0583dfad65f7dcd7 Mon Sep 17 00:00:00 2001 From: boats Date: Mon, 26 Mar 2018 06:25:31 -0700 Subject: [PATCH 17/26] Add is_whitespace and is_alphanumeric to str. The other methods from `UnicodeStr` are already stable inherent methods on str, but these have not been included. --- src/liballoc/str.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 14d5e96d2e73a..d5ef41df0d850 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -2122,6 +2122,48 @@ impl str { unsafe { String::from_utf8_unchecked(buf) } } + /// Returns true if this `str` is entirely whitespace, and false otherwise. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived Core + /// Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(" \t ".is_whitespace()); + /// + /// // a non-breaking space + /// assert!("\u{A0}".is_whitespace()); + /// + /// assert!(!" 越".is_whitespace()); + /// ``` + #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] + #[inline] + pub fn is_whitespace(&self) -> bool { + UnicodeStr::is_whitespace(self) + } + + /// Returns true if this `str` is entirely alphanumeric, and false otherwise. + /// + /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories + /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!("٣7৬Kو藏".is_alphanumeric()); + /// assert!(!"¾①".is_alphanumeric()); + /// ``` + #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] + #[inline] + pub fn is_alphanumeric(&self) -> bool { + UnicodeStr::is_alphanumeric(self) + } + /// Checks if all characters in this string are within the ASCII range. /// /// # Examples From 5fc7e0a2ba84c44caebc5801f454663bafad2ca8 Mon Sep 17 00:00:00 2001 From: boats Date: Mon, 26 Mar 2018 07:41:45 -0700 Subject: [PATCH 18/26] Remove unnecessary trait import. --- src/librustdoc/test.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3ce8bd4ebb4c1..8ab9ca451871b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -406,8 +406,6 @@ pub fn make_test(s: &str, // FIXME(aburka): use a real parser to deal with multiline attributes fn partition_source(s: &str) -> (String, String) { - use std_unicode::str::UnicodeStr; - let mut after_header = false; let mut before = String::new(); let mut after = String::new(); From a637dd00c8536d86cfbe59d8a3881e29b3e55eeb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 26 Mar 2018 02:47:04 +0300 Subject: [PATCH 19/26] Fix pretty-printing for raw identifiers --- src/librustc/hir/print.rs | 8 ++++++-- src/libsyntax/parse/token.rs | 9 ++++++++- src/libsyntax/print/pprust.rs | 6 +++++- src/test/run-pass/rfc-2151-raw-identifiers/attr.rs | 2 -- src/test/run-pass/rfc-2151-raw-identifiers/basic.rs | 2 -- src/test/run-pass/rfc-2151-raw-identifiers/items.rs | 2 -- src/test/run-pass/rfc-2151-raw-identifiers/macros.rs | 2 -- 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 3d38c0c8ed9e5..ff501f30c891a 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -13,7 +13,7 @@ pub use self::AnnNode::*; use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; -use syntax::parse::ParseSess; +use syntax::parse::{token, ParseSess}; use syntax::parse::lexer::comments; use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; @@ -1561,7 +1561,11 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - self.s.word(&name.as_str())?; + if token::is_raw_guess(ast::Ident::with_empty_ctxt(name)) { + self.s.word(&format!("r#{}", name))?; + } else { + self.s.word(&name.as_str())?; + } self.ann.post(self, NodeName(&name)) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 7798a7a77ee6c..e2dfca5d10a3c 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -142,6 +142,13 @@ pub fn is_path_segment_keyword(id: ast::Ident) -> bool { id.name == keywords::DollarCrate.name() } +// We see this identifier in a normal identifier position, like variable name or a type. +// How was it written originally? Did it use the raw form? Let's try to guess. +pub fn is_raw_guess(ident: ast::Ident) -> bool { + ident.name != keywords::Invalid.name() && + is_reserved_ident(ident) && !is_path_segment_keyword(ident) +} + // Returns true for reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(id: ast::Ident) -> bool { @@ -236,7 +243,7 @@ impl Token { /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary. pub fn from_ast_ident(ident: ast::Ident) -> Token { - Ident(ident, is_reserved_ident(ident) && !is_path_segment_keyword(ident)) + Ident(ident, is_raw_guess(ident)) } /// Returns `true` if the token starts with '>'. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 50577a26abf41..ae045fc095a50 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2373,7 +2373,11 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - self.s.word(&ident.name.as_str())?; + if token::is_raw_guess(ident) { + self.s.word(&format!("r#{}", ident))?; + } else { + self.s.word(&ident.name.as_str())?; + } self.ann.post(self, NodeIdent(&ident)) } diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs b/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs index 3566babaf4cbd..6cea75cf1d11e 100644 --- a/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs +++ b/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(raw_identifiers)] use std::mem; diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs b/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs index bd1f52a9b24e0..5d495c4e9e557 100644 --- a/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs +++ b/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(raw_identifiers)] fn r#fn(r#match: u32) -> u32 { diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/items.rs b/src/test/run-pass/rfc-2151-raw-identifiers/items.rs index 5fdc13df8dcb2..256bd263d38d4 100644 --- a/src/test/run-pass/rfc-2151-raw-identifiers/items.rs +++ b/src/test/run-pass/rfc-2151-raw-identifiers/items.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(raw_identifiers)] #[derive(Debug, PartialEq, Eq)] diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs b/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs index 82d44c57e181b..4bd16ded52fbd 100644 --- a/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs +++ b/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty - #![feature(decl_macro)] #![feature(raw_identifiers)] From 9c7b69e17909ceb090a1c4b8882a4e0924a2a755 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 26 Mar 2018 22:24:03 +0100 Subject: [PATCH 20/26] Remove mentions of unstable sort_by_cached key from stable documentation --- src/liballoc/slice.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 2b4ce9fe49c8e..68f2313843c31 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1306,10 +1306,6 @@ impl [T] { /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log(m n))` /// worst-case, where the key function is `O(m)`. /// - /// For expensive key functions (e.g. functions that are not simple property accesses or - /// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be - /// significantly faster, as it does not recompute element keys. - /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). @@ -1496,10 +1492,6 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// Due to its key calling strategy, [`sort_unstable_by_key`](#method.sort_unstable_by_key) - /// is likely to be slower than [`sort_by_cached_key`](#method.sort_by_cached_key) in - /// cases where the key function is expensive. - /// /// # Examples /// /// ``` From 604bbee84cbd0ef5064bfd6b40c384268b1b38c0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 27 Mar 2018 00:45:28 +0300 Subject: [PATCH 21/26] libsyntax: Remove obsolete.rs --- src/libsyntax/parse/mod.rs | 1 - src/libsyntax/parse/obsolete.rs | 67 --------------------------------- src/libsyntax/parse/parser.rs | 6 --- 3 files changed, 74 deletions(-) delete mode 100644 src/libsyntax/parse/obsolete.rs diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 7b39db16ac2c8..1483691a1eaee 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -40,7 +40,6 @@ pub mod attr; pub mod common; pub mod classify; -pub mod obsolete; /// Info about a parsing session. pub struct ParseSess { diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs deleted file mode 100644 index 49a697edf4164..0000000000000 --- a/src/libsyntax/parse/obsolete.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012-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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of -//! these syntaxes is tested by compile-test/obsolete-syntax.rs. -//! -//! Obsolete syntax that becomes too hard to parse can be removed. - -use syntax_pos::Span; -use parse::parser; - -/// The specific types of unsupported syntax -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub enum ObsoleteSyntax { - // Nothing here at the moment -} - -pub trait ParserObsoleteMethods { - /// Reports an obsolete syntax non-fatal error. - fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax); - fn report(&mut self, - sp: Span, - kind: ObsoleteSyntax, - kind_str: &str, - desc: &str, - error: bool); -} - -impl<'a> ParserObsoleteMethods for parser::Parser<'a> { - /// Reports an obsolete syntax non-fatal error. - #[allow(unused_variables)] - #[allow(unreachable_code)] - fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { - let (kind_str, desc, error) = match kind { - // Nothing here at the moment - }; - - self.report(sp, kind, kind_str, desc, error); - } - - fn report(&mut self, - sp: Span, - kind: ObsoleteSyntax, - kind_str: &str, - desc: &str, - error: bool) { - let mut err = if error { - self.diagnostic().struct_span_err(sp, &format!("obsolete syntax: {}", kind_str)) - } else { - self.diagnostic().struct_span_warn(sp, &format!("obsolete syntax: {}", kind_str)) - }; - - if !self.obsolete_set.contains(&kind) && - (error || self.sess.span_diagnostic.flags.can_emit_warnings) { - err.note(desc); - self.obsolete_set.insert(kind); - } - err.emit(); - } -} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 98e2528d30f24..b4b21285d3b2b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,7 +48,6 @@ use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use parse::obsolete::ObsoleteSyntax; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; @@ -59,7 +58,6 @@ use symbol::{Symbol, keywords}; use util::ThinVec; use std::cmp; -use std::collections::HashSet; use std::mem; use std::path::{self, Path, PathBuf}; use std::slice; @@ -229,9 +227,6 @@ pub struct Parser<'a> { /// the previous token kind prev_token_kind: PrevTokenKind, pub restrictions: Restrictions, - /// The set of seen errors about obsolete syntax. Used to suppress - /// extra detail when the same error is seen twice - pub obsolete_set: HashSet, /// Used to determine the path to externally loaded source files pub directory: Directory, /// Whether to parse sub-modules in other files. @@ -555,7 +550,6 @@ impl<'a> Parser<'a> { meta_var_span: None, prev_token_kind: PrevTokenKind::Other, restrictions: Restrictions::empty(), - obsolete_set: HashSet::new(), recurse_into_file_modules, directory: Directory { path: PathBuf::new(), From 0f1c649827108e11313376d2ea6cec7c9e8feb7c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 26 Mar 2018 16:20:11 -0700 Subject: [PATCH 22/26] Fix diagnostic colors on Windows 10 console. This updates termcolor to pick up BurntSushi/ripgrep#867. Fixes #49322. --- src/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c4707707be084..ad745d29e15e9 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -202,7 +202,7 @@ dependencies = [ "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -558,7 +558,7 @@ dependencies = [ "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1543,7 +1543,7 @@ dependencies = [ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1721,7 +1721,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2326,7 +2326,7 @@ dependencies = [ [[package]] name = "termcolor" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2765,7 +2765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" -"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1" +"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" From 554dd3e350721a7064932719ec925d1a1b5eb552 Mon Sep 17 00:00:00 2001 From: Alexis Hunt Date: Mon, 26 Mar 2018 21:18:50 -0400 Subject: [PATCH 23/26] Add missing '?' to format grammar. --- src/liballoc/fmt.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index a092bfb3b0a8a..c69c2cd98c8c4 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -324,7 +324,7 @@ //! sign := '+' | '-' //! width := count //! precision := count | '*' -//! type := identifier | '' +//! type := identifier | '?' | '' //! count := parameter | integer //! parameter := argument '$' //! ``` @@ -514,17 +514,17 @@ pub use core::fmt::rt; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Formatter, Result, Write}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{Octal, Binary}; +pub use core::fmt::{Binary, Octal}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{Display, Debug}; +pub use core::fmt::{Debug, Display}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{LowerHex, UpperHex, Pointer}; +pub use core::fmt::{LowerHex, Pointer, UpperHex}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{LowerExp, UpperExp}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{ArgumentV1, Arguments, write}; +pub use core::fmt::{write, ArgumentV1, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; @@ -561,7 +561,8 @@ use string; pub fn format(args: Arguments) -> string::String { let capacity = args.estimated_capacity(); let mut output = string::String::with_capacity(capacity); - output.write_fmt(args) - .expect("a formatting trait implementation returned an error"); + output + .write_fmt(args) + .expect("a formatting trait implementation returned an error"); output } From 6313997e3eede7107614adcb622b41ce8f5bcd95 Mon Sep 17 00:00:00 2001 From: Wangshan Lu Date: Tue, 27 Mar 2018 16:47:50 +0800 Subject: [PATCH 24/26] Add back 1.24.1 release notes --- RELEASES.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 51c36c99858b8..100de005990c9 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -98,6 +98,20 @@ Compatibility Notes [`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html +Version 1.24.1 (2018-03-01) +========================== + + - [Do not abort when unwinding through FFI][48251] + - [Emit UTF-16 files for linker arguments on Windows][48318] + - [Make the error index generator work again][48308] + - [Cargo will warn on Windows 7 if an update is needed][cargo/5069]. + +[48251]: https://github.com/rust-lang/rust/issues/48251 +[48308]: https://github.com/rust-lang/rust/issues/48308 +[48318]: https://github.com/rust-lang/rust/issues/48318 +[cargo/5069]: https://github.com/rust-lang/cargo/pull/5069 + + Version 1.24.0 (2018-02-15) ========================== From 5b1a60062c8882dbf60853037e4e8908b6ce7ec7 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Tue, 27 Mar 2018 15:32:06 +0200 Subject: [PATCH 25/26] Update compiler-rt with fix for 32bit iOS ARM --- src/libcompiler_builtins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 263a703b10351..2a2f6d96c8dc5 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 263a703b10351d8930e48045b4fd09768991b867 +Subproject commit 2a2f6d96c8dc578d2474742f14c9bab0b36b0408 From f513fbdf36ad0708fb222b8d55bc086dd4be18cf Mon Sep 17 00:00:00 2001 From: lukaslueg Date: Tue, 27 Mar 2018 20:56:15 +0200 Subject: [PATCH 26/26] Update CONTRIBUTING.md The current link is a 404, just link to the main repo page --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b389888e5185..7a62405f05967 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -594,7 +594,7 @@ If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy [lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc -[rfcbot]: https://github.com/dikaiosune/rust-dashboard/blob/master/RFCBOT.md +[rfcbot]: https://github.com/anp/rfcbot-rs/ ## Out-of-tree Contributions [out-of-tree-contributions]: #out-of-tree-contributions