From 963d6f757c52dd0693e3c0541d7b027279f8a2db Mon Sep 17 00:00:00 2001 From: The 8472 Date: Mon, 17 Oct 2022 22:47:39 +0200 Subject: [PATCH 1/6] add a benchmark for slice_iter.copied().array_chunks() --- library/core/benches/iter.rs | 20 ++++++++++++++++++++ library/core/benches/lib.rs | 1 + 2 files changed, 21 insertions(+) diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 4b40485d207c8..38887f29af153 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -1,4 +1,6 @@ use core::iter::*; +use core::mem; +use core::num::Wrapping; use test::{black_box, Bencher}; #[bench] @@ -398,3 +400,21 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) { acc }) } + +/// Exercises the iter::Copied specialization for slice::Iter +#[bench] +fn bench_copied_array_chunks(b: &mut Bencher) { + let v = vec![1u8; 1024]; + + b.iter(|| { + black_box(&v) + .iter() + .copied() + .array_chunks::<{ mem::size_of::() }>() + .map(|ary| { + let d = u64::from_ne_bytes(ary); + Wrapping(d.rotate_left(7).wrapping_add(1)) + }) + .sum::>() + }) +} diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index a6c174d2fca21..1e462e3fc3f8c 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -4,6 +4,7 @@ #![feature(int_log)] #![feature(test)] #![feature(trusted_random_access)] +#![feature(iter_array_chunks)] extern crate test; From dfa9d5c971d74aa5bdf6b99253fe4b7db39f9b67 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Oct 2022 14:31:33 +1100 Subject: [PATCH 2/6] Tweak `deriving-all-codegen.rs`. To include some `Option<>` fields of different types in a single enum. The test output is currently buggy, but the next commit will fix that. --- src/test/ui/deriving/deriving-all-codegen.rs | 2 +- src/test/ui/deriving/deriving-all-codegen.stdout | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/ui/deriving/deriving-all-codegen.rs b/src/test/ui/deriving/deriving-all-codegen.rs index aef79ae8a5b8d..ba7809413bd80 100644 --- a/src/test/ui/deriving/deriving-all-codegen.rs +++ b/src/test/ui/deriving/deriving-all-codegen.rs @@ -85,7 +85,7 @@ enum Mixed { P, Q, R(u32), - S { d1: u32, d2: u32 }, + S { d1: Option, d2: Option }, } // An enum with no fieldless variants. Note that `Default` cannot be derived diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index 65f7dec840802..6baa7317b12bb 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -789,8 +789,8 @@ enum Mixed { Q, R(u32), S { - d1: u32, - d2: u32, + d1: Option, + d2: Option, }, } #[automatically_derived] @@ -798,6 +798,7 @@ impl ::core::clone::Clone for Mixed { #[inline] fn clone(&self) -> Mixed { let _: ::core::clone::AssertParamIsClone; + let _: ::core::clone::AssertParamIsClone>; *self } } @@ -864,6 +865,7 @@ impl ::core::cmp::Eq for Mixed { #[no_coverage] fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq; + let _: ::core::cmp::AssertParamIsEq>; } } #[automatically_derived] From 9a23f60f9c801dd0b4686cc75c6a9979bd8928fa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Oct 2022 13:07:20 +1100 Subject: [PATCH 3/6] Fix `TyKind::is_simple_path`. PR #98758 introduced code to avoid redundant assertions in derived code like this: ``` let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; ``` But the predicate `is_simple_path` introduced as part of this failed to account for generic arguments. Therefore the deriving code erroneously considers types like `Option` and `Option` to be the same. This commit fixes `is_simple_path`. Fixes #103157. --- compiler/rustc_ast/src/ast.rs | 7 +++-- .../ui/deriving/deriving-all-codegen.stdout | 2 ++ src/test/ui/deriving/issue-103157.rs | 12 ++++++++ src/test/ui/deriving/issue-103157.stderr | 30 +++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/deriving/issue-103157.rs create mode 100644 src/test/ui/deriving/issue-103157.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 60b7f2e4c2223..7112c26757717 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2060,8 +2060,11 @@ impl TyKind { } pub fn is_simple_path(&self) -> Option { - if let TyKind::Path(None, Path { segments, .. }) = &self && segments.len() == 1 { - Some(segments[0].ident.name) + if let TyKind::Path(None, Path { segments, .. }) = &self + && let [segment] = &segments[..] + && segment.args.is_none() + { + Some(segment.ident.name) } else { None } diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index 6baa7317b12bb..56efc2a59ecb8 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -799,6 +799,7 @@ impl ::core::clone::Clone for Mixed { fn clone(&self) -> Mixed { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone>; + let _: ::core::clone::AssertParamIsClone>; *self } } @@ -866,6 +867,7 @@ impl ::core::cmp::Eq for Mixed { fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq>; + let _: ::core::cmp::AssertParamIsEq>; } } #[automatically_derived] diff --git a/src/test/ui/deriving/issue-103157.rs b/src/test/ui/deriving/issue-103157.rs new file mode 100644 index 0000000000000..52b4c7898d87b --- /dev/null +++ b/src/test/ui/deriving/issue-103157.rs @@ -0,0 +1,12 @@ +// check-fail + +#[derive(PartialEq, Eq)] +pub enum Value { + Boolean(Option), + Float(Option), //~ ERROR the trait bound `f64: Eq` is not satisfied +} + +fn main() { + let a = Value::Float(Some(f64::NAN)); + assert!(a == a); +} diff --git a/src/test/ui/deriving/issue-103157.stderr b/src/test/ui/deriving/issue-103157.stderr new file mode 100644 index 0000000000000..ee3528fe1062d --- /dev/null +++ b/src/test/ui/deriving/issue-103157.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `f64: Eq` is not satisfied + --> $DIR/issue-103157.rs:6:11 + | +LL | #[derive(PartialEq, Eq)] + | -- in this derive macro expansion +... +LL | Float(Option), + | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` + | + = help: the following other types implement trait `Eq`: + i128 + i16 + i32 + i64 + i8 + isize + u128 + u16 + and 4 others + = note: required for `Option` to implement `Eq` +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | pub struct AssertParamIsEq { + | ^^ required by this bound in `AssertParamIsEq` + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 399e5cc8db64f06c2d2d57894fc066d289e3eeae Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 27 Sep 2022 10:11:43 +0200 Subject: [PATCH 4/6] partially fix src/test/run-make/coverage-reports when cross-compiling The test does not work on cross-compiled targets because the --target flag was not passed to rustc inside the test. This commit fixes that by adding the flag to the invocations. Note that the test still fails on cross-compiled targets using remote-test, as remote-test is not capable (yet) of sending back to the host system the *.profraw file generated by the instrumentation. Because of that, this is only a partial fix, and the test has been ignored on cross-compilation. --- src/test/run-make/coverage-reports/Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile index 6fc2a6bada9a0..407992c9f43d8 100644 --- a/src/test/run-make/coverage-reports/Makefile +++ b/src/test/run-make/coverage-reports/Makefile @@ -1,6 +1,11 @@ # needs-profiler-support # ignore-windows-gnu +# FIXME(pietroalbini): this test currently does not work on cross-compiled +# targets because remote-test is not capable of sending back the *.profraw +# files generated by the LLVM instrumentation. +# ignore-cross-compile + # Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6, # corresponding with LLVM versions 12 and 13, respectively. # When upgrading LLVM versions, consider whether to enforce a minimum LLVM @@ -81,13 +86,13 @@ include clear_expected_if_blessed # Compile the test library with coverage instrumentation $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \ - --crate-type rlib -Cinstrument-coverage + --crate-type rlib -Cinstrument-coverage --target $(TARGET) %: $(SOURCEDIR)/%.rs # Compile the test program with coverage instrumentation $(RUSTC) $(SOURCEDIR)/$@.rs \ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ - -L "$(TMPDIR)" -Cinstrument-coverage + -L "$(TMPDIR)" -Cinstrument-coverage --target $(TARGET) # Run it in order to generate some profiling data, # with `LLVM_PROFILE_FILE=` environment variable set to From a3921aedc82d7796e4663dece66c12530d616204 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 18 Oct 2022 23:13:57 +0800 Subject: [PATCH 5/6] Update cargo 6 commits in b332991a57c9d055f1864de1eed93e2178d49440..3ff044334f0567ce1481c78603aeee7211b91623 2022-10-13 22:05:28 +0000 to 2022-10-17 20:25:00 +0000 - Some tiny refactors around `ops::cargo_compile` (rust-lang/cargo#11243) - Polish docs for module `build_context` (rust-lang/cargo#11241) - Remove sparse+ prefix for index.crates.io (rust-lang/cargo#11247) - docs(add): Add missing flags to reference (rust-lang/cargo#11240) - Document `cargo remove` (rust-lang/cargo#11227) - fix: Update help headings to match clap (rust-lang/cargo#11239) --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index b332991a57c9d..3ff044334f056 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b332991a57c9d055f1864de1eed93e2178d49440 +Subproject commit 3ff044334f0567ce1481c78603aeee7211b91623 From 873a18e2213a506d4cf6357e5faef0990ec08683 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Mon, 17 Oct 2022 22:49:32 +0200 Subject: [PATCH 6/6] specialize slice_iter.copied().next_chunk() --- library/core/src/iter/adapters/copied.rs | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index f9bfd77d7fbbf..62d3afb81603d 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -2,7 +2,10 @@ use crate::iter::adapters::{ zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, TrustedLen}; +use crate::mem::MaybeUninit; +use crate::mem::SizedTypeProperties; use crate::ops::Try; +use crate::{array, ptr}; /// An iterator that copies the elements of an underlying iterator. /// @@ -44,6 +47,15 @@ where self.it.next().copied() } + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> + where + Self: Sized, + { + >::spec_next_chunk(&mut self.it) + } + fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } @@ -166,3 +178,65 @@ where T: Copy, { } + +trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter>; +} + +impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I +where + I: Iterator, + T: Copy, +{ + default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter> { + array::iter_next_chunk(&mut self.map(|e| *e)) + } +} + +impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T> +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter> { + let mut raw_array = MaybeUninit::uninit_array(); + + let len = self.len(); + + if T::IS_ZST { + if len < N { + let _ = self.advance_by(len); + // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct + return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) }); + } + + let _ = self.advance_by(N); + // SAFETY: ditto + return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) }); + } + + if len < N { + // SAFETY: `len` indicates that this many elements are available and we just checked that + // it fits into the array. + unsafe { + ptr::copy_nonoverlapping( + self.as_ref().as_ptr(), + raw_array.as_mut_ptr() as *mut T, + len, + ); + let _ = self.advance_by(len); + return Err(array::IntoIter::new_unchecked(raw_array, 0..len)); + } + } + + // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // the array. + unsafe { + ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N); + let _ = self.advance_by(N); + Ok(MaybeUninit::array_assume_init(raw_array)) + } + } +}