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:
commit
a8a2a887d0
21
Cargo.lock
21
Cargo.lock
@ -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"
|
||||
|
@ -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> {
|
||||
unsafe {
|
||||
/// 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_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)) => {
|
||||
|
@ -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
|
||||
///
|
||||
/// ```
|
||||
|
@ -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")]
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,9 +1135,13 @@ macro_rules! atomic_int {
|
||||
|
||||
#[$stable_from]
|
||||
impl From<$int_type> for $atomic_type {
|
||||
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]
|
||||
impl fmt::Debug for $atomic_type {
|
||||
|
@ -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,8 +528,7 @@ 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(
|
||||
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'gcx> {
|
||||
unsubstituted_region_constraints
|
||||
.iter()
|
||||
.map(move |constraint| {
|
||||
@ -552,7 +552,6 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
)
|
||||
})
|
||||
) as Box<dyn Iterator<Item = _>>
|
||||
}
|
||||
|
||||
/// Given two sets of values for the same set of canonical variables, unify them.
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 `{}`",
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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!(
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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 (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() => {
|
||||
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();
|
||||
|
||||
// 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(
|
||||
|
@ -305,7 +305,7 @@ nav.sub {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
body:not(.source) .example-wrap > pre {
|
||||
.rustdoc:not(.source) .example-wrap > pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -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,36 +489,77 @@ 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");
|
||||
|
||||
// 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 {
|
||||
if trimline.starts_with("#[macro_use] extern crate")
|
||||
|| trimline.starts_with("extern crate") {
|
||||
crates.push_str(line);
|
||||
crates.push_str("\n");
|
||||
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");
|
||||
}
|
||||
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();
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
///
|
||||
|
@ -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)]
|
||||
|
@ -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")),
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3
|
||||
Subproject commit 95185c8c801c765ac1072392d081d265af9fb310
|
@ -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
|
||||
|
30
src/test/rustdoc/comment-in-doctest.rs
Normal file
30
src/test/rustdoc/comment-in-doctest.rs
Normal 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() {}
|
||||
//! ```
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
23
src/test/ui/issues/issue-56199.rs
Normal file
23
src/test/ui/issues/issue-56199.rs
Normal 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() {}
|
30
src/test/ui/issues/issue-56199.stderr
Normal file
30
src/test/ui/issues/issue-56199.stderr
Normal 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
|
||||
|
10
src/test/ui/issues/issue-56835.rs
Normal file
10
src/test/ui/issues/issue-56835.rs
Normal 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() {}
|
15
src/test/ui/issues/issue-56835.stderr
Normal file
15
src/test/ui/issues/issue-56835.stderr
Normal 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`.
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
7
src/test/ui/suggestions/path-display.rs
Normal file
7
src/test/ui/suggestions/path-display.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let path = Path::new("/tmp/foo/bar.txt");
|
||||
println!("{}", path);
|
||||
//~^ ERROR E0277
|
||||
}
|
14
src/test/ui/suggestions/path-display.stderr
Normal file
14
src/test/ui/suggestions/path-display.stderr
Normal 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`.
|
@ -79,6 +79,7 @@ const WHITELIST: &[Crate] = &[
|
||||
Crate("chalk-macros"),
|
||||
Crate("cloudabi"),
|
||||
Crate("cmake"),
|
||||
Crate("compiler_builtins"),
|
||||
Crate("crc"),
|
||||
Crate("crc32fast"),
|
||||
Crate("crossbeam-deque"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user