Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #78033

Merged
merged 16 commits into from
Oct 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
@@ -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());
}
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 6 additions & 1 deletion compiler/rustc_mir/src/interpret/cast.rs
Original file line number Diff line number Diff line change
@@ -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)?;
1 change: 0 additions & 1 deletion library/alloc/src/collections/btree/node.rs
Original file line number Diff line number Diff line change
@@ -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
139 changes: 138 additions & 1 deletion library/alloc/src/collections/vec_deque.rs
Original file line number Diff line number Diff line change
@@ -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> {
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -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};
39 changes: 39 additions & 0 deletions library/alloc/tests/vec_deque.rs
Original file line number Diff line number Diff line change
@@ -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));
}
20 changes: 9 additions & 11 deletions src/etc/gdb_providers.py
Original file line number Diff line number Diff line change
@@ -229,8 +229,8 @@ def cast_to_internal(node):
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 @@ def to_string(self):

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 @@ def to_string(self):
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():
11 changes: 9 additions & 2 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -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.
28 changes: 20 additions & 8 deletions src/test/debuginfo/pretty-std-collections.rs
Original file line number Diff line number Diff line change
@@ -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();
7 changes: 7 additions & 0 deletions src/test/rustdoc/no-compiler-reexport.rs
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 3 additions & 1 deletion src/test/ui/uninhabited/uninhabited-enum-cast.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Loading