Auto merge of #56875 - Centril:rollup, r=Centril

Rollup of 20 pull requests

Successful merges:

 - #53506 (Documentation for impl From for AtomicBool and other Atomic types)
 - #56343 (Remove not used mod)
 - #56439 (Clearer error message for dead assign)
 - #56640 (Add FreeBSD unsigned char platforms to std::os::raw)
 - #56648 (Fix BTreeMap UB)
 - #56672 (Document time of back operations of a Linked List)
 - #56706 (Make `const unsafe fn` bodies `unsafe`)
 - #56742 (infer: remove Box from a returned Iterator)
 - #56761 (Suggest using `.display()` when trying to print a `Path`)
 - #56781 (Update LLVM submodule)
 - #56789 (rustc: Add an unstable `simd_select_bitmask` intrinsic)
 - #56790 (Make RValue::Discriminant a normal Shallow read)
 - #56793 (rustdoc: look for comments when scraping attributes/crates from doctests)
 - #56826 (rustc: Add the `cmpxchg16b` target feature on x86/x86_64)
 - #56832 (std: Use `rustc_demangle` from crates.io)
 - #56844 (Improve CSS rule)
 - #56850 (Fixed issue with using `Self` ctor in typedefs)
 - #56855 (Remove u8 cttz hack)
 - #56857 (Fix a small mistake regarding NaNs in a deprecation message)
 - #56858 (Fix doc of `std::fs::canonicalize`)

Failed merges:

 - #56741 (treat ref-to-raw cast like a reborrow: do a special kind of retag)

r? @ghost
This commit is contained in:
bors 2018-12-16 20:58:09 +00:00
commit a8a2a887d0
52 changed files with 653 additions and 840 deletions

View File

