about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-17 01:41:43 +0000
committerbors <bors@rust-lang.org>2020-10-17 01:41:43 +0000
commit3f50dea4d0dfce527871bb0a198dc17c479e697b (patch)
treebdde49e8d12de219742f63555eed23fde2ced051
parentf1b97ee7f8ffb1a814944b85c7e05a1555a7eda5 (diff)
parentb9c45d1e782f710bae7b8d43c1863848b8f660a5 (diff)
downloadrust-3f50dea4d0dfce527871bb0a198dc17c479e697b.tar.gz
rust-3f50dea4d0dfce527871bb0a198dc17c479e697b.zip
Auto merge of #78033 - Dylan-DPC:rollup-ds2cfsf, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #76199 (Permit uninhabited enums to cast into ints)
 - #77751 (liballoc: VecDeque: Add binary search functions)
 - #77785 (Remove compiler-synthesized reexports when documenting)
 - #77932 (BTreeMap: improve gdb introspection of BTreeMap with ZST keys or values)
 - #77961 (Set .llvmbc and .llvmcmd sections as allocatable)
 - #77985 (llvm: backport SystemZ fix for AGR clobbers)

Failed merges:

r? `@ghost`
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_mir/src/interpret/cast.rs7
-rw-r--r--library/alloc/src/collections/btree/node.rs1
-rw-r--r--library/alloc/src/collections/vec_deque.rs139
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/vec_deque.rs39
-rw-r--r--src/etc/gdb_providers.py20
-rw-r--r--src/librustdoc/clean/mod.rs11
m---------src/llvm-project0
-rw-r--r--src/test/debuginfo/pretty-std-collections.rs28
-rw-r--r--src/test/rustdoc/no-compiler-reexport.rs7
-rw-r--r--src/test/ui/uninhabited/uninhabited-enum-cast.rs4
-rw-r--r--src/test/ui/uninhabited/uninhabited-enum-cast.stderr9
14 files changed, 237 insertions, 37 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index ea1a7cfa5d3..092d1cea295 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -936,8 +936,8 @@ unsafe fn embed_bitcode(
         llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
     } else {
         let asm = "
-            .section .llvmbc,\"e\"
-            .section .llvmcmd,\"e\"
+            .section .llvmbc,\"a\"
+            .section .llvmcmd,\"a\"
         ";
         llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 275888b0ce2..bc84eccfcf5 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2436,8 +2436,10 @@ impl<'tcx> AdtDef {
         self.variants.iter().flat_map(|v| v.fields.iter())
     }
 
+    /// Whether the ADT lacks fields. Note that this includes uninhabited enums,
+    /// e.g., `enum Void {}` is considered payload free as well.
     pub fn is_payloadfree(&self) -> bool {
-        !self.variants.is_empty() && self.variants.iter().all(|v| v.fields.is_empty())
+        self.variants.iter().all(|v| v.fields.is_empty())
     }
 
     /// Return a `VariantDef` given a variant id.
diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs
index 0e16b0caefa..affeae546b2 100644
--- a/compiler/rustc_mir/src/interpret/cast.rs
+++ b/compiler/rustc_mir/src/interpret/cast.rs
@@ -139,9 +139,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         // # First handle non-scalar source values.
 
