From 7c442e5c9b46de225f8903352b7dfc5552b297de Mon Sep 17 00:00:00 2001 From: Murarth Date: Wed, 21 Mar 2018 10:47:03 -0700 Subject: [PATCH 01/16] Stabilize method `String::retain` --- .../src/library-features/string-retain.md | 23 ------------------- src/liballoc/string.rs | 4 +--- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/string-retain.md diff --git a/src/doc/unstable-book/src/library-features/string-retain.md b/src/doc/unstable-book/src/library-features/string-retain.md deleted file mode 100644 index 049444aa49bdd..0000000000000 --- a/src/doc/unstable-book/src/library-features/string-retain.md +++ /dev/null @@ -1,23 +0,0 @@ -# `string_retain` - -The tracking issue for this feature is: [#43874] - -[#43874]: https://github.com/rust-lang/rust/issues/43874 - ------------------------- - -Retains only the characters specified by the predicate. - -In other words, remove all characters `c` such that `f(c)` returns `false`. -This method operates in place and preserves the order of the retained -characters. - -```rust -#![feature(string_retain)] - -let mut s = String::from("f_o_ob_ar"); - -s.retain(|c| c != '_'); - -assert_eq!(s, "foobar"); -``` diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 9fec90914985d..52ff6357c5b73 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1177,8 +1177,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(string_retain)] - /// /// let mut s = String::from("f_o_ob_ar"); /// /// s.retain(|c| c != '_'); @@ -1186,7 +1184,7 @@ impl String { /// assert_eq!(s, "foobar"); /// ``` #[inline] - #[unstable(feature = "string_retain", issue = "43874")] + #[stable(feature = "string_retain", since = "1.26.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(char) -> bool { From 7cae6fef710c4668d650219319a055e8f2157ab5 Mon Sep 17 00:00:00 2001 From: Jimmy Brush Date: Sat, 24 Mar 2018 10:01:46 -0400 Subject: [PATCH 02/16] don't pass -no-pie to gnu ld fixes #48884 --- src/librustc_trans/back/link.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 542cdc5baad32..b2bcbb295cedc 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -712,6 +712,7 @@ fn link_natively(sess: &Session, // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. if sess.target.target.options.linker_is_gnu && + sess.linker_flavor() != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) && out.contains("-no-pie") && @@ -1007,8 +1008,9 @@ fn link_args(cmd: &mut Linker, } else { // recent versions of gcc can be configured to generate position // independent executables by default. We have to pass -no-pie to - // explicitly turn that off. - if sess.target.target.options.linker_is_gnu { + // explicitly turn that off. Not applicable to ld. + if sess.target.target.options.linker_is_gnu + && sess.linker_flavor() != LinkerFlavor::Ld { cmd.no_position_independent_executable(); } } From 04f6692aaf78809c041ba6145bde2dcbeec9725e Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Mon, 26 Mar 2018 23:24:31 +0100 Subject: [PATCH 03/16] Implement `shrink_to` method on collections --- src/liballoc/binary_heap.rs | 25 +++++++++++++++++++ src/liballoc/string.rs | 28 +++++++++++++++++++++ src/liballoc/vec.rs | 27 +++++++++++++++++++- src/liballoc/vec_deque.rs | 35 +++++++++++++++++++++++++- src/libstd/collections/hash/map.rs | 40 ++++++++++++++++++++++++++++++ src/libstd/collections/hash/set.rs | 28 +++++++++++++++++++++ src/libstd/ffi/os_str.rs | 30 ++++++++++++++++++++++ src/libstd/lib.rs | 1 + src/libstd/sys/redox/os_str.rs | 5 ++++ src/libstd/sys/unix/os_str.rs | 5 ++++ src/libstd/sys/wasm/os_str.rs | 5 ++++ src/libstd/sys/windows/os_str.rs | 5 ++++ src/libstd/sys_common/wtf8.rs | 5 ++++ 13 files changed, 237 insertions(+), 2 deletions(-) diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 8aaac5d6e08a5..f6a666b599b09 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -509,6 +509,31 @@ impl BinaryHeap { self.data.shrink_to_fit(); } + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e253122ffd6b6..2bb60a50679e6 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1015,6 +1015,34 @@ impl String { self.vec.shrink_to_fit() } + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + /// Appends the given [`char`] to the end of this `String`. /// /// [`char`]: ../../std/primitive.char.html diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 953f95876be15..c9c6cf1cb6691 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::Ordering; +use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; @@ -586,6 +586,31 @@ impl Vec { self.buf.shrink_to_fit(self.len); } + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Note that this will drop any excess capacity. diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 0658777f0a0e0..be6e8d0f22f07 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -676,9 +676,42 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the `VecDeque` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + // +1 since the ringbuffer always leaves one space empty // len + 1 can't overflow for an existing, well-formed ringbuffer. - let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + let target_cap = cmp::max( + cmp::max(min_capacity, self.len()) + 1, + MINIMUM_CAPACITY + 1 + ).next_power_of_two(); + if target_cap < self.cap() { // There are three cases of interest: // All elements are out of desired bounds diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index b18b38ec30246..169d365c0ac50 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -910,6 +910,46 @@ impl HashMap } } + /// Shrinks the capacity of the map with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// assert!(map.capacity() >= 100); + /// map.shrink_to(10); + /// assert!(map.capacity() >= 10); + /// map.shrink_to(0); + /// assert!(map.capacity() >= 2); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + + let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity)); + if self.raw_capacity() != new_raw_cap { + let old_table = replace(&mut self.table, RawTable::new(new_raw_cap)); + let old_size = old_table.size(); + + // Shrink the table. Naive algorithm for resizing: + for (h, k, v) in old_table.into_iter() { + self.insert_hashed_nocheck(h, k, v); + } + + debug_assert_eq!(self.table.size(), old_size); + } + } + /// Insert a pre-hashed key-value pair, without first checking /// that there's enough room in the buckets. Returns a reference to the /// newly insert value. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 9e63ba2717a6a..855563a5cb8db 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -292,6 +292,34 @@ impl HashSet self.map.shrink_to_fit() } + /// Shrinks the capacity of the set with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::with_capacity(100); + /// set.insert(1); + /// set.insert(2); + /// assert!(set.capacity() >= 100); + /// set.shrink_to(10); + /// assert!(set.capacity() >= 10); + /// set.shrink_to(0); + /// assert!(set.capacity() >= 2); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.map.shrink_to(min_capacity) + } + /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3959e8533be5f..7520121a8c290 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -295,6 +295,36 @@ impl OsString { self.inner.shrink_to_fit() } + /// Shrinks the capacity of the `OsString` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + /// Converts this `OsString` into a boxed [`OsStr`]. /// /// [`OsStr`]: struct.OsStr.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0b06c5d4d656e..edecf309d16f9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,6 +299,7 @@ #![feature(raw)] #![feature(rustc_attrs)] #![feature(stdsimd)] +#![feature(shrink_to)] #![feature(slice_bytes)] #![feature(slice_concat_ext)] #![feature(slice_internals)] diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index 655bfdb916707..da27787babb97 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index e034938799866..e43bc6da5f1f8 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs index 543c22ebe18a3..84f560af69bec 100644 --- a/src/libstd/sys/wasm/os_str.rs +++ b/src/libstd/sys/wasm/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index 414c9c5418e45..bcc66b9954b89 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -113,6 +113,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 78b2bb5fe6e2f..dda4e1bab3b42 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -253,6 +253,11 @@ impl Wtf8Buf { self.bytes.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.bytes.shrink_to(min_capacity) + } + /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { From 96ef2f8ab9bbea24b71c7441ee534407949848db Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Mar 2018 10:33:31 +0200 Subject: [PATCH 04/16] Fix search appearance --- src/librustdoc/html/static/main.js | 6 +++++- src/librustdoc/html/static/rustdoc.css | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6c6c067f95189..fc78c5edc4cc5 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1171,6 +1171,10 @@ return h1.innerHTML; } + function pathSplitter(path) { + return '' + path.replace(/::/g, '::'); + } + function addTab(array, query, display) { var extraStyle = ''; if (display === false) { @@ -1225,7 +1229,7 @@ output += '' + '' + - displayPath + '' + + pathSplitter(displayPath) + '' + name + '' + '' + '' + escape(item.desc) + diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 9b899dd4517ea..f10fa54050b2f 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -296,6 +296,11 @@ nav.sub { overflow: auto; } +#results > table { + width: 100%; + table-layout: fixed; +} + .content pre.line-numbers { float: left; border: none; @@ -577,8 +582,16 @@ a { display: block; } -.content .search-results td:first-child { padding-right: 0; } -.content .search-results td:first-child a { padding-right: 10px; } +.content .search-results td:first-child { + padding-right: 0; + width: 75%; +} +.content .search-results td:first-child a { + padding-right: 10px; +} +.content .search-results td:first-child a span { + float: left; +} tr.result span.primitive::after { content: ' (primitive type)'; From a93a4d259ae3670d748859f430aba94f065ea6df Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 27 Mar 2018 12:27:45 -0700 Subject: [PATCH 05/16] Enable target_feature on any LLVM 6+ In `LLVMRustHasFeature()`, rather than using `MCInfo->getFeatureTable()` that is specific to Rust's LLVM fork, we can use this in LLVM 6: /// Check whether the subtarget features are enabled/disabled as per /// the provided string, ignoring all other features. bool checkFeatures(StringRef FS) const; Now rustc using external LLVM can also have `target_feature`. --- src/rustllvm/PassWrapper.cpp | 12 ++++-------- src/test/run-pass/sse2.rs | 6 +++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3d5cce81278ac..382ef2cc407dd 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -205,17 +205,13 @@ GEN_SUBTARGETS extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, const char *Feature) { -#if LLVM_RUSTLLVM +#if LLVM_VERSION_GE(6, 0) TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const FeatureBitset &Bits = MCInfo->getFeatureBits(); - const ArrayRef FeatTable = MCInfo->getFeatureTable(); - - for (auto &FeatureEntry : FeatTable) - if (!strcmp(FeatureEntry.Key, Feature)) - return (Bits & FeatureEntry.Value) == FeatureEntry.Value; -#endif + return MCInfo->checkFeatures(std::string("+") + Feature); +#else return false; +#endif } enum class LLVMRustCodeModel { diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs index 22469b2fde058..b1d7e5435c4cb 100644 --- a/src/test/run-pass/sse2.rs +++ b/src/test/run-pass/sse2.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-system-llvm -- needs MCSubtargetInfo::getFeatureTable() +// min-llvm-version 6.0 +// ^ needs MCSubtargetInfo::checkFeatures() // ignore-cloudabi no std::env #![feature(cfg_target_feature)] @@ -29,4 +30,7 @@ fn main() { assert!(cfg!(target_feature = "sse2"), "SSE2 was not detected as available on an x86 platform"); } + // check a negative case too -- whitelisted on x86, but not enabled by default + assert!(cfg!(not(target_feature = "avx2")), + "AVX2 shouldn't be detected as available by default on any platform"); } From 8be26a2ca0f9f01e5b1dd06d5681c4c94fc81042 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Mar 2018 22:49:55 +0200 Subject: [PATCH 06/16] Fix collapse toggle insertions on impl with docs --- src/librustdoc/html/static/main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6c6c067f95189..0b510dd0b6c06 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1816,6 +1816,9 @@ var func = function(e) { var next = e.nextElementSibling; + if (hasClass(e, 'impl') && next && hasClass(next, 'docblock')) { + next = next.nextElementSibling; + } if (!next) { return; } From 37fa6f8b12b9bcbd8fb663a6c1a6c5b98aa052fe Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 27 Mar 2018 14:18:54 +0200 Subject: [PATCH 07/16] rustdoc: Don't use into_iter() when cleaning impl Trait --- src/librustdoc/clean/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1a42b02140cd2..b4c78df741528 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2756,7 +2756,7 @@ impl<'tcx> Clean for Ty<'tcx> { let predicates_of = cx.tcx.predicates_of(def_id); let substs = cx.tcx.lift(&substs).unwrap(); let bounds = predicates_of.instantiate(cx.tcx, substs); - ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| { + ImplTrait(bounds.predicates.iter().filter_map(|predicate| { predicate.to_opt_poly_trait_ref().clean(cx) }).collect()) } From ac655d25c7c1b56fb70b272890b5df1cdd43d236 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 27 Mar 2018 20:45:24 +0200 Subject: [PATCH 08/16] rustdoc: Include associated type bounds when cleaning foreign impl traits --- src/librustdoc/clean/mod.rs | 46 ++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b4c78df741528..875ed12718fa3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1379,17 +1379,18 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { +impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { fn clean(&self, cx: &DocContext) -> TyParamBound { - inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(self.def_id), - Some(self.def_id), true, vec![], self.substs); + let (trait_ref, ref bounds) = *self; + inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); + let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id), + Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs); - debug!("ty::TraitRef\n subst: {:?}\n", self.substs); + debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); // collect any late bound regions let mut late_bounds = vec![]; - for ty_s in self.input_types().skip(1) { + for ty_s in trait_ref.input_types().skip(1) { if let ty::TyTuple(ts) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { @@ -1409,7 +1410,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { trait_: ResolvedPath { path, typarams: None, - did: self.def_id, + did: trait_ref.def_id, is_generic: false, }, generic_params: late_bounds, @@ -1419,6 +1420,12 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } } +impl<'tcx> Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &DocContext) -> TyParamBound { + (self, vec![]).clean(cx) + } +} + impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); @@ -2757,7 +2764,30 @@ impl<'tcx> Clean for Ty<'tcx> { let substs = cx.tcx.lift(&substs).unwrap(); let bounds = predicates_of.instantiate(cx.tcx, substs); ImplTrait(bounds.predicates.iter().filter_map(|predicate| { - predicate.to_opt_poly_trait_ref().clean(cx) + let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() { + tr + } else { + return None; + }; + + let bounds = bounds.predicates.iter().filter_map(|pred| + if let ty::Predicate::Projection(proj) = *pred { + let proj = proj.skip_binder(); + if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() { + Some(TypeBinding { + name: cx.tcx.associated_item(proj.projection_ty.item_def_id) + .name.clean(cx), + ty: proj.ty.clean(cx), + }) + } else { + None + } + } else { + None + } + ).collect(); + + Some((trait_ref.skip_binder(), bounds).clean(cx)) }).collect()) } From 32446f8db3586ff8c56b745bc2fbaf4c88bcab71 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 27 Mar 2018 20:59:09 +0200 Subject: [PATCH 09/16] rustdoc: Remove Sized bounds when cleaning foreign impl Trait --- src/librustdoc/clean/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 875ed12718fa3..aa8a7fc534627 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2770,6 +2770,14 @@ impl<'tcx> Clean for Ty<'tcx> { return None; }; + if let Some(sized) = cx.tcx.lang_items().sized_trait() { + if trait_ref.def_id() == sized { + return None; + } + } + + // FIXME(Manishearth) handle cases which aren't Sized + let bounds = bounds.predicates.iter().filter_map(|pred| if let ty::Predicate::Projection(proj) = *pred { let proj = proj.skip_binder(); From 6a547b4f61f7acec8bf526e93cc244a82cb8925e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 27 Mar 2018 21:26:44 +0200 Subject: [PATCH 10/16] rustdoc: Handle explicit ?Sized on foreign impl Trait --- src/librustdoc/clean/mod.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aa8a7fc534627..a7d34d5252434 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2763,20 +2763,26 @@ impl<'tcx> Clean for Ty<'tcx> { let predicates_of = cx.tcx.predicates_of(def_id); let substs = cx.tcx.lift(&substs).unwrap(); let bounds = predicates_of.instantiate(cx.tcx, substs); - ImplTrait(bounds.predicates.iter().filter_map(|predicate| { + let mut regions = vec![]; + let mut has_sized = false; + let mut bounds = bounds.predicates.iter().filter_map(|predicate| { let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() { tr + } else if let ty::Predicate::TypeOutlives(pred) = *predicate { + // these should turn up at the end + pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r))); + return None; } else { return None; }; if let Some(sized) = cx.tcx.lang_items().sized_trait() { if trait_ref.def_id() == sized { + has_sized = true; return None; } } - // FIXME(Manishearth) handle cases which aren't Sized let bounds = bounds.predicates.iter().filter_map(|pred| if let ty::Predicate::Projection(proj) = *pred { @@ -2796,7 +2802,12 @@ impl<'tcx> Clean for Ty<'tcx> { ).collect(); Some((trait_ref.skip_binder(), bounds).clean(cx)) - }).collect()) + }).collect::>(); + bounds.extend(regions); + if !has_sized && !bounds.is_empty() { + bounds.insert(0, TyParamBound::maybe_sized(cx)); + } + ImplTrait(bounds) } ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton) From 33dceaa24409951dfe7607c580de6fd504932c90 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 27 Mar 2018 21:37:27 +0200 Subject: [PATCH 11/16] rustdoc: Add test for foreign impl trait with bounds --- .../rustdoc/auxiliary/extern-impl-trait.rs | 37 +++++++++++++++++++ src/test/rustdoc/extern-impl-trait.rs | 21 +++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/test/rustdoc/auxiliary/extern-impl-trait.rs create mode 100644 src/test/rustdoc/extern-impl-trait.rs diff --git a/src/test/rustdoc/auxiliary/extern-impl-trait.rs b/src/test/rustdoc/auxiliary/extern-impl-trait.rs new file mode 100644 index 0000000000000..ba6c3e956953b --- /dev/null +++ b/src/test/rustdoc/auxiliary/extern-impl-trait.rs @@ -0,0 +1,37 @@ +// 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. + +pub trait Foo { + type Associated; +} + +pub struct X; +pub struct Y; + + +impl Foo for X { + type Associated = (); +} + +impl Foo for Y { + type Associated = (); +} + +impl X { + pub fn returns_sized<'a>(&'a self) -> impl Foo + 'a { + X + } +} + +impl Y { + pub fn returns_unsized<'a>(&'a self) -> Box + 'a> { + Box::new(X) + } +} diff --git a/src/test/rustdoc/extern-impl-trait.rs b/src/test/rustdoc/extern-impl-trait.rs new file mode 100644 index 0000000000000..02a8e962fe17b --- /dev/null +++ b/src/test/rustdoc/extern-impl-trait.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:extern-impl-trait.rs + +#![crate_name = "foo"] + +extern crate extern_impl_trait; + +// @has 'foo/struct.X.html' '//code' "impl Foo + 'a" +pub use extern_impl_trait::X; + +// @has 'foo/struct.Y.html' '//code' "impl ?Sized + Foo + 'a" +pub use extern_impl_trait::Y; From 884153a2572b837c90725930345cfbe74c073dc1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Mar 2018 09:50:55 +0200 Subject: [PATCH 12/16] Fix trait implementation not collapsing docs --- src/librustdoc/html/static/main.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6c6c067f95189..67a133a1934c1 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1713,19 +1713,20 @@ // we are collapsing the impl block function implHider(addOrRemove) { return function(n) { - if (hasClass(n, "method")) { - if (addOrRemove) { - addClass(n, "hidden-by-impl-hider"); - } else { - removeClass(n, "hidden-by-impl-hider"); + var is_method = hasClass(n, "method"); + if (is_method || hasClass(n, "type")) { + if (is_method === true) { + if (addOrRemove) { + addClass(n, "hidden-by-impl-hider"); + } else { + removeClass(n, "hidden-by-impl-hider"); + } } var ns = n.nextElementSibling; while (true) { if (ns && ( hasClass(ns, "docblock") || - hasClass(ns, "stability") || - false - )) { + hasClass(ns, "stability"))) { if (addOrRemove) { addClass(ns, "hidden-by-impl-hider"); } else { @@ -1741,12 +1742,13 @@ } var relatedDoc = toggle.parentNode; + var docblock = relatedDoc.nextElementSibling; while (!hasClass(relatedDoc, "impl-items")) { relatedDoc = relatedDoc.nextElementSibling; } - if (!relatedDoc) { + if (!relatedDoc && !hasClass(docblock, "docblock")) { return; } @@ -1754,7 +1756,8 @@ var action = mode; if (action === "toggle") { - if (hasClass(relatedDoc, "fns-now-collapsed")) { + if (hasClass(relatedDoc, "fns-now-collapsed") || + hasClass(docblock, "hidden-by-impl-hider")) { action = "show"; } else { action = "hide"; @@ -1763,10 +1766,12 @@ if (action === "show") { removeClass(relatedDoc, "fns-now-collapsed"); + removeClass(docblock, "hidden-by-usual-hider"); onEach(toggle.childNodes, adjustToggle(false)); onEach(relatedDoc.childNodes, implHider(false)); } else if (action === "hide") { addClass(relatedDoc, "fns-now-collapsed"); + addClass(docblock, "hidden-by-usual-hider"); onEach(toggle.childNodes, adjustToggle(true)); onEach(relatedDoc.childNodes, implHider(true)); } From 7038236da9aaadfd16208ee489e61a1a1230417c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 28 Mar 2018 10:49:45 +0200 Subject: [PATCH 13/16] Delete leftover librustc_const_eval Probably accidentally reintroduced in a rebase/merge --- src/librustc_const_eval/lib.rs | 59 ---------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 src/librustc_const_eval/lib.rs diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs deleted file mode 100644 index 2620448927d86..0000000000000 --- a/src/librustc_const_eval/lib.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 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. - -//! constant evaluation on the HIR and code to validate patterns/matches -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] -#![deny(warnings)] - -#![feature(rustc_diagnostic_macros)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![feature(macro_lifetime_matcher)] -#![cfg_attr(stage0, feature(i128_type))] -#![feature(from_ref)] - -extern crate arena; -#[macro_use] extern crate syntax; -#[macro_use] extern crate log; -#[macro_use] extern crate rustc; -extern crate rustc_const_math; -extern crate rustc_data_structures; -extern crate rustc_errors; -extern crate syntax_pos; - -// NB: This module needs to be declared first so diagnostics are -// registered before they are used. -mod diagnostics; - -mod eval; -mod _match; -pub mod check_match; -pub mod pattern; - -pub use eval::*; - -use rustc::ty::maps::Providers; - -pub fn provide(providers: &mut Providers) { - *providers = Providers { - check_match: check_match::check_match, - ..*providers - }; -} - -// Build the diagnostics array at the end so that the metadata includes error use sites. -__build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS } From 51f26acaea46afd630fbab4ca441748802d20670 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Mar 2018 09:00:58 +0200 Subject: [PATCH 14/16] Fix text overlap --- src/librustdoc/html/render.rs | 33 ++++++++++--------- src/librustdoc/html/static/rustdoc.css | 30 ++++++++++++++--- src/test/rustdoc/synthetic_auto/complex.rs | 2 +- src/test/rustdoc/synthetic_auto/lifetimes.rs | 4 +-- src/test/rustdoc/synthetic_auto/manual.rs | 4 +-- src/test/rustdoc/synthetic_auto/negative.rs | 4 +-- src/test/rustdoc/synthetic_auto/nested.rs | 4 +-- .../rustdoc/synthetic_auto/no-redundancy.rs | 2 +- src/test/rustdoc/synthetic_auto/project.rs | 4 +-- 9 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 678e1762a5519..2eee60890e87d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2243,14 +2243,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> Result<(), fmt::Error> { - write!(w, "
  • ")?; - if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() { - write!(w, "
    ")?; - write!(w, "[src]", - l, "goto source code")?; - write!(w, "
    ")?; - } - write!(w, "")?; + write!(w, "
  • ")?; // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -2269,7 +2262,14 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, write!(w, ";")?; } } - writeln!(w, "")?; + write!(w, "")?; + if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() { + write!(w, "
    ")?; + write!(w, "[src]", + l, "goto source code")?; + write!(w, "
    ")?; + } + writeln!(w, "
  • ")?; Ok(()) } @@ -3314,10 +3314,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))), None => "impl".to_string(), }); - write!(w, "

    {}", + write!(w, "

    \ +
    {}", id, i.inner_impl())?; write!(w, "", id)?; - write!(w, "")?; + write!(w, "")?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { write!(w, "
    ")?; @@ -3327,8 +3328,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else { render_stability_since_raw(w, since, outer_version)?; } - write!(w, "
    ")?; - write!(w, "\n")?; + write!(w, "

    ")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { write!(w, "
    {}
    ", Markdown(&*dox, &i.impl_item.links()))?; @@ -3357,19 +3357,20 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "

    ", id, item_type)?; write!(w, "{}", spotlight_decl(decl)?)?; write!(w, "

    ")?; } } clean::TypedefItem(ref tydef, _) => { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 9b899dd4517ea..5fb2aa4ef74f8 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -387,8 +387,6 @@ h4 > code, h3 > code, .invisible > code { .content .in-band { margin: 0px; padding: 0px; - display: inline-block; - max-width: calc(100% - 43px); } .in-band > code { @@ -403,7 +401,7 @@ h4 > code, h3 > code, .invisible > code { font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } -.content table { +.content table:not(.table-display) { border-spacing: 0 5px; border-collapse: separate; } @@ -470,7 +468,6 @@ h4 > code, h3 > code, .invisible > code { .content .methods > div:not(.important-traits) { margin-left: 40px; } .content .impl-items .docblock, .content .impl-items .stability { - margin-left: 40px; margin-bottom: .6em; } .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant { @@ -1254,3 +1251,28 @@ kbd { /* important because of conflicting rule for small screens */ display: none !important; } + +#implementations-list > h3 > span.in-band { + width: 100%; +} + +.table-display { + width: 100%; + border: 0; + border-collapse: collapse; + border-spacing: 0; + font-size: 16px; +} + +.table-display tr td:first-child { + padding-right: 0; +} + +.table-display tr td:last-child { + float: right; +} +.table-display .out-of-band { + position: relative; + font-size: 19px; + display: block; +} diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 531798c30c656..a4ebf6d3a7e83 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -30,7 +30,7 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'a, T, K: \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a, T, K: \ // ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 272925e5db542..1c1e7bc250526 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -18,10 +18,10 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \ // for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index d81e6309dff61..ef6797ecf3c54 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -9,10 +9,10 @@ // except according to those terms. // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl Sync for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl Sync for \ // Foo where T: Sync' // -// @has - '//*[@id="implementations-list"]/*[@class="impl"]/*/code' \ +// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' \ // 'impl Send for Foo' // // @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1 diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index ec9cb710f1f8c..64480d28240b6 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -13,10 +13,10 @@ pub struct Inner { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl !Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl !Send for \ // Outer" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl \ // !Sync for Outer" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 1f33a8b13cbf8..ccdbe159b6c5a 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -18,10 +18,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl Send for \ // Foo where T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' \ // 'impl Sync for Foo where T: Sync' pub struct Foo { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 0b37f2ed31790..24fba221b9937 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -19,7 +19,7 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl Send for \ // Outer where T: Copy + Send" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 977607fb14826..d588190c4f9d2 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -33,10 +33,10 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \ // for Foo<'c, K> where K: MyTrait, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: MyTrait, ::MyItem: OtherTrait, 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, From 0d15a3ee5402284450c312318871971f41603f80 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 28 Mar 2018 14:10:18 +0200 Subject: [PATCH 15/16] Clarify "length" wording in `Vec::with_capacity`. --- src/liballoc/vec.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 953f95876be15..f8fc3f2bda10b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -334,9 +334,10 @@ impl Vec { /// The vector will be able to hold exactly `capacity` elements without /// reallocating. If `capacity` is 0, the vector will not allocate. /// - /// It is important to note that this function does not specify the *length* - /// of the returned vector, but only the *capacity*. For an explanation of - /// the difference between length and capacity, see *[Capacity and reallocation]*. + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. /// /// [Capacity and reallocation]: #capacity-and-reallocation /// From 49fd71bea7bd3d8d11818503ca048227ffa1e758 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 22 Mar 2018 22:25:57 -0400 Subject: [PATCH 16/16] [incremental] Don't panic if decoding the cache fails If the cached data can't be loaded from disk, just issue a warning to the user so they know why compilation is taking longer than usual but don't fail the entire compilation since we can recover by ignorning the on disk cache. In the same way, if the disk cache can't be deserialized (because it has been corrupted for some reason), report the issue as a warning and continue without failing the compilation. `Decodable::decode()` tends to panic with various errors like "entered unreachable code" or "index out of range" if the input data is corrupted. Work around this by catching panics from the `decode()` calls when joining the thread and continuing without the cached data. Fixes #48847 --- src/librustc_driver/driver.rs | 4 +++- src/librustc_incremental/lib.rs | 1 + src/librustc_incremental/persist/load.rs | 3 ++- src/librustc_incremental/persist/mod.rs | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a3115544f30b9..c6ebc99268057 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -901,7 +901,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, Some(future) => { let prev_graph = time(sess, "blocked while dep-graph loading finishes", || { future.open() - .expect("Could not join with background dep_graph thread") + .unwrap_or_else(|e| rustc_incremental::LoadResult::Error { + message: format!("could not decode incremental cache: {:?}", e) + }) .open(sess) }); DepGraph::new(prev_graph) diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index d7ccf9d5562e6..4b524287ca1c7 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -39,6 +39,7 @@ pub use assert_dep_graph::assert_dep_graph; pub use persist::dep_graph_tcx_init; pub use persist::load_dep_graph; pub use persist::load_query_result_cache; +pub use persist::LoadResult; pub use persist::save_dep_graph; pub use persist::save_trans_partition; pub use persist::save_work_products; diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 38468e29427b0..44d6e532f79bb 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -89,7 +89,8 @@ impl LoadResult { pub fn open(self, sess: &Session) -> PreviousDepGraph { match self { LoadResult::Error { message } => { - sess.fatal(&message) /* never returns */ + sess.warn(&message); + PreviousDepGraph::new(SerializedDepGraph::new()) }, LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index 2f864aaefba89..755a550b5bca3 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -27,6 +27,7 @@ pub use self::fs::prepare_session_directory; pub use self::load::dep_graph_tcx_init; pub use self::load::load_dep_graph; pub use self::load::load_query_result_cache; +pub use self::load::LoadResult; pub use self::save::save_dep_graph; pub use self::save::save_work_products; pub use self::work_product::save_trans_partition;