@ -87,7 +87,7 @@ dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1813,7 +1813,7 @@ name = "rand_chacha"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1835,7 +1835,7 @@ name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1860,7 +1860,7 @@ name = "rand_xorshift"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2195,8 +2195,12 @@ dependencies = [
[[package]]
name = "rustc-demangle"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0",
]
[[package]]
name = "rustc-hash"
@ -2315,7 +2319,7 @@ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_llvm 0.0.0",
]
@ -2331,7 +2335,7 @@ dependencies = [
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_apfloat 0.0.0",
"rustc_codegen_utils 0.0.0",
@ -2892,6 +2896,7 @@ dependencies = [
"panic_unwind 0.0.0",
"profiler_builtins 0.0.0",
"rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_asan 0.0.0",
"rustc_lsan 0.0.0",
"rustc_msan 0.0.0",
@ -3578,7 +3583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737"
"checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a"
"checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"

View File

@ -58,9 +58,34 @@ pub const CAPACITY: usize = 2 * B - 1;
/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
/// case.
///
/// We put the metadata first so that its position is the same for every `K` and `V`, in order
/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
/// prevent them from being reordered.
/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
/// order to statically allocate a single dummy node to avoid allocations. This struct is
/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a
/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
/// by `as_header`.)
/// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around
/// because the size of `NodeHeader` depends on its alignment!
#[repr(C)]
struct NodeHeader<K, V, K2 = ()> {
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
/// This either points to an actual node or is null.
parent: *const InternalNode<K, V>,
/// This node's index into the parent node's `edges` array.
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
/// This is only guaranteed to be initialized when `parent` is non-null.
parent_idx: MaybeUninit<u16>,
/// The number of keys and values this node stores.
///
/// This next to `parent_idx` to encourage the compiler to join `len` and
/// `parent_idx` into the same 32-bit word, reducing space overhead.
len: u16,
/// See `into_key_slice`.
keys_start: [K2; 0],
}
#[repr(C)]
struct LeafNode<K, V> {
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@ -98,24 +123,25 @@ impl<K, V> LeafNode<K, V> {
len: 0
}
}
}
impl<K, V> NodeHeader<K, V> {
fn is_shared_root(&self) -> bool {
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
}
}
// We need to implement Sync here in order to make a static instance.
unsafe impl Sync for LeafNode<(), ()> {}
unsafe impl Sync for NodeHeader<(), ()> {}
// An empty node used as a placeholder for the root node, to avoid allocations.
// We use () in order to save space, since no operation on an empty tree will
// We use just a header in order to save space, since no operation on an empty tree will
// ever take a pointer past the first key.
static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader {
parent: ptr::null(),
parent_idx: MaybeUninit::uninitialized(),
len: 0,
keys: MaybeUninit::uninitialized(),
vals: MaybeUninit::uninitialized(),
keys_start: [],
};
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@ -281,7 +307,7 @@ impl<K, V> Root<K, V> {
.node)
};
self.height -= 1;
self.as_mut().as_leaf_mut().parent = ptr::null();
unsafe { (*self.as_mut().as_leaf_mut()).parent = ptr::null(); }
unsafe {
Global.dealloc(NonNull::from(top).cast(), Layout::new::<InternalNode<K, V>>());
@ -306,6 +332,11 @@ impl<K, V> Root<K, V> {
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
/// `NodeRef` could be pointing to either type of node.
/// Note that in case of a leaf node, this might still be the shared root! Only turn
/// this into a `LeafNode` reference if you know it is not a root! Shared references
/// must be dereferencable *for the entire size of their pointee*, so `&InternalNode`
/// pointing to the shared root is UB.
/// Turning this into a `NodeHeader` is always safe.
pub struct NodeRef<BorrowType, K, V, Type> {
height: usize,
node: NonNull<LeafNode<K, V>>,
@ -352,7 +383,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
/// Finds the length of the node. This is the number of keys or values. In an
/// internal node, the number of edges is `len() + 1`.
pub fn len(&self) -> usize {
self.as_leaf().len as usize
self.as_header().len as usize
}
/// Returns the height of this node in the whole tree. Zero height denotes the
@ -382,14 +413,19 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
}
}
fn as_leaf(&self) -> &LeafNode<K, V> {
/// Assert that this is indeed a proper leaf node, and not the shared root.
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
self.node.as_ref()
}
fn as_header(&self) -> &NodeHeader<K, V> {
unsafe {
self.node.as_ref()
&*(self.node.as_ptr() as *const NodeHeader<K, V>)
}
}
pub fn is_shared_root(&self) -> bool {
self.as_leaf().is_shared_root()
self.as_header().is_shared_root()
}
pub fn keys(&self) -> &[K] {
@ -418,7 +454,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
>,
Self
> {
let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
Ok(Handle {
node: NodeRef {
@ -427,7 +463,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
root: self.root,
_marker: PhantomData
},
idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
idx: unsafe { usize::from(*self.as_header().parent_idx.get_ref()) },
_marker: PhantomData
})
} else {
@ -534,10 +570,10 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
}
}
fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
unsafe {
self.node.as_mut()
}
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
// We are mutable, so we cannot be the root, so accessing this as a leaf is okay.
self.node.as_ptr()
}
fn keys_mut(&mut self) -> &mut [K] {
@ -551,28 +587,50 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
fn into_key_slice(self) -> &'a [K] {
// When taking a pointer to the keys, if our key has a stricter
// alignment requirement than the shared root does, then the pointer
// would be out of bounds, which LLVM assumes will not happen. If the
// alignment is more strict, we need to make an empty slice that doesn't
// use an out of bounds pointer.
// We have to be careful here because we might be pointing to the shared root.
// In that case, we must not create an `&LeafNode`. We could just return
// an empty slice whenever the length is 0 (this includes the shared root),
// but we want to avoid that run-time check.
// Instead, we create a slice pointing into the node whenever possible.
// We can sometimes do this even for the shared root, as the slice will be
// empty. We cannot *always* do this because if the type is too highly
// aligned, the offset of `keys` in a "full node" might be outside the bounds
// of the header! So we do an alignment check first, that will be
// evaluated at compile-time, and only do any run-time check in the rare case
// that the alignment is very big.
if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
&[]
} else {
// Here either it's not the root, or the alignment is less strict,
// in which case the keys pointer will point "one-past-the-end" of
// the node, which is allowed by LLVM.
// Thanks to the alignment check above, we know that `keys` will be
// in-bounds of some allocation even if this is the shared root!
// (We might be one-past-the-end, but that is allowed by LLVM.)
// Getting the pointer is tricky though. `NodeHeader` does not have a `keys`
// field because we want its size to not depend on the alignment of `K`
// (needed becuase `as_header` should be safe). We cannot call `as_leaf`
// because we might be the shared root.
// For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
// and hence just adds a size-0-align-1 field, not affecting layout).
// We know that we can transmute `NodeHeader<K, V, ()>` to `NodeHeader<K, V, K>`
// because we did the alignment check above, and hence `NodeHeader<K, V, K>`
// is not bigger than `NodeHeader<K, V, ()>`! Then we can use `NodeHeader<K, V, K>`
// to compute the pointer where the keys start.
// This entire hack will become unnecessary once
// <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
// pointer to the `keys` field of `*const InternalNode<K, V>`.
// This is a non-debug-assert because it can be completely compile-time evaluated.
assert!(mem::size_of::<NodeHeader<K, V>>() == mem::size_of::<NodeHeader<K, V, K>>());
let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
let keys = unsafe { &(*header).keys_start as *const _ as *const K };
unsafe {
slice::from_raw_parts(
self.as_leaf().keys.as_ptr() as *const K,
self.len()
)
slice::from_raw_parts(keys, self.len())
}
}
}
fn into_val_slice(self) -> &'a [V] {
debug_assert!(!self.is_shared_root());
// We cannot be the root, so `as_leaf` is okay
unsafe {
slice::from_raw_parts(
self.as_leaf().vals.as_ptr() as *const V,
@ -602,7 +660,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
} else {
unsafe {
slice::from_raw_parts_mut(
self.as_leaf_mut().keys.as_mut_ptr() as *mut K,
(*self.as_leaf_mut()).keys.as_mut_ptr() as *mut K,
self.len()
)
}
@ -613,7 +671,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
debug_assert!(!self.is_shared_root());
unsafe {
slice::from_raw_parts_mut(
self.as_leaf_mut().vals.as_mut_ptr() as *mut V,
(*self.as_leaf_mut()).vals.as_mut_ptr() as *mut V,
self.len()
)
}
@ -637,9 +695,9 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
unsafe {
ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
}
self.as_leaf_mut().len += 1;
(*self.as_leaf_mut()).len += 1;
}
}
/// Adds a key/value pair to the beginning of the node.
@ -651,9 +709,9 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
unsafe {
slice_insert(self.keys_mut(), 0, key);
slice_insert(self.vals_mut(), 0, val);
}
self.as_leaf_mut().len += 1;
(*self.as_leaf_mut()).len += 1;
}
}
}
@ -672,7 +730,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
ptr::write(self.as_internal_mut().edges.get_unchecked_mut(idx + 1), edge.node);
self.as_leaf_mut().len += 1;
(*self.as_leaf_mut()).len += 1;
Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
}
@ -708,7 +766,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
edge.node
);
self.as_leaf_mut().len += 1;
(*self.as_leaf_mut()).len += 1;
self.correct_all_childrens_parent_links();
}
@ -732,12 +790,12 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
ForceResult::Internal(internal) => {
let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1));
let mut new_root = Root { node: edge, height: internal.height - 1 };
new_root.as_mut().as_leaf_mut().parent = ptr::null();
(*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
Some(new_root)
}
};
self.as_leaf_mut().len -= 1;
(*self.as_leaf_mut()).len -= 1;
(key, val, edge)
}
}
@ -765,7 +823,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
);
let mut new_root = Root { node: edge, height: internal.height - 1 };
new_root.as_mut().as_leaf_mut().parent = ptr::null();
(*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
for i in 0..old_len {
Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
@ -775,7 +833,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
}
};
self.as_leaf_mut().len -= 1;
(*self.as_leaf_mut()).len -= 1;
(key, val, edge)
}
@ -966,7 +1024,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
slice_insert(self.node.keys_mut(), self.idx, key);
slice_insert(self.node.vals_mut(), self.idx, val);
self.node.as_leaf_mut().len += 1;
(*self.node.as_leaf_mut()).len += 1;
self.node.vals_mut().get_unchecked_mut(self.idx)
}
@ -1009,8 +1067,10 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let idx = self.idx as u16;
let ptr = self.node.as_internal_mut() as *mut _;
let mut child = self.descend();
child.as_leaf_mut().parent = ptr;
child.as_leaf_mut().parent_idx.set(idx);
unsafe {
(*child.as_leaf_mut()).parent = ptr;
(*child.as_leaf_mut()).parent_idx.set(idx);
}
}
/// Unsafely asserts to the compiler some static information about whether the underlying
@ -1158,7 +1218,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
new_len
);
self.node.as_leaf_mut().len = self.idx as u16;
(*self.node.as_leaf_mut()).len = self.idx as u16;
new_node.len = new_len as u16;
(
@ -1180,7 +1240,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
unsafe {
let k = slice_remove(self.node.keys_mut(), self.idx);
let v = slice_remove(self.node.vals_mut(), self.idx);
self.node.as_leaf_mut().len -= 1;
(*self.node.as_leaf_mut()).len -= 1;
(self.left_edge(), k, v)
}
}
@ -1221,7 +1281,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
new_len + 1
);
self.node.as_leaf_mut().len = self.idx as u16;
(*self.node.as_leaf_mut()).len = self.idx as u16;
new_node.data.len = new_len as u16;
let mut new_root = Root {
@ -1295,9 +1355,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
for i in self.idx+1..self.node.len() {
Handle::new_edge(self.node.reborrow_mut(), i).correct_parent_link();
}
self.node.as_leaf_mut().len -= 1;
(*self.node.as_leaf_mut()).len -= 1;
left_node.as_leaf_mut().len += right_len as u16 + 1;
(*left_node.as_leaf_mut()).len += right_len as u16 + 1;
if self.node.height > 1 {
ptr::copy_nonoverlapping(
@ -1407,8 +1467,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
move_kv(left_kv, new_left_len, parent_kv, 0, 1);
}
left_node.reborrow_mut().as_leaf_mut().len -= count as u16;
right_node.reborrow_mut().as_leaf_mut().len += count as u16;
(*left_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
(*right_node.reborrow_mut().as_leaf_mut()).len += count as u16;
match (left_node.force(), right_node.force()) {
(ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@ -1468,8 +1528,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
new_right_len);
}
left_node.reborrow_mut().as_leaf_mut().len += count as u16;
right_node.reborrow_mut().as_leaf_mut().len -= count as u16;
(*left_node.reborrow_mut().as_leaf_mut()).len += count as u16;
(*right_node.reborrow_mut().as_leaf_mut()).len -= count as u16;
match (left_node.force(), right_node.force()) {
(ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
@ -1560,8 +1620,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, ma
move_kv(left_kv, left_new_len, right_kv, 0, right_new_len);
left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16;
right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16;
(*left_node.reborrow_mut().as_leaf_mut()).len = left_new_len as u16;
(*right_node.reborrow_mut().as_leaf_mut()).len = right_new_len as u16;
match (left_node.force(), right_node.force()) {
(ForceResult::Internal(left), ForceResult::Internal(right)) => {

View File

@ -627,7 +627,9 @@ impl<T> LinkedList<T> {
self.pop_front_node().map(Node::into_element)
}
/// Appends an element to the back of a list
/// Appends an element to the back of a list.
///
/// This operation should compute in O(1) time.
///
/// # Examples
///
@ -647,6 +649,8 @@ impl<T> LinkedList<T> {
/// Removes the last element from a list and returns it, or `None` if
/// it is empty.
///
/// This operation should compute in O(1) time.
///
/// # Examples
///
/// ```

View File

@ -609,10 +609,15 @@ pub trait Debug {
/// println!("The origin is: {}", origin);
/// ```
#[rustc_on_unimplemented(
on(
_Self="std::path::Path",
label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
note="call `.display()` or `.to_string_lossy()` to safely print paths, \
as they may contain non-Unicode data"
),
message="`{Self}` doesn't implement `{Display}`",
label="`{Self}` cannot be formatted with the default formatter",
note="in format strings you may be able to use `{{:?}}` \
(or {{:#?}} for pretty-print) instead",
note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
)]
#[doc(alias = "{}")]
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -70,7 +70,7 @@ assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", st
#[stable(feature = "nonzero", since = "1.28.0")]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
$Ty(unsafe { NonZero(n) })
$Ty(NonZero(n))
}
/// Create a non-zero if the given value is not zero.
@ -2150,19 +2150,6 @@ impl isize {
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" }
}
// Emits the correct `cttz` call, depending on the size of the type.
macro_rules! uint_cttz_call {
// As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
// emits two conditional moves on x86_64. By promoting the value to
// u16 and setting bit 8, we get better code without any conditional
// operations.
// FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
// pending, remove this workaround once LLVM generates better code
// for cttz8.
($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) };
($value:expr, $_BITS:expr) => { intrinsics::cttz($value) }
}
// `Int` + `UnsignedInt` implemented for unsigned integers
macro_rules! uint_impl {
($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
@ -2306,7 +2293,7 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
#[rustc_const_unstable(feature = "const_int_ops")]
#[inline]
pub const fn trailing_zeros(self) -> u32 {
unsafe { uint_cttz_call!(self, $BITS) as u32 }
unsafe { intrinsics::cttz(self) as u32 }
}
}

View File

@ -2928,7 +2928,7 @@ impl<T: ?Sized> NonNull<T> {
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
NonNull { pointer: unsafe { NonZero(ptr as _) } }
NonNull { pointer: NonZero(ptr as _) }
}
/// Creates a new `NonNull` if `ptr` is non-null.

View File

@ -1072,6 +1072,15 @@ impl<T> AtomicPtr<T> {
#[cfg(target_has_atomic = "8")]
#[stable(feature = "atomic_bool_from", since = "1.24.0")]
impl From<bool> for AtomicBool {
/// Converts a `bool` into an `AtomicBool`.
///
/// # Examples
///
/// ```
/// use std::sync::atomic::AtomicBool;
/// let atomic_bool = AtomicBool::from(true);
/// assert_eq!(format!("{:?}", atomic_bool), "true")
/// ```
#[inline]
fn from(b: bool) -> Self { Self::new(b) }
}
@ -1126,8 +1135,12 @@ macro_rules! atomic_int {
#[$stable_from]
impl From<$int_type> for $atomic_type {
#[inline]
fn from(v: $int_type) -> Self { Self::new(v) }
doc_comment! {
concat!(
"Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`."),
#[inline]
fn from(v: $int_type) -> Self { Self::new(v) }
}
}
#[$stable_debug]

View File

@ -36,6 +36,7 @@ use traits::{Obligation, ObligationCause, PredicateObligation};
use ty::fold::TypeFoldable;
use ty::subst::{Kind, UnpackedKind};
use ty::{self, BoundVar, Lift, Ty, TyCtxt};
use util::captures::Captures;
impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
/// The "main method" for a canonicalized trait query. Given the
@ -527,32 +528,30 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
result_subst: &'a CanonicalVarValues<'tcx>,
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
Box::new(
unsubstituted_region_constraints
.iter()
.map(move |constraint| {
let constraint = substitute_value(self.tcx, result_subst, constraint);
let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'gcx> {
unsubstituted_region_constraints
.iter()
.map(move |constraint| {
let constraint = substitute_value(self.tcx, result_subst, constraint);
let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
Obligation::new(
cause.clone(),
param_env,
match k1.unpack() {
UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
ty::Binder::bind(
ty::OutlivesPredicate(r1, r2)
)
),
UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
ty::Binder::bind(
ty::OutlivesPredicate(t1, r2)
)
),
}
)
})
) as Box<dyn Iterator<Item = _>>
Obligation::new(
cause.clone(),
param_env,
match k1.unpack() {
UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
ty::Binder::bind(
ty::OutlivesPredicate(r1, r2)
)
),
UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
ty::Binder::bind(
ty::OutlivesPredicate(t1, r2)
)
),
}
)
})
}
/// Given two sets of values for the same set of canonical variables, unify them.

View File

@ -1657,11 +1657,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
if let Some(name) = self.should_warn(var) {
if is_argument {
self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
&format!("value passed to `{}` is never read", name));
self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
&format!("value passed to `{}` is never read", name))
.help("maybe it is overwritten before being read?")
.emit();
} else {
self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
&format!("value assigned to `{}` is never read", name));
self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
&format!("value assigned to `{}` is never read", name))
.help("maybe it is overwritten before being read?")
.emit();
}
}
}

