diff --git a/README.md b/README.md index dc9362ca2f0b8..fca7d1cc5bd3c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Read ["Installing Rust"] from [The Book]. 1. Make sure you have installed the dependencies: - * `g++` 4.7 or later or `clang++` 3.x + * `g++` 4.7 or later or `clang++` 3.x or later * `python` 2.7 (but not 3.x) * GNU `make` 3.81 or later * `cmake` 3.4.3 or later diff --git a/appveyor.yml b/appveyor.yml index 499f7d602e368..0e7ebf12a2a91 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,14 +43,14 @@ environment: # *not* use debug assertions and llvm assertions. This is because they take # too long on appveyor and this is tested by rustbuild below. - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja SCRIPT: python x.py test MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z MINGW_DIR: mingw32 - MSYS_BITS: 64 SCRIPT: python x.py test - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z MINGW_DIR: mingw64 @@ -68,7 +68,7 @@ environment: SCRIPT: python x.py dist DEPLOY: 1 - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja SCRIPT: python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z @@ -76,7 +76,7 @@ environment: DEPLOY: 1 - MSYS_BITS: 64 SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z MINGW_DIR: mingw64 @@ -116,9 +116,16 @@ install: # Download and install sccache - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-pc-windows-msvc - - mv 2017-03-16-sccache-x86_64-pc-windows-msvc sccache + - mv 2017-03-16-sccache-x86_64-pc-windows-msvc sccache.exe - set PATH=%PATH%;%CD% + # Download and install ninja + # + # Note that this is originally from the github releases patch of Ninja + - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-15-ninja-win.zip + - 7z x 2017-03-15-ninja-win.zip + # - set PATH=%PATH%;%CD% -- this already happens above for sccache + # Install InnoSetup to get `iscc` used to produce installers - appveyor-retry choco install -y InnoSetup - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b1d1d79b9eaa3..52ebf401aefd6 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,7 +23,7 @@ use std::process; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; -use util::push_exe_path; +use util::{exe, push_exe_path}; /// Global configuration for the entire build and/or bootstrap. /// @@ -584,10 +584,10 @@ impl Config { self.python = Some(path); } "CFG_ENABLE_CCACHE" if value == "1" => { - self.ccache = Some("ccache".to_string()); + self.ccache = Some(exe("ccache", &self.build)); } "CFG_ENABLE_SCCACHE" if value == "1" => { - self.ccache = Some("sccache".to_string()); + self.ccache = Some(exe("sccache", &self.build)); } "CFG_CONFIGURE_ARGS" if value.len() > 0 => { self.configure_args = value.split_whitespace() diff --git a/src/doc/book b/src/doc/book index e6d6caab41471..9bd223ca406b1 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit e6d6caab41471f7115a621029bd428a812c5260e +Subproject commit 9bd223ca406b1170a24942d6474f9e8a56f4a420 diff --git a/src/doc/unstable-book/src/sort-unstable.md b/src/doc/unstable-book/src/sort-unstable.md index aec39de2c9a73..9effcfc774c77 100644 --- a/src/doc/unstable-book/src/sort-unstable.md +++ b/src/doc/unstable-book/src/sort-unstable.md @@ -6,4 +6,35 @@ The tracking issue for this feature is: [#40585] ------------------------ +The default `sort` method on slices is stable. In other words, it guarantees +that the original order of equal elements is preserved after sorting. The +method has several undesirable characteristics: +1. It allocates a sizable chunk of memory. +2. If you don't need stability, it is not as performant as it could be. + +An alternative is the new `sort_unstable` feature, which includes these +methods for sorting slices: + +1. `sort_unstable` +2. `sort_unstable_by` +3. `sort_unstable_by_key` + +Unstable sorting is generally faster and makes no allocations. The majority +of real-world sorting needs doesn't require stability, so these methods can +very often come in handy. + +Another important difference is that `sort` lives in `libstd` and +`sort_unstable` lives in `libcore`. The reason is that the former makes +allocations and the latter doesn't. + +A simple example: + +```rust +#![feature(sort_unstable)] + +let mut v = [-5, 4, 1, -3, 2]; + +v.sort_unstable(); +assert!(v == [-5, -3, 1, 2, 4]); +``` diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 519117ff9e519..efa96ca468e01 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -930,13 +930,13 @@ impl<'a, T> Hole<'a, T> { self.pos } - /// Return a reference to the element removed + /// Returns a reference to the element removed. #[inline] fn element(&self) -> &T { self.elt.as_ref().unwrap() } - /// Return a reference to the element at `index`. + /// Returns a reference to the element at `index`. /// /// Unsafe because index must be within the data slice and not equal to pos. #[inline] diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 53fe6b4bc9f4f..bed216ba3d111 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -526,7 +526,7 @@ impl BTreeMap { } } - /// Returns true if the map contains a value for the specified key. + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. @@ -1965,7 +1965,7 @@ impl BTreeMap { self.length } - /// Returns true if the map contains no elements. + /// Returns `true` if the map contains no elements. /// /// # Examples /// diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 72d25f87bca95..9dbb61379379e 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -415,7 +415,7 @@ impl BTreeSet { self.map.len() } - /// Returns true if the set contains no elements. + /// Returns `true` if the set contains no elements. /// /// # Examples /// diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 602e874aaeec0..e56b94b2e1ea2 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -106,7 +106,7 @@ impl EnumSet { self.bits.count_ones() as usize } - /// Returns true if the `EnumSet` is empty. + /// Returns `true` if the `EnumSet` is empty. pub fn is_empty(&self) -> bool { self.bits == 0 } diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index 31e4d001397bf..06d89a6a70b4a 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -20,9 +20,9 @@ use Bound::{self, Excluded, Included, Unbounded}; /// **RangeArgument** is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b` or `c..d`. pub trait RangeArgument { - /// Start index bound + /// Start index bound. /// - /// Return start value as a `Bound` + /// Returns the start value as a `Bound`. /// /// # Examples /// @@ -42,9 +42,9 @@ pub trait RangeArgument { /// ``` fn start(&self) -> Bound<&T>; - /// End index bound + /// End index bound. /// - /// Return end value as a `Bound` + /// Returns the end value as a `Bound`. /// /// # Examples /// diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 5233887620a91..d3723ace9efb3 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -195,7 +195,7 @@ impl [T] { core_slice::SliceExt::is_empty(self) } - /// Returns the first element of a slice, or `None` if it is empty. + /// Returns the first element of the slice, or `None` if it is empty. /// /// # Examples /// @@ -212,7 +212,7 @@ impl [T] { core_slice::SliceExt::first(self) } - /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty. + /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. /// /// # Examples /// @@ -230,7 +230,7 @@ impl [T] { core_slice::SliceExt::first_mut(self) } - /// Returns the first and all the rest of the elements of a slice, or `None` if it is empty. + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. /// /// # Examples /// @@ -248,7 +248,7 @@ impl [T] { core_slice::SliceExt::split_first(self) } - /// Returns the first and all the rest of the elements of a slice, or `None` if it is empty. + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. /// /// # Examples /// @@ -268,7 +268,7 @@ impl [T] { core_slice::SliceExt::split_first_mut(self) } - /// Returns the last and all the rest of the elements of a slice, or `None` if it is empty. + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. /// /// # Examples /// @@ -287,7 +287,7 @@ impl [T] { } - /// Returns the last and all the rest of the elements of a slice, or `None` if it is empty. + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. /// /// # Examples /// @@ -307,7 +307,7 @@ impl [T] { core_slice::SliceExt::split_last_mut(self) } - /// Returns the last element of a slice, or `None` if it is empty. + /// Returns the last element of the slice, or `None` if it is empty. /// /// # Examples /// @@ -485,7 +485,7 @@ impl [T] { core_slice::SliceExt::as_mut_ptr(self) } - /// Swaps two elements in a slice. + /// Swaps two elements in the slice. /// /// # Arguments /// @@ -509,7 +509,7 @@ impl [T] { core_slice::SliceExt::swap(self, a, b) } - /// Reverses the order of elements in a slice, in place. + /// Reverses the order of elements in the slice, in place. /// /// # Example /// @@ -955,7 +955,7 @@ impl [T] { core_slice::SliceExt::ends_with(self, needle) } - /// Binary search a sorted slice for a given element. + /// Binary searches this 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 @@ -984,7 +984,7 @@ impl [T] { core_slice::SliceExt::binary_search(self, x) } - /// Binary search a sorted slice with a comparator function. + /// Binary searches this sorted slice with a comparator function. /// /// The comparator function should implement an order consistent /// with the sort order of the underlying slice, returning an @@ -1023,7 +1023,7 @@ impl [T] { core_slice::SliceExt::binary_search_by(self, f) } - /// Binary search a sorted slice with a key extraction function. + /// Binary searches this sorted slice with a key extraction function. /// /// Assumes that the slice is sorted by the key, for instance with /// [`sort_by_key`] using the same key extraction function. @@ -1092,7 +1092,7 @@ impl [T] { merge_sort(self, |a, b| a.lt(b)); } - /// Sorts the slice using `compare` to compare elements. + /// Sorts the slice with a comparator function. /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// @@ -1125,7 +1125,7 @@ impl [T] { merge_sort(self, |a, b| compare(a, b) == Less); } - /// Sorts the slice using `f` to extract a key to compare elements by. + /// 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. /// @@ -1191,8 +1191,8 @@ impl [T] { core_slice::SliceExt::sort_unstable(self); } - /// Sorts the slice using `compare` to compare elements, but may not preserve the order of - /// equal elements. + /// Sorts the slice with a comparator function, but may not preserve the order of equal + /// elements. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), /// and `O(n log n)` worst-case. @@ -1231,8 +1231,8 @@ impl [T] { core_slice::SliceExt::sort_unstable_by(self, compare); } - /// Sorts the slice using `f` to extract a key to compare elements by, but may not preserve the - /// order of equal elements. + /// Sorts the slice with a key extraction function, but may not preserve the order of equal + /// elements. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), /// and `O(n log n)` worst-case. @@ -1313,7 +1313,6 @@ impl [T] { core_slice::SliceExt::copy_from_slice(self, src) } - /// Copies `self` into a new `Vec`. /// /// # Examples diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 90e54a383d623..8abc9ca7e9fe8 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -204,7 +204,7 @@ impl str { core_str::StrExt::len(self) } - /// Returns true if this slice has a length of zero bytes. + /// Returns `true` if `self` has a length of zero bytes. /// /// # Examples /// diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 6a04d47a345e8..cb92236ec736c 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -133,7 +133,7 @@ impl VecDeque { ptr::write(self.ptr().offset(off as isize), value); } - /// Returns true if and only if the buffer is at capacity + /// Returns `true` if and only if the buffer is at full capacity. #[inline] fn is_full(&self) -> bool { self.cap() - self.len() == 1 @@ -788,7 +788,7 @@ impl VecDeque { count(self.tail, self.head, self.cap()) } - /// Returns true if the buffer contains no elements + /// Returns `true` if the `VecDeque` is empty. /// /// # Examples /// diff --git a/src/libcore/any.rs b/src/libcore/any.rs index b8a4174766a78..338e5c7fd95b4 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -137,7 +137,7 @@ impl fmt::Debug for Any + Send { } impl Any { - /// Returns true if the boxed type is the same as `T`. + /// Returns `true` if the boxed type is the same as `T`. /// /// # Examples /// diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index cb39796eecd7d..7db35359a1f7d 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -210,7 +210,7 @@ pub enum Ordering { } impl Ordering { - /// Reverse the `Ordering`. + /// Reverses the `Ordering`. /// /// * `Less` becomes `Greater`. /// * `Greater` becomes `Less`. @@ -616,7 +616,7 @@ pub trait PartialOrd: PartialEq { } } -/// Compare and return the minimum of two values. +/// Compares and returns the minimum of two values. /// /// Returns the first argument if the comparison determines them to be equal. /// @@ -634,7 +634,7 @@ pub fn min(v1: T, v2: T) -> T { if v1 <= v2 { v1 } else { v2 } } -/// Compare and return the maximum of two values. +/// Compares and returns the maximum of two values. /// /// Returns the second argument if the comparison determines them to be equal. /// diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index fb98e43aa614b..618edf48abd04 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -518,13 +518,13 @@ pub trait Iterator { /// Creates an iterator that both filters and maps. /// - /// The closure must return an [`Option`]. `filter_map()` creates an + /// The closure must return an [`Option`]. `filter_map` creates an /// iterator which calls this closure on each element. If the closure /// returns [`Some(element)`][`Some`], then that element is returned. If the /// closure returns [`None`], it will try again, and call the closure on the /// next element, seeing if it will return [`Some`]. /// - /// Why `filter_map()` and not just [`filter()`].[`map`]? The key is in this + /// Why `filter_map` and not just [`filter`].[`map`]? The key is in this /// part: /// /// [`filter`]: #method.filter @@ -534,7 +534,7 @@ pub trait Iterator { /// /// In other words, it removes the [`Option`] layer automatically. If your /// mapping is already returning an [`Option`] and you want to skip over - /// [`None`]s, then `filter_map()` is much, much nicer to use. + /// [`None`]s, then `filter_map` is much, much nicer to use. /// /// # Examples /// diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs index bc1aaa09f3dbd..c4d54d2c7b81d 100644 --- a/src/libcore/iter_private.rs +++ b/src/libcore/iter_private.rs @@ -22,7 +22,7 @@ #[doc(hidden)] pub unsafe trait TrustedRandomAccess : ExactSizeIterator { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; - /// Return `true` if getting an iterator element may have + /// Returns `true` if getting an iterator element may have /// side effects. Remember to take inner iterators into account. fn may_have_side_effect() -> bool; } diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index a1f4630c304bf..8904322ca48f7 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -148,14 +148,14 @@ macro_rules! define_bignum { $name { size: sz, base: base } } - /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric + /// Returns the internal digits as a slice `[a, b, c, ...]` such that the numeric /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in /// the digit type. pub fn digits(&self) -> &[$ty] { &self.base[..self.size] } - /// Return the `i`-th bit where bit 0 is the least significant one. + /// Returns the `i`-th bit where bit 0 is the least significant one. /// In other words, the bit with weight `2^i`. pub fn get_bit(&self, i: usize) -> u8 { use mem; @@ -166,7 +166,7 @@ macro_rules! define_bignum { ((self.base[d] >> b) & 1) as u8 } - /// Returns true if the bignum is zero. + /// Returns `true` if the bignum is zero. pub fn is_zero(&self) -> bool { self.digits().iter().all(|&v| v == 0) } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ccfe6364e6af6..df343c9d45f20 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2568,17 +2568,17 @@ pub trait Float: Sized { implementable outside the standard library")] fn one() -> Self; - /// Returns true if this value is NaN and false otherwise. + /// Returns `true` if this value is NaN and false otherwise. #[stable(feature = "core", since = "1.6.0")] fn is_nan(self) -> bool; - /// Returns true if this value is positive infinity or negative infinity and + /// Returns `true` if this value is positive infinity or negative infinity and /// false otherwise. #[stable(feature = "core", since = "1.6.0")] fn is_infinite(self) -> bool; - /// Returns true if this number is neither infinite nor NaN. + /// Returns `true` if this number is neither infinite nor NaN. #[stable(feature = "core", since = "1.6.0")] fn is_finite(self) -> bool; - /// Returns true if this number is neither zero, infinite, denormal, or NaN. + /// Returns `true` if this number is neither zero, infinite, denormal, or NaN. #[stable(feature = "core", since = "1.6.0")] fn is_normal(self) -> bool; /// Returns the category that this number falls into. diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 98544f8ba5e73..d2830a6d00cec 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -380,7 +380,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { #[lang = "const_ptr"] impl *const T { - /// Returns true if the pointer is null. + /// Returns `true` if the pointer is null. /// /// # Examples /// @@ -504,7 +504,7 @@ impl *const T { #[lang = "mut_ptr"] impl *mut T { - /// Returns true if the pointer is null. + /// Returns `true` if the pointer is null. /// /// # Examples /// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 00ff2fd2ce5ef..6ec8a37dfa433 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -268,7 +268,7 @@ impl Result { // Querying the contained values ///////////////////////////////////////////////////////////////////////// - /// Returns true if the result is `Ok`. + /// Returns `true` if the result is `Ok`. /// /// # Examples /// @@ -290,7 +290,7 @@ impl Result { } } - /// Returns true if the result is `Err`. + /// Returns `true` if the result is `Err`. /// /// # Examples /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 6f8b199f886b7..af492b3c63976 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1511,7 +1511,7 @@ fn ptrdistance(start: *const T, end: *const T) -> usize { trait PointerExt : Copy { unsafe fn slice_offset(self, i: isize) -> Self; - /// Increment self by 1, but return the old value + /// Increments `self` by 1, but returns the old value. #[inline(always)] unsafe fn post_inc(&mut self) -> Self { let current = *self; @@ -1519,7 +1519,7 @@ trait PointerExt : Copy { current } - /// Decrement self by 1, and return the new value + /// Decrements `self` by 1, and returns the new value. #[inline(always)] unsafe fn pre_dec(&mut self) -> Self { *self = self.slice_offset(-1); @@ -1545,7 +1545,7 @@ impl PointerExt for *mut T { /// splitn, splitn_mut etc can be implemented once. #[doc(hidden)] trait SplitIter: DoubleEndedIterator { - /// Mark the underlying iterator as complete, extracting the remaining + /// Marks the underlying iterator as complete, extracting the remaining /// portion of the slice. fn finish(&mut self) -> Option; } @@ -2267,11 +2267,11 @@ pub fn heapsort(v: &mut [T], mut is_less: F) // extern { - /// Call implementation provided memcmp + /// Calls implementation provided memcmp. /// /// Interprets the data as u8. /// - /// Return 0 for equal, < 0 for less than and > 0 for greater + /// Returns 0 for equal, < 0 for less than and > 0 for greater /// than. // FIXME(#32610): Return type should be c_int fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index fdfba33f8a9d9..d13d537d99301 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -104,7 +104,7 @@ fn shift_tail(v: &mut [T], is_less: &mut F) /// Partially sorts a slice by shifting several out-of-order elements around. /// -/// Returns true if the slice is sorted at the end. This function is `O(n)` worst-case. +/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case. #[cold] fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool where F: FnMut(&T, &T) -> bool @@ -528,7 +528,7 @@ fn break_patterns(v: &mut [T]) { } } -/// Chooses a pivot in `v` and returns the index and true if the slice is likely already sorted. +/// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted. /// /// Elements in `v` might be reordered in the process. fn choose_pivot(v: &mut [T], is_less: &mut F) -> (usize, bool) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index cf3e8a684dfab..dfb6936da6bda 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -332,7 +332,7 @@ impl fmt::Display for Utf8Error { Section: Iterators */ -/// Iterator for the char (representing *Unicode Scalar Values*) of a string +/// Iterator for the char (representing *Unicode Scalar Values*) of a string. /// /// Created with the method [`chars`]. /// @@ -343,13 +343,13 @@ pub struct Chars<'a> { iter: slice::Iter<'a, u8> } -/// Return the initial codepoint accumulator for the first byte. +/// Returns the initial codepoint accumulator for the first byte. /// The first byte is special, only want bottom 5 bits for width 2, 4 bits /// for width 3, and 3 bits for width 4. #[inline] fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 } -/// Return the value of `ch` updated with continuation byte `byte`. +/// Returns the value of `ch` updated with continuation byte `byte`. #[inline] fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 } @@ -1244,13 +1244,13 @@ Section: UTF-8 validation // use truncation to fit u64 into usize const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; -/// Return `true` if any byte in the word `x` is nonascii (>= 128). +/// Returns `true` if any byte in the word `x` is nonascii (>= 128). #[inline] fn contains_nonascii(x: usize) -> bool { (x & NONASCII_MASK) != 0 } -/// Walk through `iter` checking that it's a valid UTF-8 sequence, +/// Walks through `iter` checking that it's a valid UTF-8 sequence, /// returning `true` in that case, or, if it is invalid, `false` with /// `iter` reset such that it is pointing at the first byte in the /// invalid sequence. @@ -1389,16 +1389,16 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [ 4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF ]; -/// Given a first byte, determine how many bytes are in this UTF-8 character +/// Given a first byte, determines how many bytes are in this UTF-8 character. #[unstable(feature = "str_internals", issue = "0")] #[inline] pub fn utf8_char_width(b: u8) -> usize { return UTF8_CHAR_WIDTH[b as usize] as usize; } -/// Mask of the value bits of a continuation byte +/// Mask of the value bits of a continuation byte. const CONT_MASK: u8 = 0b0011_1111; -/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte +/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte. const TAG_CONT_U8: u8 = 0b1000_0000; /* diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index aedb8fef2885c..7bab4a8d725dc 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -12,6 +12,7 @@ use hir::def_id::DefId; use util::nodemap::NodeMap; use syntax::ast; use syntax::ext::base::MacroKind; +use syntax_pos::Span; use hir; #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -116,6 +117,7 @@ pub type ExportMap = NodeMap>; pub struct Export { pub name: ast::Name, // The name of the target. pub def: Def, // The definition of the target. + pub span: Span, // The span of the target definition. } impl CtorKind { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b4b9966cbe47b..c2ad598b0c503 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -683,7 +683,7 @@ impl<'a, 'tcx> CrateMetadata { }, ext.kind() ); - callback(def::Export { name: name, def: def }); + callback(def::Export { name: name, def: def, span: DUMMY_SP }); } } return @@ -720,6 +720,7 @@ impl<'a, 'tcx> CrateMetadata { callback(def::Export { def: def, name: self.item_name(child_index), + span: self.entry(child_index).span.decode(self), }); } } @@ -732,12 +733,10 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); + let span = child.span.decode(self); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { - callback(def::Export { - def: def, - name: name, - }); + callback(def::Export { def: def, name: name, span: span }); // For non-reexport structs and variants add their constructors to children. // Reexport lists automatically contain constructors when necessary. match def { @@ -745,10 +744,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) { let ctor_kind = self.get_ctor_kind(child_index); let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind); - callback(def::Export { - def: ctor_def, - name: name, - }); + callback(def::Export { def: ctor_def, name: name, span: span }); } } Def::Variant(def_id) => { @@ -756,10 +752,7 @@ impl<'a, 'tcx> CrateMetadata { // value namespace, they are reserved for possible future use. let ctor_kind = self.get_ctor_kind(child_index); let ctor_def = Def::VariantCtor(def_id, ctor_kind); - callback(def::Export { - def: ctor_def, - name: name, - }); + callback(def::Export { def: ctor_def, name: name, span: span }); } _ => {} } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index be905a9d0f94a..c33d5b9b6e16b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -605,7 +605,7 @@ impl<'a> Resolver<'a> { let ident = Ident::with_empty_ctxt(name); let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); if let Ok(binding) = result { - self.macro_exports.push(Export { name: name, def: binding.def() }); + self.macro_exports.push(Export { name: name, def: binding.def(), span: span }); } else { span_err!(self.session, span, E0470, "reexported macro not found"); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f83413095934d..99fc1c142f681 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -653,7 +653,7 @@ impl<'a> Resolver<'a> { if attr::contains_name(&item.attrs, "macro_export") { let def = Def::Macro(def_id, MacroKind::Bang); - self.macro_exports.push(Export { name: ident.name, def: def }); + self.macro_exports.push(Export { name: ident.name, def: def, span: item.span }); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index dbc8bca548b76..2f4ac12cd7363 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,7 +21,7 @@ use rustc::ty; use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def_id::DefId; use rustc::hir::def::*; -use rustc::util::nodemap::FxHashSet; +use rustc::util::nodemap::FxHashMap; use syntax::ast::{Ident, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; @@ -763,10 +763,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { *module.globs.borrow_mut() = Vec::new(); let mut reexports = Vec::new(); + let mut exported_macro_names = FxHashMap(); if module as *const _ == self.graph_root as *const _ { - let mut exported_macro_names = FxHashSet(); - for export in mem::replace(&mut self.macro_exports, Vec::new()).into_iter().rev() { - if exported_macro_names.insert(export.name) { + let macro_exports = mem::replace(&mut self.macro_exports, Vec::new()); + for export in macro_exports.into_iter().rev() { + if exported_macro_names.insert(export.name, export.span).is_none() { reexports.push(export); } } @@ -786,7 +787,17 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !def.def_id().is_local() { self.session.cstore.export_macros(def.def_id().krate); } - reexports.push(Export { name: ident.name, def: def }); + if let Def::Macro(..) = def { + if let Some(&span) = exported_macro_names.get(&ident.name) { + let msg = + format!("a macro named `{}` has already been exported", ident); + self.session.struct_span_err(span, &msg) + .span_label(span, &format!("`{}` already exported", ident)) + .span_note(binding.span, "previous macro export here") + .emit(); + } + } + reexports.push(Export { name: ident.name, def: def, span: binding.span }); } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 644e323a8dbf2..0136faef28d8c 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1223,6 +1223,28 @@ fn main() { ``` "##, +E0090: r##" +You gave too few lifetime parameters. Example: + +```compile_fail,E0090 +fn foo<'a: 'b, 'b: 'a>() {} + +fn main() { + foo::<'static>(); // error, expected 2 lifetime parameters +} +``` + +Please check you give the right number of lifetime parameters. Example: + +``` +fn foo<'a: 'b, 'b: 'a>() {} + +fn main() { + foo::<'static, 'static>(); +} +``` +"##, + E0091: r##" You gave an unnecessary type parameter in a type alias. Erroneous code example: @@ -4120,7 +4142,6 @@ register_diagnostics! { // E0068, // E0085, // E0086, - E0090, E0103, // @GuillaumeGomez: I was unable to get this error, try your best! E0104, // E0123, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a255ba0ad4edf..9f2d02c14dde0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1096,9 +1096,9 @@ impl fmt::Display for clean::ImportSource { impl fmt::Display for clean::TypeBinding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if f.alternate() { - write!(f, "{}={:#}", self.name, self.ty) + write!(f, "{} = {:#}", self.name, self.ty) } else { - write!(f, "{}={}", self.name, self.ty) + write!(f, "{} = {}", self.name, self.ty) } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 7b60d497932de..10fde67a45674 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2808,7 +2808,7 @@ fn render_assoc_items(w: &mut fmt::Formatter, } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { write!(w, "