-        // Handle cast from a univariant (ZST) enum.
+        // Handle cast from a ZST enum (0 or 1 variants).
         match src.layout.variants {
             Variants::Single { index } => {
+                if src.layout.abi.is_uninhabited() {
+                    // This is dead code, because an uninhabited enum is UB to
+                    // instantiate.
+                    throw_ub!(Unreachable);
+                }
                 if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     assert!(src.layout.is_zst());
                     let discr_layout = self.layout_of(discr.ty)?;
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 903faf3fa96..cf7961cbbfc 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -87,7 +87,6 @@ impl<K, V> LeafNode<K, V> {
 #[repr(C)]
 // gdb_providers.py uses this type name for introspection.
 struct InternalNode<K, V> {
-    // gdb_providers.py uses this field name for introspection.
     data: LeafNode<K, V>,
 
     /// The pointers to the children of this node. `len + 1` of these are considered
diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs
index ff9b1553bf2..94dac1cd176 100644
--- a/library/alloc/src/collections/vec_deque.rs
+++ b/library/alloc/src/collections/vec_deque.rs
@@ -2181,7 +2181,7 @@ impl<T> VecDeque<T> {
     ///
     /// This method does not allocate and does not change the order of the
     /// inserted elements. As it returns a mutable slice, this can be used to
-    /// sort or binary search a deque.
+    /// sort a deque.
     ///
     /// Once the internal storage is contiguous, the [`as_slices`] and
     /// [`as_mut_slices`] methods will return the entire contents of the
@@ -2430,6 +2430,143 @@ impl<T> VecDeque<T> {
             self.wrap_copy(self.tail, self.head, k);
         }
     }
+
+    /// Binary searches this sorted `VecDeque` for a given element.
+    ///
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// #![feature(vecdeque_binary_search)]
+    /// use std::collections::VecDeque;
+    ///
+    /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+    ///
+    /// assert_eq!(deque.binary_search(&13),  Ok(9));
+    /// assert_eq!(deque.binary_search(&4),   Err(7));
+    /// assert_eq!(deque.binary_search(&100), Err(13));
+    /// let r = deque.binary_search(&1);
+    /// assert!(matches!(r, Ok(1..=4)));
+    /// ```
+    ///
+    /// If you want to insert an item to a sorted `VecDeque`, while maintaining
+    /// sort order:
+    ///
+    /// ```
+    /// #![feature(vecdeque_binary_search)]
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+    /// let num = 42;
+    /// let idx = deque.binary_search(&num).unwrap_or_else(|x| x);
+    /// deque.insert(idx, num);
+    /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
+    /// ```
+    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[inline]
+    pub fn binary_search(&self, x: &T) -> Result<usize, usize>
+    where
+        T: Ord,
+    {
+        self.binary_search_by(|e| e.cmp(x))
+    }
+
+    /// Binary searches this sorted `VecDeque` with a comparator function.
+    ///
+    /// The comparator function should implement an order consistent
+    /// with the sort order of the underlying `VecDeque`, returning an
+    /// order code that indicates whether its argument is `Less`,
+    /// `Equal` or `Greater` than the desired target.
+    ///
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// #![feature(vecdeque_binary_search)]
+    /// use std::collections::VecDeque;
+    ///
+    /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+    ///
+    /// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)),  Ok(9));
+    /// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)),   Err(7));
+    /// assert_eq!(deque.binary_search_by(|x| x.cmp(&100)), Err(13));
+    /// let r = deque.binary_search_by(|x| x.cmp(&1));
+    /// assert!(matches!(r, Ok(1..=4)));
+    /// ```
+    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
+    where
+        F: FnMut(&'a T) -> Ordering,
+    {
+        let (front, back) = self.as_slices();
+
+        if let Some(Ordering::Less | Ordering::Equal) = back.first().map(|elem| f(elem)) {
+            back.binary_search_by(f).map(|idx| idx + front.len()).map_err(|idx| idx + front.len())
+        } else {
+            front.binary_search_by(f)
+        }
+    }
+
+    /// Binary searches this sorted `VecDeque` with a key extraction function.
+    ///
+    /// Assumes that the `VecDeque` is sorted by the key, for instance with
+    /// [`make_contiguous().sort_by_key()`](#method.make_contiguous) using the same
+    /// key extraction function.
+    ///
+    /// If the value is found then [`Result::Ok`] is returned, containing the
+    /// index of the matching element. If there are multiple matches, then any
+    /// one of the matches could be returned. If the value is not found then
+    /// [`Result::Err`] is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements in a slice of pairs sorted by
+    /// their second elements. The first is found, with a uniquely
+    /// determined position; the second and third are not found; the
+    /// fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// #![feature(vecdeque_binary_search)]
+    /// use std::collections::VecDeque;
+    ///
+    /// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1),
+    ///          (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+    ///          (1, 21), (2, 34), (4, 55)].into();
+    ///
+    /// assert_eq!(deque.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
+    /// assert_eq!(deque.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
+    /// assert_eq!(deque.binary_search_by_key(&100, |&(a,b)| b), Err(13));
+    /// let r = deque.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert!(matches!(r, Ok(1..=4)));
+    /// ```
+    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[inline]
+    pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
+    where
+        F: FnMut(&'a T) -> B,
+        B: Ord,
+    {
+        self.binary_search_by(|k| f(k).cmp(b))
+    }
 }
 
 impl<T: Clone> VecDeque<T> {
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index cff8ff9ac7a..b7cc03f8eb9 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -20,6 +20,7 @@
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
 #![feature(int_bits_const)]
+#![feature(vecdeque_binary_search)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index 46d8a3c4cb4..05cb3a2c03d 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -1659,3 +1659,42 @@ fn test_drain_leak() {
     drop(v);
     assert_eq!(unsafe { DROPS }, 7);
 }
+
+#[test]
+fn test_binary_search() {
+    // Contiguous (front only) search:
+    let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into();
+    assert!(deque.as_slices().1.is_empty());
+    assert_eq!(deque.binary_search(&3), Ok(2));
+    assert_eq!(deque.binary_search(&4), Err(3));
+
+    // Split search (both front & back non-empty):
+    let mut deque: VecDeque<_> = vec![5, 6].into();
+    deque.push_front(3);
+    deque.push_front(2);
+    deque.push_front(1);
+    deque.push_back(10);
+    assert!(!deque.as_slices().0.is_empty());
+    assert!(!deque.as_slices().1.is_empty());
+    assert_eq!(deque.binary_search(&0), Err(0));
+    assert_eq!(deque.binary_search(&1), Ok(0));
+    assert_eq!(deque.binary_search(&5), Ok(3));
+    assert_eq!(deque.binary_search(&7), Err(5));
+    assert_eq!(deque.binary_search(&20), Err(6));
+}
+
+#[test]
+fn test_binary_search_by() {
+    let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
+
+    assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&3)), Ok(2));
+    assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&4)), Err(3));
+}
+
+#[test]
+fn test_binary_search_by_key() {
+    let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
+
+    assert_eq!(deque.binary_search_by_key(&3, |&(v,)| v), Ok(2));
+    assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3));
+}
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index b2d343fd7af..eec3027085c 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -229,8 +229,8 @@ def children_of_node(boxed_node, height):
                 yield child
         if i < length:
             # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