View File

@ -1754,17 +1754,19 @@ bitflags! {
pub struct AdtFlags: u32 {
const NO_ADT_FLAGS = 0;
const IS_ENUM = 1 << 0;
const IS_PHANTOM_DATA = 1 << 1;
const IS_FUNDAMENTAL = 1 << 2;
const IS_UNION = 1 << 3;
const IS_BOX = 1 << 4;
const IS_UNION = 1 << 1;
const IS_STRUCT = 1 << 2;
const HAS_CTOR = 1 << 3;
const IS_PHANTOM_DATA = 1 << 4;
const IS_FUNDAMENTAL = 1 << 5;
const IS_BOX = 1 << 6;
/// Indicates whether the type is an `Arc`.
const IS_ARC = 1 << 5;
const IS_ARC = 1 << 7;
/// Indicates whether the type is an `Rc`.
const IS_RC = 1 << 6;
const IS_RC = 1 << 8;
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
/// (i.e., this flag is never set unless this ADT is an enum).
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
}
}
@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
repr: ReprOptions) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
let attrs = tcx.get_attrs(did);
if attr::contains_name(&attrs, "fundamental") {
flags = flags | AdtFlags::IS_FUNDAMENTAL;
}
if Some(did) == tcx.lang_items().phantom_data() {
flags = flags | AdtFlags::IS_PHANTOM_DATA;
}
if Some(did) == tcx.lang_items().owned_box() {
flags = flags | AdtFlags::IS_BOX;
}
if Some(did) == tcx.lang_items().arc() {
flags = flags | AdtFlags::IS_ARC;
}
if Some(did) == tcx.lang_items().rc() {
flags = flags | AdtFlags::IS_RC;
}
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
}
match kind {
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
AdtKind::Struct => {}
flags |= match kind {
AdtKind::Enum => AdtFlags::IS_ENUM,
AdtKind::Union => AdtFlags::IS_UNION,
AdtKind::Struct => AdtFlags::IS_STRUCT,
};
if let AdtKind::Struct = kind {
let variant_def = &variants[VariantIdx::new(0)];
let def_key = tcx.def_key(variant_def.did);
match def_key.disambiguated_data.data {
DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
_ => (),
}
}
let attrs = tcx.get_attrs(did);
if attr::contains_name(&attrs, "fundamental") {
flags |= AdtFlags::IS_FUNDAMENTAL;
}
if Some(did) == tcx.lang_items().phantom_data() {
flags |= AdtFlags::IS_PHANTOM_DATA;
}
if Some(did) == tcx.lang_items().owned_box() {
flags |= AdtFlags::IS_BOX;
}
if Some(did) == tcx.lang_items().arc() {
flags |= AdtFlags::IS_ARC;
}
if Some(did) == tcx.lang_items().rc() {
flags |= AdtFlags::IS_RC;
}
AdtDef {
did,
variants,
@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {
#[inline]
pub fn is_struct(&self) -> bool {
!self.is_union() && !self.is_enum()
self.flags.contains(AdtFlags::IS_STRUCT)
}
#[inline]
pub fn is_union(&self) -> bool {
self.flags.intersects(AdtFlags::IS_UNION)
self.flags.contains(AdtFlags::IS_UNION)
}
#[inline]
pub fn is_enum(&self) -> bool {
self.flags.intersects(AdtFlags::IS_ENUM)
self.flags.contains(AdtFlags::IS_ENUM)
}
#[inline]
pub fn is_variant_list_non_exhaustive(&self) -> bool {
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}
/// Returns the kind of the ADT - Struct or Enum.
/// Returns the kind of the ADT.
#[inline]
pub fn adt_kind(&self) -> AdtKind {
if self.is_enum() {
@ -2161,33 +2175,39 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}
}
/// Returns whether this type is #[fundamental] for the purposes
/// If this function returns `true`, it implies that `is_struct` must return `true`.
#[inline]
pub fn has_ctor(&self) -> bool {
self.flags.contains(AdtFlags::HAS_CTOR)
}
/// Returns whether this type is `#[fundamental]` for the purposes
/// of coherence checking.
#[inline]
pub fn is_fundamental(&self) -> bool {
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
}
/// Returns `true` if this is PhantomData<T>.
#[inline]
pub fn is_phantom_data(&self) -> bool {
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
}
/// Returns `true` if this is `Arc<T>`.
pub fn is_arc(&self) -> bool {
self.flags.intersects(AdtFlags::IS_ARC)
self.flags.contains(AdtFlags::IS_ARC)
}
/// Returns `true` if this is `Rc<T>`.
pub fn is_rc(&self) -> bool {
self.flags.intersects(AdtFlags::IS_RC)
self.flags.contains(AdtFlags::IS_RC)
}
/// Returns `true` if this is Box<T>.
#[inline]
pub fn is_box(&self) -> bool {
self.flags.intersects(AdtFlags::IS_BOX)
self.flags.contains(AdtFlags::IS_BOX)
}
/// Returns whether this type has a destructor.

View File

@ -1192,7 +1192,7 @@ fn generic_simd_intrinsic(
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
}
// every intrinsic takes a SIMD vector as its first argument
// every intrinsic below takes a SIMD vector as its first argument
require_simd!(arg_tys[0], "input");
let in_ty = arg_tys[0];
let in_elem = arg_tys[0].simd_type(tcx);
@ -1296,6 +1296,7 @@ fn generic_simd_intrinsic(
if name == "simd_select" {
let m_elem_ty = in_elem;
let m_len = in_len;
require_simd!(arg_tys[1], "argument");
let v_len = arg_tys[1].simd_size(tcx);
require!(m_len == v_len,
"mismatched lengths: mask length `{}` != other vector length `{}`",

View File

@ -140,6 +140,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[
("avx512vpopcntdq", Some("avx512_target_feature")),
("bmi1", None),
("bmi2", None),
("cmpxchg16b", Some("cmpxchg16b_target_feature")),
("fma", None),
("fxsr", None),
("lzcnt", None),
@ -212,6 +213,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
("x86", "pclmulqdq") => "pclmul",
("x86", "rdrand") => "rdrnd",
("x86", "bmi1") => "bmi",
("x86", "cmpxchg16b") => "cx16",
("aarch64", "fp") => "fp-armv8",
("aarch64", "fp16") => "fullfp16",
(_, s) => s,

View File

@ -545,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
self.mutate_place(
ContextKind::SetDiscrim.new(location),
(place, span),
Shallow(Some(ArtificialField::Discriminant)),
Shallow(None),
JustWrite,
flow_state,
);
@ -782,7 +782,6 @@ use self::AccessDepth::{Deep, Shallow};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum ArtificialField {
Discriminant,
ArrayLength,
ShallowBorrow,
}
@ -1191,14 +1190,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
let af = match *rvalue {
Rvalue::Len(..) => ArtificialField::ArrayLength,
Rvalue::Discriminant(..) => ArtificialField::Discriminant,
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
};
self.access_place(
context,
(place, span),
(Shallow(Some(af)), Read(ReadKind::Copy)),
(Shallow(af), Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
flow_state,
);

View File

@ -99,7 +99,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
self.mutate_place(
ContextKind::SetDiscrim.new(location),
place,
Shallow(Some(ArtificialField::Discriminant)),
Shallow(None),
JustWrite,
);
}
@ -360,14 +360,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
let af = match *rvalue {
Rvalue::Len(..) => ArtificialField::ArrayLength,
Rvalue::Discriminant(..) => ArtificialField::Discriminant,
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
};
self.access_place(
context,
place,
(Shallow(Some(af)), Read(ReadKind::Copy)),
(Shallow(af), Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
);
}

View File

@ -165,15 +165,12 @@ fn place_components_conflict<'gcx, 'tcx>(
let base_ty = base.ty(mir, tcx).to_ty(tcx);
match (elem, &base_ty.sty, access) {
(_, _, Shallow(Some(ArtificialField::Discriminant)))
| (_, _, Shallow(Some(ArtificialField::ArrayLength)))
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
| (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
// The discriminant and array length are like
// additional fields on the type; they do not
// overlap any existing data there. Furthermore,
// they cannot actually be a prefix of any
// borrowed place (at least in MIR as it is
// currently.)
// The array length is like additional fields on the
// type; it does not overlap any existing data there.
// Furthermore, if cannot actually be a prefix of any
// borrowed place (at least in MIR as it is currently.)
//
// e.g., a (mutable) borrow of `a[5]` while we read the
// array length of `a`.

View File

@ -111,13 +111,6 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe if tcx.is_min_const_fn(fn_def_id) => {
// As specified in #55607, a `const unsafe fn` differs
// from an `unsafe fn` in that its body is still considered
// safe code by default.
assert!(implicit_argument.is_none());
Safety::Safe
},
hir::Unsafety::Unsafe => Safety::FnUnsafe,
};

View File

@ -311,13 +311,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
violations: &[UnsafetyViolation],
unsafe_blocks: &[(ast::NodeId, bool)]) {
let safety = self.source_scope_local_data[self.source_info.scope].safety;
let within_unsafe = match (safety, self.min_const_fn) {
// Erring on the safe side, pun intended
(Safety::BuiltinUnsafe, true) |
// mir building encodes const fn bodies as safe, even for `const unsafe fn`
(Safety::FnUnsafe, true) => bug!("const unsafe fn body treated as inherently unsafe"),
let within_unsafe = match safety {
// `unsafe` blocks are required in safe code
(Safety::Safe, _) => {
Safety::Safe => {
for violation in violations {
let mut violation = violation.clone();
match violation.kind {
@ -342,9 +338,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
}
false
}
// regular `unsafe` function bodies allow unsafe without additional unsafe blocks
(Safety::BuiltinUnsafe, false) | (Safety::FnUnsafe, false) => true,
(Safety::ExplicitUnsafe(node_id), _) => {
// `unsafe` function bodies allow unsafe without additional unsafe blocks
Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
Safety::ExplicitUnsafe(node_id) => {
// mark unsafe block as used if there are any unsafe operations inside
if !violations.is_empty() {
self.used_unsafe.insert(node_id);
@ -616,21 +612,6 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
} in violations.iter() {
// Report an error.
match kind {
UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
let mut err = tcx.sess.struct_span_err(
source_info.span,
&format!("{} is unsafe and unsafe operations \
are not allowed in const fn", description));
err.span_label(source_info.span, &description.as_str()[..])
.note(&details.as_str()[..]);
if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
err.note(
"unsafe action within a `const unsafe fn` still require an `unsafe` \
block in contrast to regular `unsafe fn`."
);
}
err.emit();
}
UnsafetyViolationKind::GeneralAndConstFn |
UnsafetyViolationKind::General => {
struct_span_err!(

View File

@ -41,7 +41,6 @@ pub mod ast_validation;
pub mod rvalue_promotion;
pub mod hir_stats;
pub mod loops;
mod mir_stats;
__build_diagnostic_array! { librustc_passes, DIAGNOSTICS }

View File

@ -1,256 +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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// The visitors in this module collect sizes and counts of the most important
// pieces of MIR. The resulting numbers are good approximations but not
// completely accurate (some things might be counted twice, others missed).
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
use rustc::mir::{Constant, Location, Local, LocalDecl};
use rustc::mir::{Place, PlaceElem, PlaceProjection};
use rustc::mir::{Mir, Operand, ProjectionElem};
use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind, SourceScope, SourceScopeData};
use rustc::mir::interpret::EvalErrorKind;
use rustc::mir::visit as mir_visit;
use rustc::ty::{self, ClosureSubsts, TyCtxt};
use rustc::util::nodemap::{FxHashMap};
struct NodeData {
count: usize,
size: usize,
}
struct StatCollector<'a, 'tcx: 'a> {
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
data: FxHashMap<&'static str, NodeData>,
}
impl<'a, 'tcx> StatCollector<'a, 'tcx> {
fn record_with_size(&mut self, label: &'static str, node_size: usize) {
let entry = self.data.entry(label).or_insert(NodeData {
count: 0,
size: 0,
});
entry.count += 1;
entry.size = node_size;
}
fn record<T>(&mut self, label: &'static str, node: &T) {
self.record_with_size(label, ::std::mem::size_of_val(node));
}
}
impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
fn visit_mir(&mut self, mir: &Mir<'tcx>) {
self.record("Mir", mir);
// since the `super_mir` method does not traverse the MIR of
// promoted rvalues, (but we still want to gather statistics
// on the structures represented there) we manually traverse
// the promoted rvalues here.
for promoted_mir in &mir.promoted {
self.visit_mir(promoted_mir);
}
self.super_mir(mir);
}
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
self.record("BasicBlockData", data);
self.super_basic_block_data(block, data);
}
fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) {
self.record("SourceScopeData", scope_data);
self.super_source_scope_data(scope_data);
}
fn visit_statement(&mut self,
block: BasicBlock,
statement: &Statement<'tcx>,
location: Location) {
self.record("Statement", statement);
self.record(match statement.kind {
StatementKind::Assign(..) => "StatementKind::Assign",
StatementKind::FakeRead(..) => "StatementKind::FakeRead",
StatementKind::Retag { .. } => "StatementKind::Retag",
StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw",
StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType",
StatementKind::Nop => "StatementKind::Nop",
}, &statement.kind);
self.super_statement(block, statement, location);
}
fn visit_terminator(&mut self,
block: BasicBlock,
terminator: &Terminator<'tcx>,
location: Location) {
self.record("Terminator", terminator);
self.super_terminator(block, terminator, location);
}
fn visit_terminator_kind(&mut self,
block: BasicBlock,
kind: &TerminatorKind<'tcx>,
location: Location) {
self.record("TerminatorKind", kind);
self.record(match *kind {
TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
TerminatorKind::Resume => "TerminatorKind::Resume",
TerminatorKind::Abort => "TerminatorKind::Abort",
TerminatorKind::Return => "TerminatorKind::Return",
TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace",
TerminatorKind::Call { .. } => "TerminatorKind::Call",
TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
}, kind);
self.super_terminator_kind(block, kind, location);
}
fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) {
self.record("AssertMessage", msg);
self.record(match *msg {
EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
EvalErrorKind::GeneratorResumedAfterReturn => {
"AssertMessage::GeneratorResumedAfterReturn"
}
EvalErrorKind::GeneratorResumedAfterPanic => {
"AssertMessage::GeneratorResumedAfterPanic"
}
_ => bug!(),
}, msg);
self.super_assert_message(msg, location);
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
self.record("Rvalue", rvalue);
let rvalue_kind = match *rvalue {
Rvalue::Use(..) => "Rvalue::Use",
Rvalue::Repeat(..) => "Rvalue::Repeat",
Rvalue::Ref(..) => "Rvalue::Ref",
Rvalue::Len(..) => "Rvalue::Len",
Rvalue::Cast(..) => "Rvalue::Cast",
Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
Rvalue::Discriminant(..) => "Rvalue::Discriminant",
Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
Rvalue::Aggregate(ref kind, ref _operands) => {
// AggregateKind is not distinguished by visit API, so
// record it. (`super_rvalue` handles `_operands`.)
self.record(match **kind {
AggregateKind::Array(_) => "AggregateKind::Array",
AggregateKind::Tuple => "AggregateKind::Tuple",
AggregateKind::Adt(..) => "AggregateKind::Adt",
AggregateKind::Closure(..) => "AggregateKind::Closure",
AggregateKind::Generator(..) => "AggregateKind::Generator",
}, kind);
"Rvalue::Aggregate"
}
};
self.record(rvalue_kind, rvalue);
self.super_rvalue(rvalue, location);
}
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
self.record("Operand", operand);
self.record(match *operand {
Operand::Copy(..) => "Operand::Copy",
Operand::Move(..) => "Operand::Move",
Operand::Constant(..) => "Operand::Constant",
}, operand);
self.super_operand(operand, location);
}
fn visit_place(&mut self,
place: &Place<'tcx>,
context: mir_visit::PlaceContext<'tcx>,
location: Location) {
self.record("Place", place);
self.record(match *place {
Place::Local(..) => "Place::Local",
Place::Static(..) => "Place::Static",
Place::Promoted(..) => "Place::Promoted",
Place::Projection(..) => "Place::Projection",
}, place);
self.super_place(place, context, location);
}
fn visit_projection(&mut self,
place: &PlaceProjection<'tcx>,
context: mir_visit::PlaceContext<'tcx>,
location: Location) {
self.record("PlaceProjection", place);
self.super_projection(place, context, location);
}
fn visit_projection_elem(&mut self,
place: &PlaceElem<'tcx>,
location: Location) {
self.record("PlaceElem", place);
self.record(match *place {
ProjectionElem::Deref => "PlaceElem::Deref",
ProjectionElem::Subslice { .. } => "PlaceElem::Subslice",
ProjectionElem::Field(..) => "PlaceElem::Field",
ProjectionElem::Index(..) => "PlaceElem::Index",
ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex",
ProjectionElem::Downcast(..) => "PlaceElem::Downcast",
}, place);
self.super_projection_elem(place, location);
}
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
self.record("Constant", constant);
self.super_constant(constant, location);
}
fn visit_source_info(&mut self, source_info: &SourceInfo) {
self.record("SourceInfo", source_info);
self.super_source_info(source_info);
}
fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) {
self.record("ClosureSubsts", substs);
self.super_closure_substs(substs);
}
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
self.record("Const", constant);
self.super_const(constant);
}
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
self.record("LocalDecl", local_decl);
self.super_local_decl(local, local_decl);
}
fn visit_source_scope(&mut self, scope: &SourceScope) {
self.record("VisiblityScope", scope);
self.super_source_scope(scope);
}
}

View File

@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Def::Local(id) | Def::Upvar(id, ..) => {
Some(self.tcx.hir().span(id))
}
_ => self.tcx.hir().span_if_local(def.def_id())
_ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)),
};
if let Some(span) = def_span {
let label = match (unit_variant, inner_callee_path) {

View File

@ -95,7 +95,7 @@ mod op;
use astconv::AstConv;
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use rustc::hir::{self, GenericArg, Node, ItemKind, PatKind};
use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind};
use rustc::hir::def::Def;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@ -113,7 +113,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
UserSelfTy, UserSubsts};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
RegionKind};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
@ -3217,8 +3218,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return_expr_ty);
}
// A generic function for checking the then and else in an if
// or if-else.
// A generic function for checking the 'then' and 'else' clauses in an 'if'
// or 'if-else' expression.
fn check_then_else(&self,
cond_expr: &'gcx hir::Expr,
then_expr: &'gcx hir::Expr,
@ -3544,7 +3545,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// We don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not
// a bug to have constructed one.
if adt_kind != ty::AdtKind::Enum {
if adt_kind != AdtKind::Enum {
tcx.check_stability(v_field.did, Some(expr_id), field.span);
}
@ -5156,26 +5157,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}).unwrap_or(false);
let mut new_def = def;
let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let (def_id, ty) = match def {
Def::SelfCtor(impl_def_id) => {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();
match ty.ty_adt_def() {
Some(adt_def) if adt_def.is_struct() => {
let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, self.tcx.type_of(variant.did))
}
_ => {
(impl_def_id, self.tcx.types.err)
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, self.tcx.type_of(variant.did))
}
_ => {
let mut err = self.tcx.sess.struct_span_err(span,
"the `Self` constructor can only be used with tuple or unit structs");
if let Some(adt_def) = adt_def {
match adt_def.adt_kind() {
AdtKind::Enum => {
err.note("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_label(
span,
format!("did you mean `Self {{ /* fields */ }}`?"),
);
}
}
}
err.emit();
(impl_def_id, self.tcx.types.err)
}
}
}
} else {
let def_id = def.def_id();
_ => {
let def_id = def.def_id();
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = self.tcx.type_of(def_id);
(def_id, ty)
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = self.tcx.type_of(def_id);
(def_id, ty)
}
};
let substs = AstConv::create_substs_for_generic_args(

View File

@ -305,7 +305,7 @@ nav.sub {
overflow-x: auto;
}
body:not(.source) .example-wrap > pre {
.rustdoc:not(.source) .example-wrap > pre {
margin: 0;
}

View File

@ -395,6 +395,7 @@ pub fn make_test(s: &str,
// Now push any outer attributes from the example, assuming they
// are intended to be crate attributes.
prog.push_str(&crate_attrs);
prog.push_str(&crates);
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
// crate already is included.
@ -488,37 +489,78 @@ pub fn make_test(s: &str,
prog.push_str("\n}");
}
debug!("final doctest:\n{}", prog);
(prog, line_offset)
}
// FIXME(aburka): use a real parser to deal with multiline attributes
fn partition_source(s: &str) -> (String, String, String) {
let mut after_header = false;
#[derive(Copy, Clone, PartialEq)]
enum PartitionState {
Attrs,
Crates,
Other,
}
let mut state = PartitionState::Attrs;
let mut before = String::new();
let mut crates = String::new();
let mut after = String::new();
for line in s.lines() {
let trimline = line.trim();
let header = trimline.chars().all(|c| c.is_whitespace()) ||
trimline.starts_with("#![") ||
trimline.starts_with("#[macro_use] extern crate") ||
trimline.starts_with("extern crate");
if !header || after_header {
after_header = true;
after.push_str(line);
after.push_str("\n");
} else {
if trimline.starts_with("#[macro_use] extern crate")
|| trimline.starts_with("extern crate") {
// FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
// shunted into "everything else"
match state {
PartitionState::Attrs => {
state = if trimline.starts_with("#![") ||
trimline.chars().all(|c| c.is_whitespace()) ||
(trimline.starts_with("//") && !trimline.starts_with("///"))
{
PartitionState::Attrs
} else if trimline.starts_with("extern crate") ||
trimline.starts_with("#[macro_use] extern crate")
{
PartitionState::Crates
} else {
PartitionState::Other
};
}
PartitionState::Crates => {
state = if trimline.starts_with("extern crate") ||
trimline.starts_with("#[macro_use] extern crate") ||
trimline.chars().all(|c| c.is_whitespace()) ||
(trimline.starts_with("//") && !trimline.starts_with("///"))
{
PartitionState::Crates
} else {
PartitionState::Other
};
}
PartitionState::Other => {}
}
match state {
PartitionState::Attrs => {
before.push_str(line);
before.push_str("\n");
}
PartitionState::Crates => {
crates.push_str(line);
crates.push_str("\n");
}
before.push_str(line);
before.push_str("\n");
PartitionState::Other => {
after.push_str(line);
after.push_str("\n");
}
}
}
debug!("before:\n{}", before);
debug!("crates:\n{}", crates);
debug!("after:\n{}", after);
(before, after, crates)
}
@ -1035,8 +1077,8 @@ fn main() {
assert_eq!(2+2, 4);";
let expected =
"#![allow(unused)]
fn main() {
//Ceci n'est pas une `fn main`
fn main() {
assert_eq!(2+2, 4);
}".to_string();
let output = make_test(input, None, false, &opts);
@ -1083,8 +1125,8 @@ assert_eq!(2+2, 4);";
let expected =
"#![allow(unused)]
fn main() {
// fn main
fn main() {
assert_eq!(2+2, 4);
}".to_string();

View File

@ -21,6 +21,7 @@ libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of
compiler_builtins = { version = "0.1.1" }
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
unwind = { path = "../libunwind" }
rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
[dev-dependencies]
rand = "0.6.1"

View File

@ -550,7 +550,8 @@ impl f32 {
#[inline]
#[rustc_deprecated(since = "1.10.0",
reason = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` (also \
this operation is `(self - other).max(0.0)` \
except that `abs_sub` also propagates NaNs (also \
known as `fdimf` in C). If you truly need the positive \
difference, consider using that expression or the C function \
`fdimf`, depending on how you wish to handle NaN (please consider \

View File

@ -491,7 +491,8 @@ impl f64 {
#[inline]
#[rustc_deprecated(since = "1.10.0",
reason = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` (also \
this operation is `(self - other).max(0.0)` \
except that `abs_sub` also propagates NaNs (also \
known as `fdim` in C). If you truly need the positive \
difference, consider using that expression or the C function \
`fdim`, depending on how you wish to handle NaN (please consider \

View File

@ -1729,7 +1729,7 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
/// limited to just these cases:
///
/// * `path` does not exist.
/// * A component in path is not a directory.
/// * A non-final component in path is not a directory.
///
/// # Examples
///

View File

@ -339,6 +339,7 @@ pub use core::{unreachable, unimplemented, write, writeln, try};
extern crate alloc as alloc_crate;
#[doc(masked)]
extern crate libc;
extern crate rustc_demangle;
// We always need an unwinder currently for backtraces
#[doc(masked)]

View File

@ -27,6 +27,10 @@
all(target_os = "android", any(target_arch = "aarch64",
target_arch = "arm")),
all(target_os = "l4re", target_arch = "x86_64"),
all(target_os = "freebsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64")),
all(target_os = "netbsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc")),
@ -42,6 +46,10 @@
all(target_os = "android", any(target_arch = "aarch64",
target_arch = "arm")),
all(target_os = "l4re", target_arch = "x86_64"),
all(target_os = "freebsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64")),
all(target_os = "netbsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc")),

View File

@ -14,11 +14,12 @@
use env;
use io::prelude::*;
use io;
use path::{self, Path};
use ptr;
use rustc_demangle::demangle;
use str;
use sync::atomic::{self, Ordering};
use path::{self, Path};
use sys::mutex::Mutex;
use ptr;
pub use sys::backtrace::{
unwind_backtrace,
@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame,
PrintFormat::Short => write!(w, " {:2}: ", idx)?,
}
match s {
Some(string) => demangle(w, string, format)?,
Some(string) => {
let symbol = demangle(string);
match format {
PrintFormat::Full => write!(w, "{}", symbol)?,
// strip the trailing hash if short mode
PrintFormat::Short => write!(w, "{:#}", symbol)?,
}
}
None => w.write_all(b"<unknown>")?,
}
w.write_all(b"\n")
@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write,
w.write_all(b"\n")
}
// All rust symbols are in theory lists of "::"-separated identifiers. Some
// assemblers, however, can't handle these characters in symbol names. To get
// around this, we use C++-style mangling. The mangling method is:
//
// 1. Prefix the symbol with "_ZN"
// 2. For each element of the path, emit the length plus the element
// 3. End the path with "E"
//
// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
//
// We're the ones printing our backtraces, so we can't rely on anything else to
// demangle our symbols. It's *much* nicer to look at demangled symbols, so
// this function is implemented to give us nice pretty output.
//
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
// During ThinLTO LLVM may import and rename internal symbols, so strip out
// those endings first as they're one of the last manglings applied to
// symbol names.
let llvm = ".llvm.";
if let Some(i) = s.find(llvm) {
let candidate = &s[i + llvm.len()..];
let all_hex = candidate.chars().all(|c| {
match c {
'A' ..= 'F' | '0' ..= '9' => true,
_ => false,
}
});
if all_hex {
s = &s[..i];
}
}
// Validate the symbol. If it doesn't look like anything we're
// expecting, we just print it literally. Note that we must handle non-rust
// symbols because we could have any function in the backtrace.
let mut valid = true;
let mut inner = s;
if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
inner = &s[3 .. s.len() - 1];
// On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
} else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
inner = &s[2 .. s.len() - 1];
} else {
valid = false;
}
if valid {
let mut chars = inner.chars();
while valid {
let mut i = 0;
for c in chars.by_ref() {
if c.is_numeric() {
i = i * 10 + c as usize - '0' as usize;
} else {
break
}
}
if i == 0 {
valid = chars.next().is_none();
break
} else if chars.by_ref().take(i - 1).count() != i - 1 {
valid = false;
}
}
}
// Alright, let's do this.
if !valid {
writer.write_all(s.as_bytes())?;
} else {
// remove the `::hfc2edb670e5eda97` part at the end of the symbol.
if format == PrintFormat::Short {
// The symbol in still mangled.
let mut split = inner.rsplitn(2, "17h");
match (split.next(), split.next()) {
(Some(addr), rest) => {
if addr.len() == 16 &&
addr.chars().all(|c| c.is_digit(16))
{
inner = rest.unwrap_or("");
}
}
_ => (),
}
}
let mut first = true;
while !inner.is_empty() {
if !first {
writer.write_all(b"::")?;
} else {
first = false;
}
let mut rest = inner;
while rest.chars().next().unwrap().is_numeric() {
rest = &rest[1..];
}
let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
inner = &rest[i..];
rest = &rest[..i];
if rest.starts_with("_$") {
rest = &rest[1..];
}
while !rest.is_empty() {
if rest.starts_with(".") {
if let Some('.') = rest[1..].chars().next() {
writer.write_all(b"::")?;
rest = &rest[2..];
} else {
writer.write_all(b".")?;
rest = &rest[1..];
}
} else if rest.starts_with("$") {
macro_rules! demangle {
($($pat:expr => $demangled:expr),*) => ({
$(if rest.starts_with($pat) {
writer.write_all($demangled)?;
rest = &rest[$pat.len()..];
} else)*
{
writer.write_all(rest.as_bytes())?;
break;
}
})
}
// see src/librustc/back/link.rs for these mappings
demangle! (
"$SP$" => b"@",
"$BP$" => b"*",
"$RF$" => b"&",
"$LT$" => b"<",
"$GT$" => b">",
"$LP$" => b"(",
"$RP$" => b")",
"$C$" => b",",
// in theory we can demangle any Unicode code point, but
// for simplicity we just catch the common ones.
"$u7e$" => b"~",
"$u20$" => b" ",
"$u27$" => b"'",
"$u5b$" => b"[",
"$u5d$" => b"]",
"$u7b$" => b"{",
"$u7d$" => b"}",
"$u3b$" => b";",
"$u2b$" => b"+",
"$u22$" => b"\""
)
} else {
let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') {
None => rest.len(),
Some((i, _)) => i,
};
writer.write_all(rest[..idx].as_bytes())?;
rest = &rest[idx..];
}
}
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use sys_common;
macro_rules! t { ($a:expr, $b:expr) => ({
let mut m = Vec::new();
sys_common::backtrace::demangle(&mut m,
$a,
super::PrintFormat::Full).unwrap();
assert_eq!(String::from_utf8(m).unwrap(), $b);
}) }
#[test]
fn demangle() {
t!("test", "test");
t!("_ZN4testE", "test");
t!("_ZN4test", "_ZN4test");
t!("_ZN4test1a2bcE", "test::a::bc");
}
#[test]
fn demangle_dollars() {
t!("_ZN4$RP$E", ")");
t!("_ZN8$RF$testE", "&test");
t!("_ZN8$BP$test4foobE", "*test::foob");
t!("_ZN9$u20$test4foobE", " test::foob");
t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>");
}
#[test]
fn demangle_many_dollars() {
t!("_ZN13test$u20$test4foobE", "test test::foob");
t!("_ZN12test$BP$test4foobE", "test*test::foob");
}
#[test]
fn demangle_windows() {
t!("ZN4testE", "test");
t!("ZN13test$u20$test4foobE", "test test::foob");
t!("ZN12test$RF$test4foobE", "test&test::foob");
}
#[test]
fn demangle_elements_beginning_with_underscore() {
t!("_ZN13_$LT$test$GT$E", "<test>");
t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}");
t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR");
}
#[test]
fn demangle_trait_impls() {
t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
"<Test + 'static as foo::Bar<Test>>::bar");
}
}

@ -1 +1 @@
Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3
Subproject commit 95185c8c801c765ac1072392d081d265af9fb310

View File

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
2018-11-28
2018-12-13

View File

@ -0,0 +1,30 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:--test
// comments, both doc comments and regular ones, used to trick rustdoc's doctest parser into
// thinking that everything after it was part of the regular program. combined with the libsyntax
// parser loop failing to detect the manual main function, it would wrap everything in `fn main`,
// which would cause the doctest to fail as the "extern crate" declaration was no longer valid.
// oddly enough, it would pass in 2018 if a crate was in the extern prelude. see
// https://github.com/rust-lang/rust/issues/56727
//! ```
//! // crate: proc-macro-test
//! //! this is a test
//!
//! // used to pull in proc-macro specific items
//! extern crate proc_macro;
//!
//! use proc_macro::TokenStream;
//!
//! # fn main() {}
//! ```

View File

@ -1,3 +1,31 @@
warning[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:27:7
|
LL | Foo::Y(ref mut a, _) => a,
| --------- borrow of `y.0` occurs here
...
LL | Foo::Y(_, ref mut b) => b,
| ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
...
LL | *a += 1;
| ------- borrow later used here
|
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
It represents potential unsoundness in your code.
This warning will become a hard error in the future.
error[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:44:7
|
LL | Foo::Y(ref mut a, _) => a,
| --------- borrow of `y.0` occurs here
...
LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
| ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
...
LL | *a += 1;
| ------- borrow later used here
error[E0499]: cannot borrow `y.0` as mutable more than once at a time
--> $DIR/borrowck-anon-fields-variant.rs:44:14
|
@ -10,6 +38,7 @@ LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
LL | *a += 1;
| ------- first borrow later used here
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0499`.
Some errors occurred: E0499, E0503.
For more information about an error, try `rustc --explain E0499`.

View File

@ -28,13 +28,13 @@ const fn call_unsafe_generic_cell_const_fn() -> *const Vec<std::cell::Cell<u32>>
unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
//~^ ERROR calls to `const unsafe fn` in const fns
}
const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
//~^ dereferencing raw pointers in constant functions
fn main() {}
const unsafe fn no_union() {
union Foo { x: (), y: () }
Foo { x: () }.y //~ ERROR not allowed in const fn
Foo { x: () }.y
//~^ unions in const fn
}

View File

@ -1,7 +1,7 @@
error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
--> $DIR/min_const_fn_unsafe.rs:31:59
|
LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
| ^^
|
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
@ -9,7 +9,7 @@ LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR no
error[E0658]: unions in const fn are unstable (see issue #51909)
--> $DIR/min_const_fn_unsafe.rs:38:5
|
LL | Foo { x: () }.y //~ ERROR not allowed in const fn
LL | Foo { x: () }.y
| ^^^^^^^^^^^^^^^
|
= help: add #![feature(const_fn_union)] to the crate attributes to enable
@ -38,24 +38,6 @@ LL | unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
|
= help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe.rs:31:59
|
LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
| ^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: access to union field is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe.rs:38:5
|
LL | Foo { x: () }.y //~ ERROR not allowed in const fn
| ^^^^^^^^^^^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: aborting due to 7 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -34,29 +34,28 @@ const unsafe fn foo9_3() -> *const String {
const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
}
// not ok
const unsafe fn foo8_2() -> i32 {
foo4() //~ ERROR not allowed in const fn
foo4()
}
const unsafe fn foo9_2() -> *const String {
foo5::<String>() //~ ERROR not allowed in const fn
foo5::<String>()
}
const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
foo6::<Vec<std::cell::Cell<u32>>>()
}
const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
//~^ dereferencing raw pointers in constant functions
const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
//~^ dereferencing raw pointers in constant functions
const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
//~^ dereferencing raw pointers in constant functions
fn main() {}
const unsafe fn no_union() {
union Foo { x: (), y: () }
Foo { x: () }.y //~ ERROR not allowed in const fn
Foo { x: () }.y
//~^ unions in const fn
}

View File

@ -1,97 +1,44 @@
error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
--> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
--> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51
|
LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
| ^^
|
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
--> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
--> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60
|
LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
| ^^^
|
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
--> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
--> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
|
LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
| ^^^
|
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
error[E0658]: unions in const fn are unstable (see issue #51909)
--> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
--> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5
|
LL | Foo { x: () }.y //~ ERROR not allowed in const fn
LL | Foo { x: () }.y
| ^^^^^^^^^^^^^^^
|
= help: add #![feature(const_fn_union)] to the crate attributes to enable
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:39:5
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
--> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
|
LL | foo4() //~ ERROR not allowed in const fn
| ^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:42:5
|
LL | foo5::<String>() //~ ERROR not allowed in const fn
| ^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:45:5
|
LL | foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
|
LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
| ^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
|
LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR not allowed in const fn
| ^^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
|
LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ ERROR not allowed
LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
| ^^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
error: access to union field is unsafe and unsafe operations are not allowed in const fn
--> $DIR/min_const_fn_unsafe_feature_gate.rs:60:5
|
LL | Foo { x: () }.y //~ ERROR not allowed in const fn
| ^^^^^^^^^^^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
= note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
error: aborting due to 5 previous errors
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0658`.
Some errors occurred: E0133, E0658.
For more information about an error, try `rustc --explain E0133`.

View File

@ -0,0 +1,23 @@
enum Foo {}
struct Bar {}
impl Foo {
fn foo() {
let _ = Self;
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
let _ = Self();
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
}
}
impl Bar {
fn bar() {
let _ = Self;
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
let _ = Self();
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
}
}
fn main() {}

View File

@ -0,0 +1,30 @@
error: the `Self` constructor can only be used with tuple or unit structs
--> $DIR/issue-56199.rs:7:17
|
LL | let _ = Self;
| ^^^^
|
= note: did you mean to use one of the enum's variants?
error: the `Self` constructor can only be used with tuple or unit structs
--> $DIR/issue-56199.rs:9:17
|
LL | let _ = Self();
| ^^^^
|
= note: did you mean to use one of the enum's variants?
error: the `Self` constructor can only be used with tuple or unit structs
--> $DIR/issue-56199.rs:16:17
|
LL | let _ = Self;
| ^^^^ did you mean `Self { /* fields */ }`?
error: the `Self` constructor can only be used with tuple or unit structs
--> $DIR/issue-56199.rs:18:17
|
LL | let _ = Self();
| ^^^^ did you mean `Self { /* fields */ }`?
error: aborting due to 4 previous errors

View File

@ -0,0 +1,10 @@
pub struct Foo {}
impl Foo {
fn bar(Self(foo): Self) {}
//~^ ERROR the `Self` constructor can only be used with tuple or unit structs
//~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164]
}
fn main() {}

View File

@ -0,0 +1,15 @@
error: the `Self` constructor can only be used with tuple or unit structs
--> $DIR/issue-56835.rs:5:12
|
LL | fn bar(Self(foo): Self) {}
| ^^^^^^^^^ did you mean `Self { /* fields */ }`?
error[E0164]: expected tuple struct/variant, found self constructor `Self`
--> $DIR/issue-56835.rs:5:12
|
LL | fn bar(Self(foo): Self) {}
| ^^^^^^^^^ not a tuple variant or struct
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0164`.

View File

@ -55,6 +55,7 @@ note: lint level defined here
LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
| ^^^^^^
= note: #[warn(unused_assignments)] implied by #[warn(unused)]
= help: maybe it is overwritten before being read?
warning: unused variable: `fire`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:32

View File

@ -9,24 +9,31 @@ note: lint level defined here
|
LL | #![deny(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
= help: maybe it is overwritten before being read?
error: value assigned to `x` is never read
--> $DIR/liveness-dead.rs:27:5
|
LL | x = 4; //~ ERROR: value assigned to `x` is never read
| ^
|
= help: maybe it is overwritten before being read?
error: value passed to `x` is never read
--> $DIR/liveness-dead.rs:30:11
|
LL | fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
| ^
|
= help: maybe it is overwritten before being read?
error: value assigned to `x` is never read
--> $DIR/liveness-dead.rs:37:5
|
LL | x = 4; //~ ERROR: value assigned to `x` is never read
| ^
|
= help: maybe it is overwritten before being read?
error: aborting due to 4 previous errors

View File

@ -60,6 +60,7 @@ note: lint level defined here
|
LL | #![deny(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
= help: maybe it is overwritten before being read?
error: variable `z` is assigned to, but never used
--> $DIR/liveness-unused.rs:47:13
@ -106,6 +107,8 @@ error: value assigned to `x` is never read
|
LL | x = 0; //~ ERROR value assigned to `x` is never read
| ^
|
= help: maybe it is overwritten before being read?
error: aborting due to 13 previous errors

View File

@ -46,9 +46,9 @@ fn enum_example(mut e: E) {
E::V(ref mut x, _) => x,
E::W => panic!(),
};
match e { // OK, no access of borrowed data
match e { // Don't know that E uses a tag for its discriminant
_ if false => (),
E::V(_, r) => (),
E::V(_, r) => (), //~ ERROR
E::W => (),
}
x;
@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
E::V(ref mut x, _) => x,
E::W => panic!(),
};
match f { // OK, no access of borrowed data
match f { // Don't know that E uses a tag for its discriminant
_ if false => (),
E::V(_, r) => (),
E::V(_, r) => (), //~ ERROR
E::W => (),
}
x;

View File

@ -1,3 +1,27 @@
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:51:9
|
LL | E::V(ref mut x, _) => x,
| --------- borrow of `e.0` occurs here
...
LL | E::V(_, r) => (), //~ ERROR
| ^^^^^^^^^^ use of borrowed `e.0`
...
LL | x;
| - borrow later used here
error[E0503]: cannot use `*f` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:64:9
|
LL | E::V(ref mut x, _) => x,
| --------- borrow of `f.0` occurs here
...
LL | E::V(_, r) => (), //~ ERROR
| ^^^^^^^^^^ use of borrowed `f.0`
...
LL | x;
| - borrow later used here
error[E0503]: cannot use `t` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:82:9
|
@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n`
LL | match n {} //~ ERROR
| ^ use of possibly uninitialized `n`
error: aborting due to 2 previous errors
error: aborting due to 4 previous errors
Some errors occurred: E0381, E0503.
For more information about an error, try `rustc --explain E0381`.

View File

@ -54,8 +54,14 @@ fn main() {
simd_select(z, z, z);
//~^ ERROR mask element type is `f32`, expected `i_`
simd_select(m4, 0u32, 1u32);
//~^ ERROR found non-SIMD `u32`
simd_select_bitmask(0u8, x, x);
//~^ ERROR mask length `8` != other vector length `4`
//
simd_select_bitmask(0u8, 1u32, 2u32);
//~^ ERROR found non-SIMD `u32`
simd_select_bitmask(0.0f32, x, x);
//~^ ERROR `f32` is not an integral type

View File

@ -16,24 +16,36 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element
LL | simd_select(z, z, z);
| ^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
--> $DIR/simd-intrinsic-generic-select.rs:57:9
|
LL | simd_select(m4, 0u32, 1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
--> $DIR/simd-intrinsic-generic-select.rs:60:9
|
LL | simd_select_bitmask(0u8, x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
--> $DIR/simd-intrinsic-generic-select.rs:63:9
|
LL | simd_select_bitmask(0u8, 1u32, 2u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
--> $DIR/simd-intrinsic-generic-select.rs:60:9
--> $DIR/simd-intrinsic-generic-select.rs:66:9
|
LL | simd_select_bitmask(0.0f32, x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
--> $DIR/simd-intrinsic-generic-select.rs:63:9
--> $DIR/simd-intrinsic-generic-select.rs:69:9
|
LL | simd_select_bitmask("x", x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0511`.

View File

@ -0,0 +1,7 @@
use std::path::Path;
fn main() {
let path = Path::new("/tmp/foo/bar.txt");
println!("{}", path);
//~^ ERROR E0277
}

View File

@ -0,0 +1,14 @@
error[E0277]: `std::path::Path` doesn't implement `std::fmt::Display`
--> $DIR/path-display.rs:5:20
|
LL | println!("{}", path);
| ^^^^ `std::path::Path` cannot be formatted with the default formatter; call `.display()` on it
|
= help: the trait `std::fmt::Display` is not implemented for `std::path::Path`
= note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
= note: required because of the requirements on the impl of `std::fmt::Display` for `&std::path::Path`
= note: required by `std::fmt::Display::fmt`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -79,6 +79,7 @@ const WHITELIST: &[Crate] = &[
Crate("chalk-macros"),
Crate("cloudabi"),
Crate("cmake"),
Crate("compiler_builtins"),
Crate("crc"),
Crate("crc32fast"),
Crate("crossbeam-deque"),