Methods from \ - {}<Target={}>

", trait_, type_)?; + {}<Target = {}>", trait_, type_)?; RenderMode::ForDeref { mut_: deref_mut_ } } }; diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 40561597e93e0..74ec3691b3860 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -45,14 +45,6 @@ pre { background-color: #fff; } -.sidebar { - background-color: #F1F1F1; -} - -.sidebar .current { - background-color: #fff; -} - .sidebar .location { border-color: #000; background-color: #fff; diff --git a/src/test/compile-fail/duplicate-check-macro-exports.rs b/src/test/compile-fail/duplicate-check-macro-exports.rs new file mode 100644 index 0000000000000..53d7e54ee5b7b --- /dev/null +++ b/src/test/compile-fail/duplicate-check-macro-exports.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +#![feature(use_extern_macros)] + +pub use std::panic; //~ NOTE previous macro export here + +#[macro_export] +macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported +//~| NOTE `panic` already exported + +fn main() {} diff --git a/src/test/run-pass/macro-nested_definition_issue-31946.rs b/src/test/run-pass/macro-nested_definition_issue-31946.rs new file mode 100644 index 0000000000000..84ff2dc4d0d61 --- /dev/null +++ b/src/test/run-pass/macro-nested_definition_issue-31946.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +fn main() { + println!("{}", { + macro_rules! foo { + ($name:expr) => { concat!("hello ", $name) } + } + foo!("rust") + }); +} diff --git a/src/test/rustdoc/doc-assoc-item.rs b/src/test/rustdoc/doc-assoc-item.rs new file mode 100644 index 0000000000000..36f44295953f0 --- /dev/null +++ b/src/test/rustdoc/doc-assoc-item.rs @@ -0,0 +1,28 @@ +// Copyright 2017 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. + +pub struct Foo { + x: T, +} + +pub trait Bar { + type Fuu; + + fn foo(foo: Self::Fuu); +} + +// @has doc_assoc_item/struct.Foo.html '//*[@class="impl"]' 'impl> Foo' +impl> Foo { + pub fn new(t: T) -> Foo { + Foo { + x: t, + } + } +} diff --git a/src/test/rustdoc/issue-20646.rs b/src/test/rustdoc/issue-20646.rs index 87c40d1157974..49fac20035fc0 100644 --- a/src/test/rustdoc/issue-20646.rs +++ b/src/test/rustdoc/issue-20646.rs @@ -23,7 +23,7 @@ pub trait Trait { } // @has issue_20646/fn.fun.html \ -// '//*[@class="rust fn"]' 'where T: Trait' +// '//*[@class="rust fn"]' 'where T: Trait' pub fn fun(_: T) where T: Trait {} pub mod reexport { @@ -31,6 +31,6 @@ pub mod reexport { // '//*[@id="associatedtype.Output"]' \ // 'type Output' // @has issue_20646/reexport/fn.fun.html \ - // '//*[@class="rust fn"]' 'where T: Trait' + // '//*[@class="rust fn"]' 'where T: Trait' pub use issue_20646::{Trait, fun}; } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 5a97f7e3ee9b5..657739c65b1f5 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -486,11 +486,9 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn } fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { - let stamp_name = format!("{}-H-{}-T-{}-S-{}.stamp", + let stamp_name = format!("{}-{}.stamp", testpaths.file.file_name().unwrap() .to_str().unwrap(), - config.host, - config.target, config.stage_id); config.build_base.canonicalize() .unwrap_or(config.build_base.clone())