-            key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else None
-            val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else None
+            key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else "()"
+            val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else "()"
             yield key, val
 
 
@@ -242,11 +242,8 @@ def children_of_map(map):
             root = root.cast(gdb.lookup_type(root.type.name[21:-1]))
         boxed_root_node = root["node"]
         height = root["height"]
-        for i, (key, val) in enumerate(children_of_node(boxed_root_node, height)):
-            if key is not None:
-                yield "key{}".format(i), key
-            if val is not None:
-                yield "val{}".format(i), val
+        for child in children_of_node(boxed_root_node, height):
+            yield child
 
 
 class StdBTreeSetProvider:
@@ -258,8 +255,8 @@ class StdBTreeSetProvider:
 
     def children(self):
         inner_map = self.valobj["map"]
-        for child in children_of_map(inner_map):
-            yield child
+        for i, (child, _) in enumerate(children_of_map(inner_map)):
+            yield "[{}]".format(i), child
 
     @staticmethod
     def display_hint():
@@ -274,8 +271,9 @@ class StdBTreeMapProvider:
         return "BTreeMap(size={})".format(self.valobj["length"])
 
     def children(self):
-        for child in children_of_map(self.valobj):
-            yield child
+        for i, (key, val) in enumerate(children_of_map(self.valobj)):
+            yield "key{}".format(i), key
+            yield "val{}".format(i), val
 
     @staticmethod
     def display_hint():
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 776b131a076..0365a8b48db 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -23,9 +23,9 @@ use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
 use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
-use rustc_span::hygiene::MacroKind;
+use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{self, Pos};
+use rustc_span::{self, ExpnKind, Pos};
 use rustc_typeck::hir_ty_to_ty;
 
 use std::collections::hash_map::Entry;
@@ -2231,6 +2231,13 @@ impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
 
 impl Clean<Vec<Item>> for doctree::Import<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
