mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Auto merge of #77013 - RalfJung:rollup-84ut0xq, r=RalfJung
Rollup of 10 pull requests Successful merges: - #76439 (Add error explanation for E0755) - #76521 (Fix segfault if pthread_getattr_np fails) - #76835 (make replace_prefix only take &str as arguments ) - #76967 (Revert adding Atomic::from_mut.) - #76977 (Add a regression test for copy propagation miscompilation) - #76981 (liballoc bench use imported path Bencher) - #76983 (BTreeMap: extra testing & fixed comments) - #76996 (Fix typo in rustc_lexer docs) - #77009 (Dogfood total_cmp in the test crate) - #77012 (update Miri for another bugfix) Failed merges: - #76489 (Add explanation for E0756) r? `@ghost`
This commit is contained in:
commit
4eff9b0b29
@ -440,6 +440,7 @@ E0751: include_str!("./error_codes/E0751.md"),
|
||||
E0752: include_str!("./error_codes/E0752.md"),
|
||||
E0753: include_str!("./error_codes/E0753.md"),
|
||||
E0754: include_str!("./error_codes/E0754.md"),
|
||||
E0755: include_str!("./error_codes/E0755.md"),
|
||||
E0758: include_str!("./error_codes/E0758.md"),
|
||||
E0759: include_str!("./error_codes/E0759.md"),
|
||||
E0760: include_str!("./error_codes/E0760.md"),
|
||||
@ -632,7 +633,6 @@ E0774: include_str!("./error_codes/E0774.md"),
|
||||
E0722, // Malformed `#[optimize]` attribute
|
||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
||||
E0755, // `#[ffi_pure]` is only allowed on foreign functions
|
||||
E0756, // `#[ffi_const]` is only allowed on foreign functions
|
||||
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
|
||||
|
28
compiler/rustc_error_codes/src/error_codes/E0755.md
Normal file
28
compiler/rustc_error_codes/src/error_codes/E0755.md
Normal file
@ -0,0 +1,28 @@
|
||||
The `ffi_pure` attribute was used on a non-foreign function.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0755
|
||||
#![feature(ffi_pure)]
|
||||
|
||||
#[ffi_pure] // error!
|
||||
pub fn foo() {}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
The `ffi_pure` attribute can only be used on foreign functions which do not have
|
||||
side effects or infinite loops:
|
||||
|
||||
```
|
||||
#![feature(ffi_pure)]
|
||||
|
||||
extern "C" {
|
||||
#[ffi_pure] // ok!
|
||||
pub fn strlen(s: *const i8) -> isize;
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
You can find more information about it in the [unstable Rust Book].
|
||||
|
||||
[unstable Rust Book]: https://doc.rust-lang.org/unstable-book/language-features/ffi-pure.html
|
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! The idea with `librustc_lexer` is to make a reusable library,
|
||||
//! by separating out pure lexing and rustc-specific concerns, like spans,
|
||||
//! error reporting an interning. So, rustc_lexer operates directly on `&str`,
|
||||
//! error reporting, and interning. So, rustc_lexer operates directly on `&str`,
|
||||
//! produces simple tokens which are a pair of type-tag and a bit of original text,
|
||||
//! and does not report errors, instead storing them as flags on the token.
|
||||
//!
|
||||
|
@ -362,16 +362,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
fn replace_prefix<A, B, C>(&self, s: A, old: B, new: C) -> Option<String>
|
||||
where
|
||||
A: AsRef<str>,
|
||||
B: AsRef<str>,
|
||||
C: AsRef<str>,
|
||||
{
|
||||
let s = s.as_ref();
|
||||
let old = old.as_ref();
|
||||
fn replace_prefix(&self, s: &str, old: &str, new: &str) -> Option<String> {
|
||||
if let Some(stripped) = s.strip_prefix(old) {
|
||||
Some(new.as_ref().to_owned() + stripped)
|
||||
Some(new.to_string() + stripped)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -422,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind {
|
||||
if let Ok(src) = sm.span_to_snippet(sp) {
|
||||
if let Some(src) = self.replace_prefix(src, "b\"", "\"") {
|
||||
if let Some(src) = self.replace_prefix(&src, "b\"", "\"") {
|
||||
return Some((
|
||||
sp,
|
||||
"consider removing the leading `b`",
|
||||
@ -436,7 +429,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
|
||||
if let hir::ExprKind::Lit(_) = expr.kind {
|
||||
if let Ok(src) = sm.span_to_snippet(sp) {
|
||||
if let Some(src) = self.replace_prefix(src, "\"", "b\"") {
|
||||
if let Some(src) = self.replace_prefix(&src, "\"", "b\"") {
|
||||
return Some((
|
||||
sp,
|
||||
"consider adding a leading `b`",
|
||||
@ -561,7 +554,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// we may want to suggest removing a `&`.
|
||||
if sm.is_imported(expr.span) {
|
||||
if let Ok(src) = sm.span_to_snippet(sp) {
|
||||
if let Some(src) = self.replace_prefix(src, "&", "") {
|
||||
if let Some(src) = self.replace_prefix(&src, "&", "") {
|
||||
return Some((
|
||||
sp,
|
||||
"consider removing the borrow",
|
||||
@ -598,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match mutbl_a {
|
||||
hir::Mutability::Mut => {
|
||||
if let Some(s) =
|
||||
self.replace_prefix(src, "&mut ", new_prefix)
|
||||
self.replace_prefix(&src, "&mut ", &new_prefix)
|
||||
{
|
||||
Some((s, Applicability::MachineApplicable))
|
||||
} else {
|
||||
@ -607,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
hir::Mutability::Not => {
|
||||
if let Some(s) =
|
||||
self.replace_prefix(src, "&", new_prefix)
|
||||
self.replace_prefix(&src, "&", &new_prefix)
|
||||
{
|
||||
Some((s, Applicability::Unspecified))
|
||||
} else {
|
||||
@ -621,7 +614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match mutbl_a {
|
||||
hir::Mutability::Mut => {
|
||||
if let Some(s) =
|
||||
self.replace_prefix(src, "&mut ", new_prefix)
|
||||
self.replace_prefix(&src, "&mut ", &new_prefix)
|
||||
{
|
||||
Some((s, Applicability::MachineApplicable))
|
||||
} else {
|
||||
@ -630,7 +623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
hir::Mutability::Not => {
|
||||
if let Some(s) =
|
||||
self.replace_prefix(src, "&", new_prefix)
|
||||
self.replace_prefix(&src, "&", &new_prefix)
|
||||
{
|
||||
Some((s, Applicability::MachineApplicable))
|
||||
} else {
|
||||
|
@ -496,7 +496,7 @@ bench_in_place![
|
||||
];
|
||||
|
||||
#[bench]
|
||||
fn bench_in_place_recycle(b: &mut test::Bencher) {
|
||||
fn bench_in_place_recycle(b: &mut Bencher) {
|
||||
let mut data = vec![0; 1000];
|
||||
|
||||
b.iter(|| {
|
||||
@ -513,7 +513,7 @@ fn bench_in_place_recycle(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_in_place_zip_recycle(b: &mut test::Bencher) {
|
||||
fn bench_in_place_zip_recycle(b: &mut Bencher) {
|
||||
let mut data = vec![0u8; 1000];
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut subst = vec![0u8; 1000];
|
||||
@ -533,7 +533,7 @@ fn bench_in_place_zip_recycle(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_in_place_zip_iter_mut(b: &mut test::Bencher) {
|
||||
fn bench_in_place_zip_iter_mut(b: &mut Bencher) {
|
||||
let mut data = vec![0u8; 256];
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut subst = vec![0u8; 1000];
|
||||
@ -558,7 +558,7 @@ impl Drop for Droppable {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_in_place_collect_droppable(b: &mut test::Bencher) {
|
||||
fn bench_in_place_collect_droppable(b: &mut Bencher) {
|
||||
let v: Vec<Droppable> = std::iter::repeat_with(|| Droppable(0)).take(1000).collect();
|
||||
b.iter(|| {
|
||||
v.clone()
|
||||
@ -571,13 +571,13 @@ fn bench_in_place_collect_droppable(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_chain_collect(b: &mut test::Bencher) {
|
||||
fn bench_chain_collect(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| data.iter().cloned().chain([1].iter().cloned()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_chain_chain_collect(b: &mut test::Bencher) {
|
||||
fn bench_chain_chain_collect(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| {
|
||||
data.iter()
|
||||
@ -589,7 +589,7 @@ fn bench_chain_chain_collect(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_nest_chain_chain_collect(b: &mut test::Bencher) {
|
||||
fn bench_nest_chain_chain_collect(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| {
|
||||
data.iter().cloned().chain([1].iter().chain([2].iter()).cloned()).collect::<Vec<_>>()
|
||||
@ -616,12 +616,12 @@ pub fn map_fast(l: &[(u32, u32)]) -> Vec<u32> {
|
||||
const LEN: usize = 16384;
|
||||
|
||||
#[bench]
|
||||
fn bench_range_map_collect(b: &mut test::Bencher) {
|
||||
fn bench_range_map_collect(b: &mut Bencher) {
|
||||
b.iter(|| (0..LEN).map(|_| u32::default()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_chain_extend_ref(b: &mut test::Bencher) {
|
||||
fn bench_chain_extend_ref(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u32>::with_capacity(data.len() + 1);
|
||||
@ -631,7 +631,7 @@ fn bench_chain_extend_ref(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_chain_extend_value(b: &mut test::Bencher) {
|
||||
fn bench_chain_extend_value(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u32>::with_capacity(data.len() + 1);
|
||||
@ -641,7 +641,7 @@ fn bench_chain_extend_value(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_rev_1(b: &mut test::Bencher) {
|
||||
fn bench_rev_1(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u32>::new();
|
||||
@ -651,13 +651,13 @@ fn bench_rev_1(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_rev_2(b: &mut test::Bencher) {
|
||||
fn bench_rev_2(b: &mut Bencher) {
|
||||
let data = black_box([0; LEN]);
|
||||
b.iter(|| example_plain_slow(&data));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_map_regular(b: &mut test::Bencher) {
|
||||
fn bench_map_regular(b: &mut Bencher) {
|
||||
let data = black_box([(0, 0); LEN]);
|
||||
b.iter(|| {
|
||||
let mut v = Vec::<u32>::new();
|
||||
@ -667,7 +667,7 @@ fn bench_map_regular(b: &mut test::Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_map_fast(b: &mut test::Bencher) {
|
||||
fn bench_map_fast(b: &mut Bencher) {
|
||||
let data = black_box([(0, 0); LEN]);
|
||||
b.iter(|| map_fast(&data));
|
||||
}
|
||||
|
@ -88,6 +88,11 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
|
||||
let min_len = if is_root { 1 } else { node::MIN_LEN };
|
||||
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
|
||||
|
||||
for idx in 0..=node.len() {
|
||||
let edge = unsafe { node::Handle::new_edge(node, idx) };
|
||||
assert!(edge.descend().ascend().ok().unwrap() == edge);
|
||||
}
|
||||
|
||||
internal_length += node.len();
|
||||
}
|
||||
Position::InternalKV(kv) => {
|
||||
@ -1846,3 +1851,17 @@ fn test_into_values() {
|
||||
assert!(values.contains(&'b'));
|
||||
assert!(values.contains(&'c'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_remove_intertwined() {
|
||||
let loops = if cfg!(miri) { 100 } else { 1_000_000 };
|
||||
let mut map = BTreeMap::new();
|
||||
let mut i = 1;
|
||||
for _ in 0..loops {
|
||||
i = (i + 421) & 0xFF;
|
||||
map.insert(i, i);
|
||||
map.remove(&(0xFF - i));
|
||||
}
|
||||
|
||||
map.check();
|
||||
}
|
||||
|
@ -613,8 +613,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
}
|
||||
|
||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
/// Adds a key/value pair and an edge to go to the right of that pair to
|
||||
/// the end of the node.
|
||||
/// Adds a key/value pair, and an edge to go to the right of that pair,
|
||||
/// to the end of the node.
|
||||
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||
assert!(edge.height == self.height - 1);
|
||||
|
||||
@ -630,8 +630,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a key/value pair and an edge to go to the left of that pair to
|
||||
/// the beginning of the node.
|
||||
/// Adds a key/value pair, and an edge to go to the left of that pair,
|
||||
/// to the beginning of the node.
|
||||
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||
assert!(edge.height == self.height - 1);
|
||||
assert!(self.len() < CAPACITY);
|
||||
@ -1152,7 +1152,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
|
||||
///
|
||||
/// - The node is truncated to only contain the key/value pairs to the right of
|
||||
/// this handle.
|
||||
/// - The key and value pointed to by this handle and extracted.
|
||||
/// - The key and value pointed to by this handle are extracted.
|
||||
/// - All the key/value pairs to the right of this handle are put into a newly
|
||||
/// allocated node.
|
||||
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
|
||||
@ -1196,7 +1196,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
|
||||
///
|
||||
/// - The node is truncated to only contain the edges and key/value pairs to the
|
||||
/// right of this handle.
|
||||
/// - The key and value pointed to by this handle and extracted.
|
||||
/// - The key and value pointed to by this handle are extracted.
|
||||
/// - All the edges and key/value pairs to the right of this handle are put into
|
||||
/// a newly allocated node.
|
||||
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Internal>, K, V, Root<K, V>) {
|
||||
|
@ -110,7 +110,6 @@ use self::Ordering::*;
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics;
|
||||
use crate::mem::align_of;
|
||||
|
||||
use crate::hint::spin_loop;
|
||||
|
||||
@ -328,27 +327,6 @@ impl AtomicBool {
|
||||
unsafe { &mut *(self.v.get() as *mut bool) }
|
||||
}
|
||||
|
||||
/// Get atomic access to a `&mut bool`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_from_mut)]
|
||||
/// use std::sync::atomic::{AtomicBool, Ordering};
|
||||
///
|
||||
/// let mut some_bool = true;
|
||||
/// let a = AtomicBool::from_mut(&mut some_bool);
|
||||
/// a.store(false, Ordering::Relaxed);
|
||||
/// assert_eq!(some_bool, false);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_from_mut", issue = "76314")]
|
||||
pub fn from_mut(v: &mut bool) -> &Self {
|
||||
// SAFETY: the mutable reference guarantees unique ownership, and
|
||||
// alignment of both `bool` and `Self` is 1.
|
||||
unsafe { &*(v as *mut bool as *mut Self) }
|
||||
}
|
||||
|
||||
/// Consumes the atomic and returns the contained value.
|
||||
///
|
||||
/// This is safe because passing `self` by value guarantees that no other threads are
|
||||
@ -841,30 +819,6 @@ impl<T> AtomicPtr<T> {
|
||||
self.p.get_mut()
|
||||
}
|
||||
|
||||
/// Get atomic access to a pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(atomic_from_mut)]
|
||||
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
///
|
||||
/// let mut some_ptr = &mut 123 as *mut i32;
|
||||
/// let a = AtomicPtr::from_mut(&mut some_ptr);
|
||||
/// a.store(&mut 456, Ordering::Relaxed);
|
||||
/// assert_eq!(unsafe { *some_ptr }, 456);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "atomic_from_mut", issue = "76314")]
|
||||
pub fn from_mut(v: &mut *mut T) -> &Self {
|
||||
let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
|
||||
// SAFETY:
|
||||
// - the mutable reference guarantees unique ownership.
|
||||
// - the alignment of `*mut T` and `Self` is the same on all platforms
|
||||
// supported by rust, as verified above.
|
||||
unsafe { &*(v as *mut *mut T as *mut Self) }
|
||||
}
|
||||
|
||||
/// Consumes the atomic and returns the contained value.
|
||||
///
|
||||
/// This is safe because passing `self` by value guarantees that no other threads are
|
||||
@ -1167,7 +1121,6 @@ macro_rules! atomic_int {
|
||||
$stable_nand:meta,
|
||||
$const_stable:meta,
|
||||
$stable_init_const:meta,
|
||||
$(from_mut: cfg($from_mut_cfg:meta),)?
|
||||
$s_int_type:literal, $int_ref:expr,
|
||||
$extra_feature:expr,
|
||||
$min_fn:ident, $max_fn:ident,
|
||||
@ -1278,45 +1231,6 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.
|
||||
|
||||
",
|
||||
if_not_8_bit! {
|
||||
$int_type,
|
||||
concat!(
|
||||
"**Note:** This function is only available on targets where `",
|
||||
stringify!($int_type), "` has an alignment of ", $align, " bytes."
|
||||
)
|
||||
},
|
||||
"
|
||||
|
||||
# Examples
|
||||
|
||||
```
|
||||
#![feature(atomic_from_mut)]
|
||||
", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
|
||||
|
||||
let mut some_int = 123;
|
||||
let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);
|
||||
a.store(100, Ordering::Relaxed);
|
||||
assert_eq!(some_int, 100);
|
||||
```
|
||||
"),
|
||||
#[inline]
|
||||
$(#[cfg($from_mut_cfg)])?
|
||||
#[unstable(feature = "atomic_from_mut", issue = "76314")]
|
||||
pub fn from_mut(v: &mut $int_type) -> &Self {
|
||||
let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
|
||||
// SAFETY:
|
||||
// - the mutable reference guarantees unique ownership.
|
||||
// - the alignment of `$int_type` and `Self` is the
|
||||
// same on all platforms enabled by `$from_mut_cfg`
|
||||
// as verified above.
|
||||
unsafe { &*(v as *mut $int_type as *mut Self) }
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Consumes the atomic and returns the contained value.
|
||||
|
||||
@ -2075,7 +1989,6 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
from_mut: cfg(not(target_arch = "x86")),
|
||||
"i64", "../../../std/primitive.i64.html",
|
||||
"",
|
||||
atomic_min, atomic_max,
|
||||
@ -2094,7 +2007,6 @@ atomic_int! {
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
from_mut: cfg(not(target_arch = "x86")),
|
||||
"u64", "../../../std/primitive.u64.html",
|
||||
"",
|
||||
atomic_umin, atomic_umax,
|
||||
@ -2113,7 +2025,6 @@ atomic_int! {
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
from_mut: cfg(not(target_arch = "x86_64")),
|
||||
"i128", "../../../std/primitive.i128.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
atomic_min, atomic_max,
|
||||
@ -2132,7 +2043,6 @@ atomic_int! {
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
from_mut: cfg(not(target_arch = "x86_64")),
|
||||
"u128", "../../../std/primitive.u128.html",
|
||||
"#![feature(integer_atomics)]\n\n",
|
||||
atomic_umin, atomic_umax,
|
||||
|
@ -294,6 +294,7 @@ pub mod guard {
|
||||
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
|
||||
let mut ret = None;
|
||||
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
|
||||
#[cfg(target_os = "freebsd")]
|
||||
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
|
||||
@ -305,7 +306,9 @@ pub mod guard {
|
||||
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
|
||||
ret = Some(stackaddr);
|
||||
}
|
||||
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||
if e == 0 || cfg!(target_os = "freebsd") {
|
||||
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
@ -403,6 +406,7 @@ pub mod guard {
|
||||
pub unsafe fn current() -> Option<Guard> {
|
||||
let mut ret = None;
|
||||
let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
|
||||
#[cfg(target_os = "freebsd")]
|
||||
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
|
||||
@ -446,7 +450,9 @@ pub mod guard {
|
||||
Some(stackaddr..stackaddr + guardsize)
|
||||
};
|
||||
}
|
||||
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||
if e == 0 || cfg!(target_os = "freebsd") {
|
||||
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(termination_trait_lib)]
|
||||
#![feature(test)]
|
||||
#![feature(total_cmp)]
|
||||
|
||||
// Public reexports
|
||||
pub use self::bench::{black_box, Bencher};
|
||||
|
@ -1,29 +1,13 @@
|
||||
#![allow(missing_docs)]
|
||||
#![allow(deprecated)] // Float
|
||||
|
||||
use std::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use std::mem;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
fn local_cmp(x: f64, y: f64) -> Ordering {
|
||||
// arbitrarily decide that NaNs are larger than everything.
|
||||
if y.is_nan() {
|
||||
Less
|
||||
} else if x.is_nan() {
|
||||
Greater
|
||||
} else if x < y {
|
||||
Less
|
||||
} else if x == y {
|
||||
Equal
|
||||
} else {
|
||||
Greater
|
||||
}
|
||||
}
|
||||
|
||||
fn local_sort(v: &mut [f64]) {
|
||||
v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
|
||||
v.sort_by(|x: &f64, y: &f64| x.total_cmp(y));
|
||||
}
|
||||
|
||||
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
|
||||
|
@ -6,3 +6,4 @@ LL | #[ffi_pure]
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0755`.
|
||||
|
30
src/test/ui/mir/issue-76740-copy-propagation.rs
Normal file
30
src/test/ui/mir/issue-76740-copy-propagation.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Regression test for issue #76740.
|
||||
// run-fail FIXME: change to run-pass once #76899 lands
|
||||
// compile-flags: -Zmir-opt-level=3
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct V([usize; 4]);
|
||||
|
||||
impl V {
|
||||
fn new() -> Self {
|
||||
V([0; 4])
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn check(mut self) {
|
||||
assert_eq!(self.0[0], 0);
|
||||
self.0[0] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = V::new();
|
||||
let mut i = 0;
|
||||
while i != 10 {
|
||||
// Copy propagation incorrectly assumed that Operand::Move does not
|
||||
// mutate the local, and used the same v for each V::check call,
|
||||
// rather than a copy.
|
||||
v.check();
|
||||
i += 1;
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit cbc7560ae2d44669ef6ba0f43014e10ce881180e
|
||||
Subproject commit 02a33d411d8e385942776760a99535d69826349b
|
Loading…
Reference in New Issue
Block a user