From 69ffed763d1540c387db3b578848184026da0484 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Sep 2020 13:40:23 +0200 Subject: [PATCH 01/11] Add error explanation for E0755 --- compiler/rustc_error_codes/src/error_codes.rs | 2 +- .../src/error_codes/E0755.md | 28 +++++++++++++++++++ src/test/ui/ffi_pure.stderr | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0755.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 789a1fc35a64f..af9ca7e10fcf4 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -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"), @@ -631,7 +632,6 @@ E0773: include_str!("./error_codes/E0773.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 {}`. diff --git a/compiler/rustc_error_codes/src/error_codes/E0755.md b/compiler/rustc_error_codes/src/error_codes/E0755.md new file mode 100644 index 0000000000000..88b7f48496906 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0755.md @@ -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 diff --git a/src/test/ui/ffi_pure.stderr b/src/test/ui/ffi_pure.stderr index 3a849c0bca79c..bc911c85ddb29 100644 --- a/src/test/ui/ffi_pure.stderr +++ b/src/test/ui/ffi_pure.stderr @@ -6,3 +6,4 @@ LL | #[ffi_pure] error: aborting due to previous error +For more information about this error, try `rustc --explain E0755`. From a06edda3ad9abd4f07d07bbe46cb488efeebbbd0 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 9 Sep 2020 10:16:03 -0400 Subject: [PATCH 02/11] Fix segfault if pthread_getattr_np fails glibc destroys[1] the passed pthread_attr_t if pthread_getattr_np() fails. Destroying it again leads to a segfault. Fix it by only destroying it on success for glibc. [1]: https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_getattr_np.c;h=ce437205e41dc05653e435f6188768cccdd91c99;hb=HEAD#l205 --- library/std/src/sys/unix/thread.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 04da9812ddc45..569aedd741192 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -305,7 +305,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!(not(target_env = "gnu")) { + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + } ret } @@ -446,7 +448,9 @@ pub mod guard { Some(stackaddr..stackaddr + guardsize) }; } - assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + if e == 0 || cfg!(not(target_env = "gnu")) { + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + } ret } } From a684153f2920729f9fc3ea27ddb77d7cc3543214 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 9 Sep 2020 11:10:43 -0400 Subject: [PATCH 03/11] Only call pthread_attr_destroy() after getattr_np() succeeds on all libcs The calling convention of pthread_getattr_np() is to initialize the pthread_attr_t, so _destroy() is only necessary on success (and _init() isn't necessary beforehand). On the other hand, FreeBSD wants the attr_t to be initialized before pthread_attr_get_np(), and therefore it should always be destroyed afterwards. --- library/std/src/sys/unix/thread.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 569aedd741192..652219e28f6e0 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -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,7 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0); ret = Some(stackaddr); } - if e == 0 || cfg!(not(target_env = "gnu")) { + if e == 0 || cfg!(target_os = "freebsd") { assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); } ret @@ -405,6 +406,7 @@ pub mod guard { pub unsafe fn current() -> Option { 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); @@ -448,7 +450,7 @@ pub mod guard { Some(stackaddr..stackaddr + guardsize) }; } - if e == 0 || cfg!(not(target_env = "gnu")) { + if e == 0 || cfg!(target_os = "freebsd") { assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); } ret From 026922ad60a9529f16b792e8c2fe805ab3906259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 17 Sep 2020 13:11:01 +0200 Subject: [PATCH 04/11] make replace_prefix only take &str as arguments /~https://github.com/rust-lang/rust/pull/76828#issuecomment-694078200 --- compiler/rustc_typeck/src/check/demand.rs | 25 ++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index c7ce5008c3354..247bbf637ceaf 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -362,16 +362,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn replace_prefix(&self, s: A, old: B, new: C) -> Option - where - A: AsRef, - B: AsRef, - C: AsRef, - { - let s = s.as_ref(); - let old = old.as_ref(); + fn replace_prefix(&self, s: &str, old: &str, new: &str) -> Option { 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 { From 65edf54c256e5369fdf9c0a972cd83d2414d5bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 20 Sep 2020 00:00:00 +0000 Subject: [PATCH 05/11] Add a regression test for copy propagation miscompilation --- .../ui/mir/issue-76740-copy-propagation.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/ui/mir/issue-76740-copy-propagation.rs diff --git a/src/test/ui/mir/issue-76740-copy-propagation.rs b/src/test/ui/mir/issue-76740-copy-propagation.rs new file mode 100644 index 0000000000000..e3283949b2688 --- /dev/null +++ b/src/test/ui/mir/issue-76740-copy-propagation.rs @@ -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; + } +} From 5ef1db3622c373883571868cbdafbfbd568cddcb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 12:50:13 +0200 Subject: [PATCH 06/11] Revert adding Atomic::from_mut. This made too many assumptions about platforms, breaking some things. Will need to be added later with a better way of gating on proper alignment, without hardcoding cfg(target_arch)s. --- library/core/src/sync/atomic.rs | 90 --------------------------------- 1 file changed, 90 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 9d74f537491b1..1d2880405a64d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -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 @@ -842,30 +820,6 @@ impl AtomicPtr { unsafe { &mut *self.p.get() } } - /// 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::>() - 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 @@ -1168,7 +1122,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, @@ -1280,45 +1233,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::() - 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. @@ -2077,7 +1991,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, @@ -2096,7 +2009,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, @@ -2115,7 +2027,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, @@ -2134,7 +2045,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, From d99bb9d31c9fb170c1f80c20511d18e433cc5e9c Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 21 Sep 2020 00:46:40 +0800 Subject: [PATCH 07/11] liballoc bench use imported path Bencher test is already in scope, no need to use the full path --- library/alloc/benches/vec.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 6703a99b15155..b295342f3610e 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -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 = 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::>()); } #[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::>() @@ -616,12 +616,12 @@ pub fn map_fast(l: &[(u32, u32)]) -> Vec { 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::>()); } #[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::::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::::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::::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::::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)); } From 37ec0458507447565f3abdba0fab182c0dcd0e14 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Sun, 20 Sep 2020 00:45:29 +0200 Subject: [PATCH 08/11] BTreeMap: extra testing unveiling mistakes in future PR --- .../alloc/src/collections/btree/map/tests.rs | 19 +++++++++++++++++++ library/alloc/src/collections/btree/node.rs | 12 ++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index d2cd6b8e5241a..8018514fa1776 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -88,6 +88,11 @@ impl<'a, K: 'a, V: 'a> BTreeMap { 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(); +} diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index f52d07c9b8c94..f1d66e973cb52 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -613,8 +613,8 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { } impl<'a, K: 'a, V: 'a> NodeRef, 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) { assert!(edge.height == self.height - 1); @@ -630,8 +630,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, 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) { assert!(edge.height == self.height - 1); assert!(self.len() < CAPACITY); @@ -1152,7 +1152,7 @@ impl<'a, K: 'a, V: 'a> Handle, 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, K, V, marker::Leaf>, K, V, Root) { @@ -1196,7 +1196,7 @@ impl<'a, K: 'a, V: 'a> Handle, 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, K, V, marker::Internal>, K, V, Root) { From fc20b7841ccd0efed87ec063b63e35d35fde3544 Mon Sep 17 00:00:00 2001 From: LingMan Date: Mon, 21 Sep 2020 05:43:39 +0200 Subject: [PATCH 09/11] Fix typo in rustc_lexer docs Also add an Oxford comma while we're editing that line. --- compiler/rustc_lexer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 44999bbe85713..d784a86f14cee 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -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. //! From 9172e277f864205daaf8fde64868d833cc6e7eb2 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 21 Sep 2020 12:13:26 +0200 Subject: [PATCH 10/11] Dogfood total_cmp in the test crate --- library/test/src/lib.rs | 1 + library/test/src/stats.rs | 18 +----------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 6bd708ef48798..caea4b1e30941 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -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}; diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs index c02f93bf9d42f..1a2cb893a8a4f 100644 --- a/library/test/src/stats.rs +++ b/library/test/src/stats.rs @@ -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. From 57baec7d4342f3c2949c136aa2af2e151d36d093 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Sep 2020 15:26:50 +0200 Subject: [PATCH 11/11] update Miri for another bugfix --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index cbc7560ae2d44..02a33d411d8e3 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit cbc7560ae2d44669ef6ba0f43014e10ce881180e +Subproject commit 02a33d411d8e385942776760a99535d69826349b