+        // We need this comparison because some imports (for std types for example)
+        // are "inserted" as well but directly by the compiler and they should not be
+        // taken into account.
+        if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
+            return Vec::new();
+        }
+
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 3c5d47c81d78e9316e971c9870e8bc7c2c449d2
+Subproject 77a0125981b293260c9aec6355dff46ec707ab5
diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs
index c6d2090759f..cc2a3a34510 100644
--- a/src/test/debuginfo/pretty-std-collections.rs
+++ b/src/test/debuginfo/pretty-std-collections.rs
@@ -34,20 +34,26 @@
 // gdb-check:$6 = BTreeMap(size=15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]}
 // (abbreviated because it's boring but we need enough elements to include internal nodes)
 
-// gdb-command: print zst_btree_map
-// gdb-check:$7 = BTreeMap(size=1)
+// gdb-command: print zst_key_btree_map
+// gdb-check:$7 = BTreeMap(size=1) = {[()] = 1}
+
+// gdb-command: print zst_val_btree_map
+// gdb-check:$8 = BTreeMap(size=1) = {[1] = ()}
+
+// gdb-command: print zst_key_val_btree_map
+// gdb-check:$9 = BTreeMap(size=1) = {[()] = ()}
 
 // gdb-command: print vec_deque
-// gdb-check:$8 = VecDeque(size=3) = {5, 3, 7}
+// gdb-check:$10 = VecDeque(size=3) = {5, 3, 7}
 
 // gdb-command: print vec_deque2
-// gdb-check:$9 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8}
+// gdb-check:$11 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8}
 
 // gdb-command: print hash_map
-// gdb-check:$10 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40}
+// gdb-check:$12 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40}
 
 // gdb-command: print hash_set
-// gdb-check:$11 = HashSet(size=4) = {1, 2, 3, 4}
+// gdb-check:$13 = HashSet(size=4) = {1, 2, 3, 4}
 
 // === LLDB TESTS ==================================================================================
 
@@ -114,8 +120,14 @@ fn main() {
         nasty_btree_map.insert(i, MyLeafNode(i));
     }
 
-    let mut zst_btree_map: BTreeMap<(), ()> = BTreeMap::new();
-    zst_btree_map.insert((), ());
+    let mut zst_key_btree_map: BTreeMap<(), i32> = BTreeMap::new();
+    zst_key_btree_map.insert((), 1);
+
+    let mut zst_val_btree_map: BTreeMap<i32, ()> = BTreeMap::new();
+    zst_val_btree_map.insert(1, ());
+
+    let mut zst_key_val_btree_map: BTreeMap<(), ()> = BTreeMap::new();
+    zst_key_val_btree_map.insert((), ());
 
     // VecDeque
     let mut vec_deque = VecDeque::new();
diff --git a/src/test/rustdoc/no-compiler-reexport.rs b/src/test/rustdoc/no-compiler-reexport.rs
new file mode 100644
index 00000000000..6d50325fed5
--- /dev/null
+++ b/src/test/rustdoc/no-compiler-reexport.rs
@@ -0,0 +1,7 @@
+// compile-flags: --no-defaults
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html' '//code' 'extern crate std;'
+// @!has 'foo/index.html' '//code' 'use std::prelude::v1::*;'
+pub struct Foo;
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.rs b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
index 7e178e054cc..5a75c94c42f 100644
--- a/src/test/ui/uninhabited/uninhabited-enum-cast.rs
+++ b/src/test/ui/uninhabited/uninhabited-enum-cast.rs
@@ -1,7 +1,9 @@
+// check-pass
+
 enum E {}
 
 fn f(e: E) {
-    println!("{}", (e as isize).to_string());   //~ ERROR non-primitive cast
+    println!("{}", (e as isize).to_string());
 }
 
 fn main() {}
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
deleted file mode 100644
index a9f10dfec99..00000000000
--- a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0605]: non-primitive cast: `E` as `isize`
-  --> $DIR/uninhabited-enum-cast.rs:4:20
-   |
-LL |     println!("{}", (e as isize).to_string());
-   |                    ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0605`.