From 3c7c38ad9335b043315addc1fcabf3631bbe1125 Mon Sep 17 00:00:00 2001 From: real-eren Date: Sun, 2 Feb 2025 17:59:43 -0500 Subject: [PATCH 01/20] Simplify SSE2 implementation --- .../rustc_span/src/analyze_source_file.rs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index fba205665803c..87c8e3fce072d 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -110,25 +110,19 @@ cfg_match! { if control_char_mask != 0 { // Check for newlines in the chunk let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; if control_char_mask == newlines_mask { // All control characters are newlines, record them - let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32; let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - loop { + while newlines_mask != 0 { let index = newlines_mask.trailing_zeros(); - if index >= CHUNK_SIZE as u32 { - // We have arrived at the end of the chunk. - break; - } - lines.push(RelativeBytePos(index) + output_offset); // Clear the bit, so we can find the next one. - newlines_mask &= (!1) << index; + newlines_mask &= newlines_mask - 1; } // We are done for this chunk. All control characters were @@ -268,25 +262,19 @@ cfg_match! { if control_char_mask != 0 { // Check for newlines in the chunk let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; if control_char_mask == newlines_mask { // All control characters are newlines, record them - let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32; let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - loop { + while newlines_mask != 0 { let index = newlines_mask.trailing_zeros(); - if index >= CHUNK_SIZE as u32 { - // We have arrived at the end of the chunk. - break; - } - lines.push(RelativeBytePos(index) + output_offset); // Clear the bit, so we can find the next one. - newlines_mask &= (!1) << index; + newlines_mask &= newlines_mask - 1; } // We are done for this chunk. All control characters were From d6ca7ad0d7a7e8acd14f6da3bad4e7b5a25c3d17 Mon Sep 17 00:00:00 2001 From: real-eren Date: Sun, 2 Feb 2025 19:39:07 -0500 Subject: [PATCH 02/20] Remove dead control char logic Only newlines and multibyte characters are actually relevant --- .../rustc_span/src/analyze_source_file.rs | 175 ++++++------------ 1 file changed, 55 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index 87c8e3fce072d..47cc16b623d10 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -95,59 +95,32 @@ cfg_match! { if multibyte_mask == 0 { assert!(intra_chunk_offset == 0); - // Check if there are any control characters in the chunk. All - // control characters that we can encounter at this point have a - // byte value less than 32 or ... - let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) }; - let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) }; - - // ... it's the ASCII 'DEL' character with a value of 127. - let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) }; - let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) }; - - let control_char_mask = control_char_mask0 | control_char_mask1; - - if control_char_mask != 0 { - // Check for newlines in the chunk - let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; - - if control_char_mask == newlines_mask { - // All control characters are newlines, record them - let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - - while newlines_mask != 0 { - let index = newlines_mask.trailing_zeros(); - - lines.push(RelativeBytePos(index) + output_offset); - - // Clear the bit, so we can find the next one. - newlines_mask &= newlines_mask - 1; - } - - // We are done for this chunk. All control characters were - // newlines and we took care of those. - continue; - } else { - // Some of the control characters are not newlines, - // fall through to the slow path below. - } - } else { - // No control characters, nothing to record for this chunk - continue; + // Check for newlines in the chunk + let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + + let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); + + while newlines_mask != 0 { + let index = newlines_mask.trailing_zeros(); + + lines.push(RelativeBytePos(index) + output_offset); + + // Clear the bit, so we can find the next one. + newlines_mask &= newlines_mask - 1; } + } else { + // The slow path. + // There are multibyte chars in here, fallback to generic decoding. + let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; + intra_chunk_offset = analyze_source_file_generic( + &src[scan_start..], + CHUNK_SIZE - intra_chunk_offset, + RelativeBytePos::from_usize(scan_start), + lines, + multi_byte_chars, + ); } - - // The slow path. - // There are control chars in here, fallback to generic decoding. - let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; - intra_chunk_offset = analyze_source_file_generic( - &src[scan_start..], - CHUNK_SIZE - intra_chunk_offset, - RelativeBytePos::from_usize(scan_start), - lines, - multi_byte_chars, - ); } // There might still be a tail left to analyze @@ -247,59 +220,32 @@ cfg_match! { if multibyte_mask == 0 { assert!(intra_chunk_offset == 0); - // Check if there are any control characters in the chunk. All - // control characters that we can encounter at this point have a - // byte value less than 32 or ... - let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) }; - let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) }; - - // ... it's the ASCII 'DEL' character with a value of 127. - let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) }; - let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) }; - - let control_char_mask = control_char_mask0 | control_char_mask1; - - if control_char_mask != 0 { - // Check for newlines in the chunk - let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; - - if control_char_mask == newlines_mask { - // All control characters are newlines, record them - let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - - while newlines_mask != 0 { - let index = newlines_mask.trailing_zeros(); - - lines.push(RelativeBytePos(index) + output_offset); - - // Clear the bit, so we can find the next one. - newlines_mask &= newlines_mask - 1; - } - - // We are done for this chunk. All control characters were - // newlines and we took care of those. - continue; - } else { - // Some of the control characters are not newlines, - // fall through to the slow path below. - } - } else { - // No control characters, nothing to record for this chunk - continue; + // Check for newlines in the chunk + let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + + let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); + + while newlines_mask != 0 { + let index = newlines_mask.trailing_zeros(); + + lines.push(RelativeBytePos(index) + output_offset); + + // Clear the bit, so we can find the next one. + newlines_mask &= newlines_mask - 1; } + } else { + // The slow path. + // There are multibyte chars in here, fallback to generic decoding. + let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; + intra_chunk_offset = analyze_source_file_generic( + &src[scan_start..], + CHUNK_SIZE - intra_chunk_offset, + RelativeBytePos::from_usize(scan_start), + lines, + multi_byte_chars, + ); } - - // The slow path. - // There are control chars in here, fallback to generic decoding. - let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; - intra_chunk_offset = analyze_source_file_generic( - &src[scan_start..], - CHUNK_SIZE - intra_chunk_offset, - RelativeBytePos::from_usize(scan_start), - lines, - multi_byte_chars, - ); } // There might still be a tail left to analyze @@ -357,29 +303,18 @@ fn analyze_source_file_generic( // string. let mut char_len = 1; - if byte < 32 { - // This is an ASCII control character, it could be one of the cases - // that are interesting to us. - + if byte == b'\n' { let pos = RelativeBytePos::from_usize(i) + output_offset; - - if let b'\n' = byte { - lines.push(pos + RelativeBytePos(1)); - } - } else if byte >= 127 { - // The slow path: - // This is either ASCII control character "DEL" or the beginning of - // a multibyte char. Just decode to `char`. + lines.push(pos + RelativeBytePos(1)); + } else if byte >= 128 { + // This is the beginning of a multibyte char. Just decode to `char`. let c = src[i..].chars().next().unwrap(); char_len = c.len_utf8(); let pos = RelativeBytePos::from_usize(i) + output_offset; - - if char_len > 1 { - assert!((2..=4).contains(&char_len)); - let mbc = MultiByteChar { pos, bytes: char_len as u8 }; - multi_byte_chars.push(mbc); - } + assert!((2..=4).contains(&char_len)); + let mbc = MultiByteChar { pos, bytes: char_len as u8 }; + multi_byte_chars.push(mbc); } i += char_len; From 4b086d47118668bff5f04b511e673fa3c84369d3 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Wed, 12 Feb 2025 00:54:00 -0500 Subject: [PATCH 03/20] expect EINVAL for pthread_mutex_destroy for aix --- library/std/src/sys/pal/unix/sync/mutex.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/unix/sync/mutex.rs b/library/std/src/sys/pal/unix/sync/mutex.rs index 8ff6c3d3d15da..557e70af94ba7 100644 --- a/library/std/src/sys/pal/unix/sync/mutex.rs +++ b/library/std/src/sys/pal/unix/sync/mutex.rs @@ -111,9 +111,9 @@ impl Drop for Mutex { // `PTHREAD_MUTEX_INITIALIZER`, which is valid at all locations. Thus, // this call always destroys a valid mutex. let r = unsafe { libc::pthread_mutex_destroy(self.raw()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. + if cfg!(any(target_os = "aix", target_os = "dragonfly")) { + // On AIX and DragonFly pthread_mutex_destroy() returns EINVAL if called + // on a mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. // Once it is used (locked/unlocked) or pthread_mutex_init() is called, // this behaviour no longer occurs. debug_assert!(r == 0 || r == libc::EINVAL); From 88193aad724279c938efd2d17332e08a751de106 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 12 Feb 2025 23:52:53 +0000 Subject: [PATCH 04/20] Use the right binder for rebinding PolyTraitRef --- .../rustc_trait_selection/src/traits/util.rs | 4 ++-- .../traits/alias/expand-higher-ranked-alias.rs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/alias/expand-higher-ranked-alias.rs diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index d30363ec1589a..15f5cf916a48b 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -47,11 +47,11 @@ pub fn expand_trait_aliases<'tcx>( queue.extend( tcx.explicit_super_predicates_of(trait_pred.def_id()) .iter_identity_copied() - .map(|(clause, span)| { + .map(|(super_clause, span)| { let mut spans = spans.clone(); spans.push(span); ( - clause.instantiate_supertrait( + super_clause.instantiate_supertrait( tcx, clause.kind().rebind(trait_pred.trait_ref), ), diff --git a/tests/ui/traits/alias/expand-higher-ranked-alias.rs b/tests/ui/traits/alias/expand-higher-ranked-alias.rs new file mode 100644 index 0000000000000..8a301d39f4c46 --- /dev/null +++ b/tests/ui/traits/alias/expand-higher-ranked-alias.rs @@ -0,0 +1,18 @@ +// Make sure we are using the right binder vars when expanding +// `for<'a> Foo<'a>` to `for<'a> Bar<'a>`. + +//@ check-pass + +#![feature(trait_alias)] + +trait Bar<'a> {} + +trait Foo<'a> = Bar<'a>; + +fn test2(_: &(impl for<'a> Foo<'a> + ?Sized)) {} + +fn test(x: &dyn for<'a> Foo<'a>) { + test2(x); +} + +fn main() {} From 9c03369c17c6eed8b6471cb7e176f7da99f6cdfb Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 11 Feb 2025 21:58:54 -0700 Subject: [PATCH 05/20] add `IntoBounds` trait for `range_into_bounds` feature, #136903 --- library/core/src/ops/mod.rs | 2 + library/core/src/ops/range.rs | 82 +++++++++++++++++++++++++++++++++++ library/core/src/range.rs | 28 +++++++++++- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 7b2ced2cc4bdc..627a875d9f724 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -182,6 +182,8 @@ pub use self::function::{Fn, FnMut, FnOnce}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::index::{Index, IndexMut}; pub(crate) use self::index_range::IndexRange; +#[unstable(feature = "range_into_bounds", issue = "136903")] +pub use self::range::IntoBounds; #[stable(feature = "inclusive_range", since = "1.26.0")] pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "one_sided_range", issue = "69780")] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 42e07a0e51da4..5580faefacc0d 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -831,6 +831,30 @@ pub trait RangeBounds { } } +/// Used to convert a range into start and end bounds, consuming the +/// range by value. +/// +/// `IntoBounds` is implemented by Rust’s built-in range types, produced +/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. +#[unstable(feature = "range_into_bounds", issue = "136903")] +pub trait IntoBounds: RangeBounds { + /// Convert this range into the start and end bounds. + /// Returns `(start_bound, end_bound)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(range_into_bounds)] + /// + /// use std::ops::Bound::*; + /// use std::ops::IntoBounds; + /// + /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5))); + /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7))); + /// ``` + fn into_bounds(self) -> (Bound, Bound); +} + use self::Bound::{Excluded, Included, Unbounded}; #[stable(feature = "collections_range", since = "1.28.0")] @@ -843,6 +867,13 @@ impl RangeBounds for RangeFull { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeFull { + fn into_bounds(self) -> (Bound, Bound) { + (Unbounded, Unbounded) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for RangeFrom { fn start_bound(&self) -> Bound<&T> { @@ -853,6 +884,13 @@ impl RangeBounds for RangeFrom { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeFrom { + fn into_bounds(self) -> (Bound, Bound) { + (Included(self.start), Unbounded) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for RangeTo { fn start_bound(&self) -> Bound<&T> { @@ -863,6 +901,13 @@ impl RangeBounds for RangeTo { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeTo { + fn into_bounds(self) -> (Bound, Bound) { + (Unbounded, Excluded(self.end)) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for Range { fn start_bound(&self) -> Bound<&T> { @@ -873,6 +918,13 @@ impl RangeBounds for Range { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for Range { + fn into_bounds(self) -> (Bound, Bound) { + (Included(self.start), Excluded(self.end)) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { @@ -889,6 +941,22 @@ impl RangeBounds for RangeInclusive { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeInclusive { + fn into_bounds(self) -> (Bound, Bound) { + ( + Included(self.start), + if self.exhausted { + // When the iterator is exhausted, we usually have start == end, + // but we want the range to appear empty, containing nothing. + Excluded(self.end) + } else { + Included(self.end) + }, + ) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for RangeToInclusive { fn start_bound(&self) -> Bound<&T> { @@ -899,6 +967,13 @@ impl RangeBounds for RangeToInclusive { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for RangeToInclusive { + fn into_bounds(self) -> (Bound, Bound) { + (Unbounded, Included(self.end)) + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl RangeBounds for (Bound, Bound) { fn start_bound(&self) -> Bound<&T> { @@ -918,6 +993,13 @@ impl RangeBounds for (Bound, Bound) { } } +#[unstable(feature = "range_into_bounds", issue = "136903")] +impl IntoBounds for (Bound, Bound) { + fn into_bounds(self) -> (Bound, Bound) { + self + } +} + #[stable(feature = "collections_range", since = "1.28.0")] impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { fn start_bound(&self) -> Bound<&T> { diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 6a62928873fe8..e94499065ac9a 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -31,7 +31,9 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive}; #[doc(inline)] pub use crate::iter::Step; #[doc(inline)] -pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive}; +pub use crate::ops::{ + Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive, +}; /// A (half-open) range bounded inclusively below and exclusively above /// (`start..end` in a future edition). @@ -175,6 +177,14 @@ impl RangeBounds for Range<&T> { } } +// #[unstable(feature = "range_into_bounds", issue = "136903")] +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoBounds for Range { + fn into_bounds(self) -> (Bound, Bound) { + (Included(self.start), Excluded(self.end)) + } +} + #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::Range { #[inline] @@ -343,6 +353,14 @@ impl RangeBounds for RangeInclusive<&T> { } } +// #[unstable(feature = "range_into_bounds", issue = "136903")] +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoBounds for RangeInclusive { + fn into_bounds(self) -> (Bound, Bound) { + (Included(self.start), Included(self.end)) + } +} + #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeInclusive { #[inline] @@ -479,6 +497,14 @@ impl RangeBounds for RangeFrom<&T> { } } +// #[unstable(feature = "range_into_bounds", issue = "136903")] +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoBounds for RangeFrom { + fn into_bounds(self) -> (Bound, Bound) { + (Included(self.start), Unbounded) + } +} + #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeFrom { #[inline] From 51b105d9f7a6c678da7dde6eb09d97d4f270a42a Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 12 Feb 2025 21:16:36 -0500 Subject: [PATCH 06/20] ignore vendor directory in `git status` --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ddc8dad95e809..2184e04f16b27 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,8 @@ no_llvm_build /library/target /src/bootstrap/target /src/tools/x/target +# Created by `x vendor` +/vendor # Created by default with `src/ci/docker/run.sh` /obj/ # Created by nix dev shell / .envrc From 1a3efd27abc25372930fef847ff2d2027f5e821a Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:04:10 +0100 Subject: [PATCH 07/20] Use `slice::fill` in `io::Repeat` implementation Use the existing `fill` methods on slices instead of manually writing the fill loop. --- library/std/src/io/util.rs | 28 ++++++++++------------------ library/std/src/lib.rs | 1 + 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 424f862090f09..cb3f864fd4e1e 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -7,6 +7,7 @@ use crate::fmt; use crate::io::{ self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; +use crate::mem::MaybeUninit; /// `Empty` ignores any data written via [`Write`], and will always be empty /// (returning zero bytes) when read via [`Read`]. @@ -182,35 +183,26 @@ pub const fn repeat(byte: u8) -> Repeat { impl Read for Repeat { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { - for slot in &mut *buf { - *slot = self.byte; - } + buf.fill(self.byte); Ok(buf.len()) } + #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - for slot in &mut *buf { - *slot = self.byte; - } + buf.fill(self.byte); Ok(()) } + #[inline] fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { - // SAFETY: No uninit bytes are being written - for slot in unsafe { buf.as_mut() } { - slot.write(self.byte); - } - - let remaining = buf.capacity(); - - // SAFETY: the entire unfilled portion of buf has been initialized - unsafe { - buf.advance_unchecked(remaining); - } - + // SAFETY: No uninit bytes are being written. + MaybeUninit::fill(unsafe { buf.as_mut() }, self.byte); + // SAFETY: the entire unfilled portion of buf has been initialized. + unsafe { buf.advance_unchecked(buf.capacity()) }; Ok(()) } + #[inline] fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { self.read_buf(buf) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index aea81b4bddee0..5ad19a981d958 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -302,6 +302,7 @@ #![feature(link_cfg)] #![feature(linkage)] #![feature(macro_metavar_expr_concat)] +#![feature(maybe_uninit_fill)] #![feature(min_specialization)] #![feature(must_not_suspend)] #![feature(needs_panic_runtime)] From d7eca8ac1524fea59f37f5bf02b072ca822532e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Feb 2025 12:12:37 +0100 Subject: [PATCH 08/20] Trace execution of bootstrap commands --- src/bootstrap/src/core/build_steps/compile.rs | 5 ++++- src/bootstrap/src/lib.rs | 2 ++ src/bootstrap/src/utils/exec.rs | 22 +++++++++++++++++++ src/bootstrap/src/utils/helpers.rs | 4 +++- src/bootstrap/src/utils/tracing.rs | 19 ++++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index a2375842bddef..9442d80841f0e 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -30,7 +30,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode}; +use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode, trace_cmd}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -2234,6 +2234,9 @@ pub fn stream_cargo( cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { let mut cmd = cargo.into_cmd(); + + let _run_span = trace_cmd!(cmd); + let cargo = cmd.as_command_mut(); // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 665ab117002e0..90b10a95c0eb9 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -905,6 +905,8 @@ impl Build { return CommandOutput::default(); } + let _run_span = trace_cmd!(command); + let created_at = command.get_created_location(); let executed_at = std::panic::Location::caller(); diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 1902dcd396283..f486ab3fe7547 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -329,3 +329,25 @@ impl Default for CommandOutput { } } } + +/// Helper trait to format both Command and BootstrapCommand as a short execution line, +/// without all the other details (e.g. environment variables). +#[allow(unused)] +pub trait FormatShortCmd { + fn format_short_cmd(&self) -> String; +} + +impl FormatShortCmd for BootstrapCommand { + fn format_short_cmd(&self) -> String { + self.command.format_short_cmd() + } +} + +impl FormatShortCmd for Command { + fn format_short_cmd(&self) -> String { + let program = Path::new(self.get_program()); + let mut line = vec![program.file_name().unwrap().to_str().unwrap()]; + line.extend(self.get_args().into_iter().map(|arg| arg.to_str().unwrap())); + line.join(" ") + } +} diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index a1b1748c85b53..244c4cc3c8576 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -13,11 +13,11 @@ use std::{env, fs, io, str}; use build_helper::util::fail; use object::read::archive::ArchiveFile; -use crate::LldMode; use crate::core::builder::Builder; use crate::core::config::{Config, TargetSelection}; use crate::utils::exec::{BootstrapCommand, command}; pub use crate::utils::shared_helpers::{dylib_path, dylib_path_var}; +use crate::{LldMode, trace_cmd}; #[cfg(test)] mod tests; @@ -265,6 +265,8 @@ pub fn make(host: &str) -> PathBuf { #[track_caller] pub fn output(cmd: &mut Command) -> String { + let _run_span = trace_cmd!(cmd); + let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")), diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs index e89decf9e5586..55531019f0332 100644 --- a/src/bootstrap/src/utils/tracing.rs +++ b/src/bootstrap/src/utils/tracing.rs @@ -47,3 +47,22 @@ macro_rules! error { ::tracing::error!($($tokens)*) } } + +#[macro_export] +macro_rules! trace_cmd { + ($cmd:expr) => { + { + #[allow(unused)] + use $crate::utils::exec::FormatShortCmd; + + #[cfg(feature = "tracing")] + ::tracing::span!( + target: "COMMAND", + ::tracing::Level::TRACE, + "executing command", + cmd = $cmd.format_short_cmd(), + full_cmd = ?$cmd + ).entered() + } + }; +} From 447a6a0322b887ebc8fc734b0582db8bc754967b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Feb 2025 13:35:36 +0100 Subject: [PATCH 09/20] Add export of bootstrap tracing to Chrome events --- src/bootstrap/Cargo.lock | 12 ++++++++++++ src/bootstrap/Cargo.toml | 3 ++- src/bootstrap/src/bin/main.rs | 16 +++++++++++++--- src/bootstrap/src/core/build_steps/compile.rs | 5 +++-- src/bootstrap/src/lib.rs | 1 + src/bootstrap/src/utils/exec.rs | 2 +- src/bootstrap/src/utils/helpers.rs | 5 +++-- src/bootstrap/src/utils/tracing.rs | 2 -- 8 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index d2f3c7f36ca86..a47f3af60cbd5 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -59,6 +59,7 @@ dependencies = [ "termcolor", "toml", "tracing", + "tracing-chrome", "tracing-subscriber", "tracing-tree", "walkdir", @@ -727,6 +728,17 @@ dependencies = [ "syn", ] +[[package]] +name = "tracing-chrome" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.33" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index d7afcc7f27d2e..ed51862390d40 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -7,7 +7,7 @@ default-run = "bootstrap" [features] build-metrics = ["sysinfo"] -tracing = ["dep:tracing", "dep:tracing-subscriber", "dep:tracing-tree"] +tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-tree"] [lib] path = "src/lib.rs" @@ -67,6 +67,7 @@ sysinfo = { version = "0.33.0", default-features = false, optional = true, featu # Dependencies needed by the `tracing` feature tracing = { version = "0.1", optional = true, features = ["attributes"] } +tracing-chrome = { version = "0.7", optional = true } tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] } tracing-tree = { version = "0.4.0", optional = true } diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 441674936c666..38b380e3db824 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -21,7 +21,7 @@ use tracing::instrument; #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))] fn main() { #[cfg(feature = "tracing")] - setup_tracing(); + let _guard = setup_tracing(); let args = env::args().skip(1).collect::>(); @@ -210,7 +210,7 @@ fn check_version(config: &Config) -> Option { // - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature = // "tracing", instrument(..))]`. #[cfg(feature = "tracing")] -fn setup_tracing() { +fn setup_tracing() -> impl Drop { use tracing_subscriber::EnvFilter; use tracing_subscriber::layer::SubscriberExt; @@ -218,7 +218,17 @@ fn setup_tracing() { // cf. . let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2); - let registry = tracing_subscriber::registry().with(filter).with(layer); + let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true); + + // Writes the Chrome profile to trace-.json if enabled + if !env::var("BOOTSTRAP_PROFILE").is_ok_and(|v| v == "1") { + chrome_layer = chrome_layer.writer(io::sink()); + } + + let (chrome_layer, _guard) = chrome_layer.build(); + + let registry = tracing_subscriber::registry().with(filter).with(layer).with(chrome_layer); tracing::subscriber::set_global_default(registry).unwrap(); + _guard } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 9442d80841f0e..8e5a8b7e2541c 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -30,7 +30,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode, trace_cmd}; +use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -2235,7 +2235,8 @@ pub fn stream_cargo( ) -> bool { let mut cmd = cargo.into_cmd(); - let _run_span = trace_cmd!(cmd); + #[cfg(feature = "tracing")] + let _run_span = crate::trace_cmd!(cmd); let cargo = cmd.as_command_mut(); // Instruct Cargo to give us json messages on stdout, critically leaving diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 90b10a95c0eb9..7cd8aacf0d6c8 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -905,6 +905,7 @@ impl Build { return CommandOutput::default(); } + #[cfg(feature = "tracing")] let _run_span = trace_cmd!(command); let created_at = command.get_created_location(); diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index f486ab3fe7547..7eb9ab96c8a4a 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -347,7 +347,7 @@ impl FormatShortCmd for Command { fn format_short_cmd(&self) -> String { let program = Path::new(self.get_program()); let mut line = vec![program.file_name().unwrap().to_str().unwrap()]; - line.extend(self.get_args().into_iter().map(|arg| arg.to_str().unwrap())); + line.extend(self.get_args().map(|arg| arg.to_str().unwrap())); line.join(" ") } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 244c4cc3c8576..3fee397da091d 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -13,11 +13,11 @@ use std::{env, fs, io, str}; use build_helper::util::fail; use object::read::archive::ArchiveFile; +use crate::LldMode; use crate::core::builder::Builder; use crate::core::config::{Config, TargetSelection}; use crate::utils::exec::{BootstrapCommand, command}; pub use crate::utils::shared_helpers::{dylib_path, dylib_path_var}; -use crate::{LldMode, trace_cmd}; #[cfg(test)] mod tests; @@ -265,7 +265,8 @@ pub fn make(host: &str) -> PathBuf { #[track_caller] pub fn output(cmd: &mut Command) -> String { - let _run_span = trace_cmd!(cmd); + #[cfg(feature = "tracing")] + let _run_span = crate::trace_cmd!(cmd); let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs index 55531019f0332..99849341dc3b9 100644 --- a/src/bootstrap/src/utils/tracing.rs +++ b/src/bootstrap/src/utils/tracing.rs @@ -52,10 +52,8 @@ macro_rules! error { macro_rules! trace_cmd { ($cmd:expr) => { { - #[allow(unused)] use $crate::utils::exec::FormatShortCmd; - #[cfg(feature = "tracing")] ::tracing::span!( target: "COMMAND", ::tracing::Level::TRACE, From 521cbd36fa1cc645a3682fe429b4d636b16b6fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 12 Feb 2025 13:48:48 +0100 Subject: [PATCH 10/20] Document bootstrap profiling --- .../src/building/bootstrapping/debugging-bootstrap.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md index 3f907e85dd6cc..04fa5b204dd4e 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md @@ -121,6 +121,14 @@ For `#[instrument]`, it's recommended to: - Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps. - Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled. +### Profiling bootstrap + +You can use the `COMMAND` tracing target to trace execution of most commands spawned by bootstrap. If you also use the `BOOTSTRAP_PROFILE=1` environment variable, bootstrap will generate a Chrome JSON trace file, which can be visualized in Chrome's `chrome://tracing` page or on https://ui.perfetto.dev. + +```bash +$ BOOTSTRAP_TRACING=COMMAND=trace BOOTSTRAP_PROFILE=1 ./x build library +``` + ### rust-analyzer integration? Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in . From ce9bf4a61214c89dcdb4055937597adf9993ab5c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:38:59 +0000 Subject: [PATCH 11/20] Move all alloc integration tests to a new alloctests crate --- library/Cargo.lock | 8 ++++ library/Cargo.toml | 1 + library/alloc/Cargo.toml | 18 -------- .../alloc/src/{raw_vec.rs => raw_vec/mod.rs} | 0 library/alloc/src/{rc.rs => rc/mod.rs} | 0 library/alloctests/Cargo.toml | 46 +++++++++++++++++++ .../benches/binary_heap.rs | 0 .../benches/btree/map.rs | 0 .../benches/btree/mod.rs | 0 .../benches/btree/set.rs | 0 library/{alloc => alloctests}/benches/lib.rs | 0 .../benches/linked_list.rs | 0 .../{alloc => alloctests}/benches/slice.rs | 0 library/{alloc => alloctests}/benches/str.rs | 0 .../{alloc => alloctests}/benches/string.rs | 0 library/{alloc => alloctests}/benches/vec.rs | 0 .../benches/vec_deque.rs | 0 .../benches/vec_deque_append.rs | 0 library/alloctests/lib.rs | 1 + .../tests/alloc_test.rs} | 0 library/{alloc => alloctests}/tests/arc.rs | 0 .../{alloc => alloctests}/tests/autotraits.rs | 0 library/{alloc => alloctests}/tests/borrow.rs | 0 library/{alloc => alloctests}/tests/boxed.rs | 0 .../tests/btree_set_hash.rs | 0 library/{alloc => alloctests}/tests/c_str.rs | 0 library/{alloc => alloctests}/tests/c_str2.rs | 0 .../tests/collections/binary_heap.rs | 0 .../tests/collections/mod.rs | 0 .../{alloc => alloctests}/tests/const_fns.rs | 0 .../{alloc => alloctests}/tests/cow_str.rs | 0 library/{alloc => alloctests}/tests/fmt.rs | 0 library/{alloc => alloctests}/tests/heap.rs | 0 library/{alloc => alloctests}/tests/lib.rs | 3 +- .../tests/linked_list.rs | 0 .../{alloc => alloctests}/tests/misc_tests.rs | 0 library/{alloc => alloctests}/tests/rc.rs | 0 library/{alloc => alloctests}/tests/slice.rs | 0 .../tests/sort/ffi_types.rs | 0 .../tests/sort/known_good_stable_sort.rs | 0 .../{alloc => alloctests}/tests/sort/mod.rs | 0 .../tests/sort/patterns.rs | 0 .../{alloc => alloctests}/tests/sort/tests.rs | 0 .../{alloc => alloctests}/tests/sort/zipf.rs | 0 library/{alloc => alloctests}/tests/str.rs | 0 library/{alloc => alloctests}/tests/string.rs | 0 library/{alloc => alloctests}/tests/sync.rs | 0 library/{alloc => alloctests}/tests/task.rs | 0 .../tests/testing/crash_test.rs | 0 .../tests/testing/mod.rs | 0 .../{alloc => alloctests}/tests/thin_box.rs | 0 library/{alloc => alloctests}/tests/vec.rs | 0 .../{alloc => alloctests}/tests/vec_deque.rs | 0 .../tests/vec_deque_alloc_error.rs | 0 src/bootstrap/mk/Makefile.in | 2 + src/bootstrap/src/core/build_steps/check.rs | 5 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/tools/tidy/src/style.rs | 2 +- 58 files changed, 66 insertions(+), 22 deletions(-) rename library/alloc/src/{raw_vec.rs => raw_vec/mod.rs} (100%) rename library/alloc/src/{rc.rs => rc/mod.rs} (100%) create mode 100644 library/alloctests/Cargo.toml rename library/{alloc => alloctests}/benches/binary_heap.rs (100%) rename library/{alloc => alloctests}/benches/btree/map.rs (100%) rename library/{alloc => alloctests}/benches/btree/mod.rs (100%) rename library/{alloc => alloctests}/benches/btree/set.rs (100%) rename library/{alloc => alloctests}/benches/lib.rs (100%) rename library/{alloc => alloctests}/benches/linked_list.rs (100%) rename library/{alloc => alloctests}/benches/slice.rs (100%) rename library/{alloc => alloctests}/benches/str.rs (100%) rename library/{alloc => alloctests}/benches/string.rs (100%) rename library/{alloc => alloctests}/benches/vec.rs (100%) rename library/{alloc => alloctests}/benches/vec_deque.rs (100%) rename library/{alloc => alloctests}/benches/vec_deque_append.rs (100%) create mode 100644 library/alloctests/lib.rs rename library/{alloc/tests/alloc.rs => alloctests/tests/alloc_test.rs} (100%) rename library/{alloc => alloctests}/tests/arc.rs (100%) rename library/{alloc => alloctests}/tests/autotraits.rs (100%) rename library/{alloc => alloctests}/tests/borrow.rs (100%) rename library/{alloc => alloctests}/tests/boxed.rs (100%) rename library/{alloc => alloctests}/tests/btree_set_hash.rs (100%) rename library/{alloc => alloctests}/tests/c_str.rs (100%) rename library/{alloc => alloctests}/tests/c_str2.rs (100%) rename library/{alloc => alloctests}/tests/collections/binary_heap.rs (100%) rename library/{alloc => alloctests}/tests/collections/mod.rs (100%) rename library/{alloc => alloctests}/tests/const_fns.rs (100%) rename library/{alloc => alloctests}/tests/cow_str.rs (100%) rename library/{alloc => alloctests}/tests/fmt.rs (100%) rename library/{alloc => alloctests}/tests/heap.rs (100%) rename library/{alloc => alloctests}/tests/lib.rs (98%) rename library/{alloc => alloctests}/tests/linked_list.rs (100%) rename library/{alloc => alloctests}/tests/misc_tests.rs (100%) rename library/{alloc => alloctests}/tests/rc.rs (100%) rename library/{alloc => alloctests}/tests/slice.rs (100%) rename library/{alloc => alloctests}/tests/sort/ffi_types.rs (100%) rename library/{alloc => alloctests}/tests/sort/known_good_stable_sort.rs (100%) rename library/{alloc => alloctests}/tests/sort/mod.rs (100%) rename library/{alloc => alloctests}/tests/sort/patterns.rs (100%) rename library/{alloc => alloctests}/tests/sort/tests.rs (100%) rename library/{alloc => alloctests}/tests/sort/zipf.rs (100%) rename library/{alloc => alloctests}/tests/str.rs (100%) rename library/{alloc => alloctests}/tests/string.rs (100%) rename library/{alloc => alloctests}/tests/sync.rs (100%) rename library/{alloc => alloctests}/tests/task.rs (100%) rename library/{alloc => alloctests}/tests/testing/crash_test.rs (100%) rename library/{alloc => alloctests}/tests/testing/mod.rs (100%) rename library/{alloc => alloctests}/tests/thin_box.rs (100%) rename library/{alloc => alloctests}/tests/vec.rs (100%) rename library/{alloc => alloctests}/tests/vec_deque.rs (100%) rename library/{alloc => alloctests}/tests/vec_deque_alloc_error.rs (100%) diff --git a/library/Cargo.lock b/library/Cargo.lock index 930db2ecd5796..7d83b93489ed6 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -40,6 +40,14 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloctests" +version = "0.0.0" +dependencies = [ + "rand", + "rand_xorshift", +] + [[package]] name = "cc" version = "1.2.0" diff --git a/library/Cargo.toml b/library/Cargo.toml index 1205f7c9ed6b5..4d5955593ffcd 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -4,6 +4,7 @@ members = [ "std", "sysroot", "coretests", + "alloctests", ] exclude = [ diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 6b0b5761391c7..b9d5bb53d918e 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,24 +16,6 @@ compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } rand = { version = "0.8.5", default-features = false, features = ["alloc"] } rand_xorshift = "0.3.0" -[[test]] -name = "alloctests" -path = "tests/lib.rs" - -[[test]] -name = "vec_deque_alloc_error" -path = "tests/vec_deque_alloc_error.rs" - -[[bench]] -name = "allocbenches" -path = "benches/lib.rs" -test = true - -[[bench]] -name = "vec_deque_append_bench" -path = "benches/vec_deque_append.rs" -harness = false - [features] compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec/mod.rs similarity index 100% rename from library/alloc/src/raw_vec.rs rename to library/alloc/src/raw_vec/mod.rs diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc/mod.rs similarity index 100% rename from library/alloc/src/rc.rs rename to library/alloc/src/rc/mod.rs diff --git a/library/alloctests/Cargo.toml b/library/alloctests/Cargo.toml new file mode 100644 index 0000000000000..93c7c786e881b --- /dev/null +++ b/library/alloctests/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "alloctests" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Tests for the Rust Allocation Library" +autotests = false +autobenches = false +edition = "2021" + +[lib] +path = "lib.rs" +test = false +bench = false + +[dev-dependencies] +rand = { version = "0.8.5", default-features = false, features = ["alloc"] } +rand_xorshift = "0.3.0" + +[[test]] +name = "alloctests" +path = "tests/lib.rs" + +[[test]] +name = "vec_deque_alloc_error" +path = "tests/vec_deque_alloc_error.rs" + +[[bench]] +name = "allocbenches" +path = "benches/lib.rs" +test = true + +[[bench]] +name = "vec_deque_append_bench" +path = "benches/vec_deque_append.rs" +harness = false + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + 'cfg(bootstrap)', + 'cfg(no_global_oom_handling)', + 'cfg(no_rc)', + 'cfg(no_sync)', + 'cfg(randomized_layouts)', +] diff --git a/library/alloc/benches/binary_heap.rs b/library/alloctests/benches/binary_heap.rs similarity index 100% rename from library/alloc/benches/binary_heap.rs rename to library/alloctests/benches/binary_heap.rs diff --git a/library/alloc/benches/btree/map.rs b/library/alloctests/benches/btree/map.rs similarity index 100% rename from library/alloc/benches/btree/map.rs rename to library/alloctests/benches/btree/map.rs diff --git a/library/alloc/benches/btree/mod.rs b/library/alloctests/benches/btree/mod.rs similarity index 100% rename from library/alloc/benches/btree/mod.rs rename to library/alloctests/benches/btree/mod.rs diff --git a/library/alloc/benches/btree/set.rs b/library/alloctests/benches/btree/set.rs similarity index 100% rename from library/alloc/benches/btree/set.rs rename to library/alloctests/benches/btree/set.rs diff --git a/library/alloc/benches/lib.rs b/library/alloctests/benches/lib.rs similarity index 100% rename from library/alloc/benches/lib.rs rename to library/alloctests/benches/lib.rs diff --git a/library/alloc/benches/linked_list.rs b/library/alloctests/benches/linked_list.rs similarity index 100% rename from library/alloc/benches/linked_list.rs rename to library/alloctests/benches/linked_list.rs diff --git a/library/alloc/benches/slice.rs b/library/alloctests/benches/slice.rs similarity index 100% rename from library/alloc/benches/slice.rs rename to library/alloctests/benches/slice.rs diff --git a/library/alloc/benches/str.rs b/library/alloctests/benches/str.rs similarity index 100% rename from library/alloc/benches/str.rs rename to library/alloctests/benches/str.rs diff --git a/library/alloc/benches/string.rs b/library/alloctests/benches/string.rs similarity index 100% rename from library/alloc/benches/string.rs rename to library/alloctests/benches/string.rs diff --git a/library/alloc/benches/vec.rs b/library/alloctests/benches/vec.rs similarity index 100% rename from library/alloc/benches/vec.rs rename to library/alloctests/benches/vec.rs diff --git a/library/alloc/benches/vec_deque.rs b/library/alloctests/benches/vec_deque.rs similarity index 100% rename from library/alloc/benches/vec_deque.rs rename to library/alloctests/benches/vec_deque.rs diff --git a/library/alloc/benches/vec_deque_append.rs b/library/alloctests/benches/vec_deque_append.rs similarity index 100% rename from library/alloc/benches/vec_deque_append.rs rename to library/alloctests/benches/vec_deque_append.rs diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs new file mode 100644 index 0000000000000..b49208cd4eb3a --- /dev/null +++ b/library/alloctests/lib.rs @@ -0,0 +1 @@ +// Intentionally left empty. diff --git a/library/alloc/tests/alloc.rs b/library/alloctests/tests/alloc_test.rs similarity index 100% rename from library/alloc/tests/alloc.rs rename to library/alloctests/tests/alloc_test.rs diff --git a/library/alloc/tests/arc.rs b/library/alloctests/tests/arc.rs similarity index 100% rename from library/alloc/tests/arc.rs rename to library/alloctests/tests/arc.rs diff --git a/library/alloc/tests/autotraits.rs b/library/alloctests/tests/autotraits.rs similarity index 100% rename from library/alloc/tests/autotraits.rs rename to library/alloctests/tests/autotraits.rs diff --git a/library/alloc/tests/borrow.rs b/library/alloctests/tests/borrow.rs similarity index 100% rename from library/alloc/tests/borrow.rs rename to library/alloctests/tests/borrow.rs diff --git a/library/alloc/tests/boxed.rs b/library/alloctests/tests/boxed.rs similarity index 100% rename from library/alloc/tests/boxed.rs rename to library/alloctests/tests/boxed.rs diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloctests/tests/btree_set_hash.rs similarity index 100% rename from library/alloc/tests/btree_set_hash.rs rename to library/alloctests/tests/btree_set_hash.rs diff --git a/library/alloc/tests/c_str.rs b/library/alloctests/tests/c_str.rs similarity index 100% rename from library/alloc/tests/c_str.rs rename to library/alloctests/tests/c_str.rs diff --git a/library/alloc/tests/c_str2.rs b/library/alloctests/tests/c_str2.rs similarity index 100% rename from library/alloc/tests/c_str2.rs rename to library/alloctests/tests/c_str2.rs diff --git a/library/alloc/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs similarity index 100% rename from library/alloc/tests/collections/binary_heap.rs rename to library/alloctests/tests/collections/binary_heap.rs diff --git a/library/alloc/tests/collections/mod.rs b/library/alloctests/tests/collections/mod.rs similarity index 100% rename from library/alloc/tests/collections/mod.rs rename to library/alloctests/tests/collections/mod.rs diff --git a/library/alloc/tests/const_fns.rs b/library/alloctests/tests/const_fns.rs similarity index 100% rename from library/alloc/tests/const_fns.rs rename to library/alloctests/tests/const_fns.rs diff --git a/library/alloc/tests/cow_str.rs b/library/alloctests/tests/cow_str.rs similarity index 100% rename from library/alloc/tests/cow_str.rs rename to library/alloctests/tests/cow_str.rs diff --git a/library/alloc/tests/fmt.rs b/library/alloctests/tests/fmt.rs similarity index 100% rename from library/alloc/tests/fmt.rs rename to library/alloctests/tests/fmt.rs diff --git a/library/alloc/tests/heap.rs b/library/alloctests/tests/heap.rs similarity index 100% rename from library/alloc/tests/heap.rs rename to library/alloctests/tests/heap.rs diff --git a/library/alloc/tests/lib.rs b/library/alloctests/tests/lib.rs similarity index 98% rename from library/alloc/tests/lib.rs rename to library/alloctests/tests/lib.rs index 1bcec4037cdd6..9f5ffb84b7858 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -44,11 +44,12 @@ #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] +extern crate alloc; extern crate test; use std::hash::{DefaultHasher, Hash, Hasher}; -mod alloc; +mod alloc_test; mod arc; mod autotraits; mod borrow; diff --git a/library/alloc/tests/linked_list.rs b/library/alloctests/tests/linked_list.rs similarity index 100% rename from library/alloc/tests/linked_list.rs rename to library/alloctests/tests/linked_list.rs diff --git a/library/alloc/tests/misc_tests.rs b/library/alloctests/tests/misc_tests.rs similarity index 100% rename from library/alloc/tests/misc_tests.rs rename to library/alloctests/tests/misc_tests.rs diff --git a/library/alloc/tests/rc.rs b/library/alloctests/tests/rc.rs similarity index 100% rename from library/alloc/tests/rc.rs rename to library/alloctests/tests/rc.rs diff --git a/library/alloc/tests/slice.rs b/library/alloctests/tests/slice.rs similarity index 100% rename from library/alloc/tests/slice.rs rename to library/alloctests/tests/slice.rs diff --git a/library/alloc/tests/sort/ffi_types.rs b/library/alloctests/tests/sort/ffi_types.rs similarity index 100% rename from library/alloc/tests/sort/ffi_types.rs rename to library/alloctests/tests/sort/ffi_types.rs diff --git a/library/alloc/tests/sort/known_good_stable_sort.rs b/library/alloctests/tests/sort/known_good_stable_sort.rs similarity index 100% rename from library/alloc/tests/sort/known_good_stable_sort.rs rename to library/alloctests/tests/sort/known_good_stable_sort.rs diff --git a/library/alloc/tests/sort/mod.rs b/library/alloctests/tests/sort/mod.rs similarity index 100% rename from library/alloc/tests/sort/mod.rs rename to library/alloctests/tests/sort/mod.rs diff --git a/library/alloc/tests/sort/patterns.rs b/library/alloctests/tests/sort/patterns.rs similarity index 100% rename from library/alloc/tests/sort/patterns.rs rename to library/alloctests/tests/sort/patterns.rs diff --git a/library/alloc/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs similarity index 100% rename from library/alloc/tests/sort/tests.rs rename to library/alloctests/tests/sort/tests.rs diff --git a/library/alloc/tests/sort/zipf.rs b/library/alloctests/tests/sort/zipf.rs similarity index 100% rename from library/alloc/tests/sort/zipf.rs rename to library/alloctests/tests/sort/zipf.rs diff --git a/library/alloc/tests/str.rs b/library/alloctests/tests/str.rs similarity index 100% rename from library/alloc/tests/str.rs rename to library/alloctests/tests/str.rs diff --git a/library/alloc/tests/string.rs b/library/alloctests/tests/string.rs similarity index 100% rename from library/alloc/tests/string.rs rename to library/alloctests/tests/string.rs diff --git a/library/alloc/tests/sync.rs b/library/alloctests/tests/sync.rs similarity index 100% rename from library/alloc/tests/sync.rs rename to library/alloctests/tests/sync.rs diff --git a/library/alloc/tests/task.rs b/library/alloctests/tests/task.rs similarity index 100% rename from library/alloc/tests/task.rs rename to library/alloctests/tests/task.rs diff --git a/library/alloc/tests/testing/crash_test.rs b/library/alloctests/tests/testing/crash_test.rs similarity index 100% rename from library/alloc/tests/testing/crash_test.rs rename to library/alloctests/tests/testing/crash_test.rs diff --git a/library/alloc/tests/testing/mod.rs b/library/alloctests/tests/testing/mod.rs similarity index 100% rename from library/alloc/tests/testing/mod.rs rename to library/alloctests/tests/testing/mod.rs diff --git a/library/alloc/tests/thin_box.rs b/library/alloctests/tests/thin_box.rs similarity index 100% rename from library/alloc/tests/thin_box.rs rename to library/alloctests/tests/thin_box.rs diff --git a/library/alloc/tests/vec.rs b/library/alloctests/tests/vec.rs similarity index 100% rename from library/alloc/tests/vec.rs rename to library/alloctests/tests/vec.rs diff --git a/library/alloc/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs similarity index 100% rename from library/alloc/tests/vec_deque.rs rename to library/alloctests/tests/vec_deque.rs diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloctests/tests/vec_deque_alloc_error.rs similarity index 100% rename from library/alloc/tests/vec_deque_alloc_error.rs rename to library/alloctests/tests/vec_deque_alloc_error.rs diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 7e6a39a236e07..b5ad868f21055 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -56,6 +56,7 @@ check-aux: # Run standard library tests in Miri. $(Q)$(BOOTSTRAP) miri --stage 2 \ library/coretests \ + library/alloctests \ library/alloc \ $(BOOTSTRAP_ARGS) \ --no-doc @@ -63,6 +64,7 @@ check-aux: $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 \ library/coretests \ + library/alloctests \ library/alloc \ $(BOOTSTRAP_ARGS) \ --doc diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 21afb0312033a..62500baea5b9e 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -45,7 +45,10 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").crate_or_deps("coretests").path("library") + run.crate_or_deps("sysroot") + .crate_or_deps("coretests") + .crate_or_deps("alloctests") + .path("library") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 509875a469f1f..a9da55f445197 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2668,7 +2668,7 @@ impl Step for Crate { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").crate_or_deps("coretests") + run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests") } fn make_run(run: RunConfig<'_>) { diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 21b513629ed8d..32ae1e8f8c246 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -462,7 +462,7 @@ pub fn check(path: &Path, bad: &mut bool) { && !trimmed.starts_with("//") && !file.ancestors().any(|a| { (a.ends_with("tests") && a.join("COMPILER_TESTS.md").exists()) - || a.ends_with("library/alloc/tests") + || a.ends_with("library/alloctests") }) && filename != "tests.rs" { From 4a01dcc98596f86079241f28468f2fdb3db34b75 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:07:24 +0000 Subject: [PATCH 12/20] Move most Rc tests to alloctests --- library/alloc/src/rc/tests.rs | 649 --------------------------------- library/alloctests/tests/rc.rs | 648 +++++++++++++++++++++++++++++++- 2 files changed, 647 insertions(+), 650 deletions(-) diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 2210a7c24c06a..35ff6b7d570d0 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -1,64 +1,5 @@ -use std::cell::RefCell; -use std::clone::Clone; - use super::*; -#[test] -fn test_clone() { - let x = Rc::new(RefCell::new(5)); - let y = x.clone(); - *x.borrow_mut() = 20; - assert_eq!(*y.borrow(), 20); -} - -#[test] -fn test_simple() { - let x = Rc::new(5); - assert_eq!(*x, 5); -} - -#[test] -fn test_simple_clone() { - let x = Rc::new(5); - let y = x.clone(); - assert_eq!(*x, 5); - assert_eq!(*y, 5); -} - -#[test] -fn test_destructor() { - let x: Rc> = Rc::new(Box::new(5)); - assert_eq!(**x, 5); -} - -#[test] -fn test_live() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - assert!(y.upgrade().is_some()); -} - -#[test] -fn test_dead() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); -} - -#[test] -fn weak_self_cyclic() { - struct Cycle { - x: RefCell>>, - } - - let a = Rc::new(Cycle { x: RefCell::new(None) }); - let b = Rc::downgrade(&a.clone()); - *a.x.borrow_mut() = Some(b); - - // hopefully we don't double-free (or leak)... -} - #[test] fn is_unique() { let x = Rc::new(3); @@ -72,593 +13,3 @@ fn is_unique() { drop(w); assert!(Rc::is_unique(&x)); } - -#[test] -fn test_strong_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - let b = w.upgrade().expect("upgrade of live rc failed"); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Rc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&c) == 2); -} - -#[test] -fn test_weak_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 1); - drop(w); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Rc::strong_count(&a) == 2); - assert!(Rc::weak_count(&a) == 0); - drop(c); -} - -#[test] -fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::::new()), 0); - assert_eq!(Weak::strong_count(&Weak::::new()), 0); - - let a = Rc::new(0); - let w = Rc::downgrade(&a); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 1); - let w2 = w.clone(); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 2); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 2); - drop(w); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 1); - let a2 = a.clone(); - assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), 1); - drop(a2); - drop(a); - assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), 0); - drop(w2); -} - -#[test] -fn try_unwrap() { - let x = Rc::new(3); - assert_eq!(Rc::try_unwrap(x), Ok(3)); - let x = Rc::new(4); - let _y = x.clone(); - assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); - let x = Rc::new(5); - let _w = Rc::downgrade(&x); - assert_eq!(Rc::try_unwrap(x), Ok(5)); -} - -#[test] -fn into_inner() { - let x = Rc::new(3); - assert_eq!(Rc::into_inner(x), Some(3)); - - let x = Rc::new(4); - let y = Rc::clone(&x); - assert_eq!(Rc::into_inner(x), None); - assert_eq!(Rc::into_inner(y), Some(4)); - - let x = Rc::new(5); - let _w = Rc::downgrade(&x); - assert_eq!(Rc::into_inner(x), Some(5)); -} - -#[test] -fn into_from_raw() { - let x = Rc::new(Box::new("hello")); - let y = x.clone(); - - let x_ptr = Rc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Rc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let rc: Rc = Rc::from("foo"); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert_eq!(rc, rc2); - - let rc: Rc = Rc::new(123); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert_eq!(rc2.to_string(), "123"); -} - -#[test] -fn into_from_weak_raw() { - let x = Rc::new(Box::new("hello")); - let y = Rc::downgrade(&x); - - let y_ptr = Weak::into_raw(y); - unsafe { - assert_eq!(**y_ptr, "hello"); - - let y = Weak::from_raw(y_ptr); - let y_up = Weak::upgrade(&y).unwrap(); - assert_eq!(**y_up, "hello"); - drop(y_up); - - assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_weak_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Rc = Rc::from("foo"); - let weak: Weak = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert!(weak.ptr_eq(&weak2)); - - let arc: Rc = Rc::new(123); - let weak: Weak = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert!(weak.ptr_eq(&weak2)); -} - -#[test] -fn get_mut() { - let mut x = Rc::new(3); - *Rc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Rc::get_mut(&mut x).is_none()); - drop(y); - assert!(Rc::get_mut(&mut x).is_some()); - let _w = Rc::downgrade(&x); - assert!(Rc::get_mut(&mut x).is_none()); -} - -#[test] -fn test_cowrc_clone_make_unique() { - let mut cow0 = Rc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Rc::make_mut(&mut cow0)); - assert!(75 == *Rc::make_mut(&mut cow1)); - assert!(75 == *Rc::make_mut(&mut cow2)); - - *Rc::make_mut(&mut cow0) += 1; - *Rc::make_mut(&mut cow1) += 2; - *Rc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); -} - -#[test] -fn test_cowrc_clone_unique2() { - let mut cow0 = Rc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); -} - -#[test] -fn test_cowrc_clone_weak() { - let mut cow0 = Rc::new(75); - let cow1_weak = Rc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); -} - -/// This is similar to the doc-test for `Rc::make_mut()`, but on an unsized type (slice). -#[test] -fn test_cowrc_unsized() { - use std::rc::Rc; - - let mut data: Rc<[i32]> = Rc::new([10, 20, 30]); - - Rc::make_mut(&mut data)[0] += 1; // Won't clone anything - let mut other_data = Rc::clone(&data); // Won't clone inner data - Rc::make_mut(&mut data)[1] += 1; // Clones inner data - Rc::make_mut(&mut data)[2] += 1; // Won't clone anything - Rc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything - - // Now `data` and `other_data` point to different allocations. - assert_eq!(*data, [11, 21, 31]); - assert_eq!(*other_data, [110, 20, 30]); -} - -#[test] -fn test_show() { - let foo = Rc::new(75); - assert_eq!(format!("{foo:?}"), "75"); -} - -#[test] -fn test_unsized() { - let foo: Rc<[i32]> = Rc::new([1, 2, 3]); - assert_eq!(foo, foo.clone()); -} - -#[test] -fn test_maybe_thin_unsized() { - // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::CStr; - - let x: Rc = Rc::from(c"swordfish"); - assert_eq!(format!("{x:?}"), "\"swordfish\""); - let y: Weak = Rc::downgrade(&x); - drop(x); - - // At this point, the weak points to a dropped DST - assert!(y.upgrade().is_none()); - // But we still need to be able to get the alloc layout to drop. - // CStr has no drop glue, but custom DSTs might, and need to work. - drop(y); -} - -#[test] -fn test_from_owned() { - let foo = 123; - let foo_rc = Rc::from(foo); - assert!(123 == *foo_rc); -} - -#[test] -fn test_new_weak() { - let foo: Weak = Weak::new(); - assert!(foo.upgrade().is_none()); -} - -#[test] -fn test_ptr_eq() { - let five = Rc::new(5); - let same_five = five.clone(); - let other_five = Rc::new(5); - - assert!(Rc::ptr_eq(&five, &same_five)); - assert!(!Rc::ptr_eq(&five, &other_five)); -} - -#[test] -fn test_from_str() { - let r: Rc = Rc::from("foo"); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_copy_from_slice() { - let s: &[u32] = &[1, 2, 3]; - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_clone_from_slice() { - #[derive(Clone, Debug, Eq, PartialEq)] - struct X(u32); - - let s: &[X] = &[X(1), X(2), X(3)]; - let r: Rc<[X]> = Rc::from(s); - - assert_eq!(&r[..], s); -} - -#[test] -#[should_panic] -fn test_clone_from_slice_panic() { - use std::string::{String, ToString}; - - struct Fail(u32, String); - - impl Clone for Fail { - fn clone(&self) -> Fail { - if self.0 == 2 { - panic!(); - } - Fail(self.0, self.1.clone()) - } - } - - let s: &[Fail] = - &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; - - // Should panic, but not cause memory corruption - let _r: Rc<[Fail]> = Rc::from(s); -} - -#[test] -fn test_from_box() { - let b: Box = Box::new(123); - let r: Rc = Rc::from(b); - - assert_eq!(*r, 123); -} - -#[test] -fn test_from_box_str() { - use std::string::String; - - let s = String::from("foo").into_boxed_str(); - assert_eq!((&&&s).as_str(), "foo"); - - let r: Rc = Rc::from(s); - assert_eq!((&r).as_str(), "foo"); - assert_eq!(r.as_str(), "foo"); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_from_box_slice() { - let s = vec![1, 2, 3].into_boxed_slice(); - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_from_box_trait() { - use std::fmt::Display; - use std::string::ToString; - - let b: Box = Box::new(123); - let r: Rc = Rc::from(b); - - assert_eq!(r.to_string(), "123"); -} - -#[test] -fn test_from_box_trait_zero_sized() { - use std::fmt::Debug; - - let b: Box = Box::new(()); - let r: Rc = Rc::from(b); - - assert_eq!(format!("{r:?}"), "()"); -} - -#[test] -fn test_from_vec() { - let v = vec![1, 2, 3]; - let r: Rc<[u32]> = Rc::from(v); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_downcast() { - use std::any::Any; - - let r1: Rc = Rc::new(i32::MAX); - let r2: Rc = Rc::new("abc"); - - assert!(r1.clone().downcast::().is_err()); - - let r1i32 = r1.downcast::(); - assert!(r1i32.is_ok()); - assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX)); - - assert!(r2.clone().downcast::().is_err()); - - let r2str = r2.downcast::<&'static str>(); - assert!(r2str.is_ok()); - assert_eq!(r2str.unwrap(), Rc::new("abc")); -} - -#[test] -fn test_array_from_slice() { - let v = vec![1, 2, 3]; - let r: Rc<[u32]> = Rc::from(v); - - let a: Result, _> = r.clone().try_into(); - assert!(a.is_ok()); - - let a: Result, _> = r.clone().try_into(); - assert!(a.is_err()); -} - -#[test] -fn test_rc_cyclic_with_zero_refs() { - struct ZeroRefs { - inner: Weak, - } - - let zero_refs = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - ZeroRefs { inner: Weak::new() } - }); - - assert_eq!(Rc::strong_count(&zero_refs), 1); - assert_eq!(Rc::weak_count(&zero_refs), 0); - assert_eq!(zero_refs.inner.strong_count(), 0); - assert_eq!(zero_refs.inner.weak_count(), 0); -} - -#[test] -fn test_rc_cyclic_with_one_ref() { - struct OneRef { - inner: Weak, - } - - let one_ref = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - OneRef { inner: inner.clone() } - }); - - assert_eq!(Rc::strong_count(&one_ref), 1); - assert_eq!(Rc::weak_count(&one_ref), 1); - - let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); - assert!(Rc::ptr_eq(&one_ref, &one_ref2)); - - assert_eq!(one_ref.inner.strong_count(), 2); - assert_eq!(one_ref.inner.weak_count(), 1); -} - -#[test] -fn test_rc_cyclic_with_two_ref() { - struct TwoRefs { - inner: Weak, - inner1: Weak, - } - - let two_refs = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - TwoRefs { inner: inner.clone(), inner1: inner.clone() } - }); - - assert_eq!(Rc::strong_count(&two_refs), 1); - assert_eq!(Rc::weak_count(&two_refs), 2); - - let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap(); - assert!(Rc::ptr_eq(&two_refs, &two_ref3)); - - let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap(); - assert!(Rc::ptr_eq(&two_refs, &two_ref2)); - - assert_eq!(Rc::strong_count(&two_refs), 3); - assert_eq!(Rc::weak_count(&two_refs), 2); -} - -#[test] -fn test_unique_rc_weak() { - let rc = UniqueRc::new(42); - let weak = UniqueRc::downgrade(&rc); - assert!(weak.upgrade().is_none()); - - let _rc = UniqueRc::into_rc(rc); - assert_eq!(*weak.upgrade().unwrap(), 42); -} - -#[test] -fn test_unique_rc_drop_weak() { - let rc = UniqueRc::new(42); - let weak = UniqueRc::downgrade(&rc); - mem::drop(weak); - - let rc = UniqueRc::into_rc(rc); - assert_eq!(*rc, 42); -} - -#[test] -fn test_unique_rc_drops_contents() { - let mut dropped = false; - struct DropMe<'a>(&'a mut bool); - impl Drop for DropMe<'_> { - fn drop(&mut self) { - *self.0 = true; - } - } - { - let rc = UniqueRc::new(DropMe(&mut dropped)); - drop(rc); - } - assert!(dropped); -} - -/// Exercise the non-default allocator usage. -#[test] -fn test_unique_rc_with_alloc_drops_contents() { - let mut dropped = false; - struct DropMe<'a>(&'a mut bool); - impl Drop for DropMe<'_> { - fn drop(&mut self) { - *self.0 = true; - } - } - { - let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System); - drop(rc); - } - assert!(dropped); -} - -#[test] -fn test_unique_rc_weak_clone_holding_ref() { - let mut v = UniqueRc::new(0u8); - let w = UniqueRc::downgrade(&v); - let r = &mut *v; - let _ = w.clone(); // touch weak count - *r = 123; -} - -#[test] -fn test_unique_rc_unsizing_coercion() { - let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]); - assert_eq!(rc.len(), 3); - rc[0] = 123; - let rc: Rc<[u8]> = UniqueRc::into_rc(rc); - assert_eq!(*rc, [123, 0, 0]); -} diff --git a/library/alloctests/tests/rc.rs b/library/alloctests/tests/rc.rs index 451765d724283..fc3189e7cc413 100644 --- a/library/alloctests/tests/rc.rs +++ b/library/alloctests/tests/rc.rs @@ -2,7 +2,7 @@ use std::any::Any; use std::cell::{Cell, RefCell}; use std::iter::TrustedLen; use std::mem; -use std::rc::{Rc, Weak}; +use std::rc::{Rc, UniqueRc, Weak}; #[test] fn uninhabited() { @@ -258,3 +258,649 @@ mod pin_coerce_unsized { arg } } + +#[test] +fn test_clone() { + let x = Rc::new(RefCell::new(5)); + let y = x.clone(); + *x.borrow_mut() = 20; + assert_eq!(*y.borrow(), 20); +} + +#[test] +fn test_simple() { + let x = Rc::new(5); + assert_eq!(*x, 5); +} + +#[test] +fn test_simple_clone() { + let x = Rc::new(5); + let y = x.clone(); + assert_eq!(*x, 5); + assert_eq!(*y, 5); +} + +#[test] +fn test_destructor() { + let x: Rc> = Rc::new(Box::new(5)); + assert_eq!(**x, 5); +} + +#[test] +fn test_live() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: RefCell>>, + } + + let a = Rc::new(Cycle { x: RefCell::new(None) }); + let b = Rc::downgrade(&a.clone()); + *a.x.borrow_mut() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn test_strong_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Rc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 1); + drop(w); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Rc::strong_count(&a) == 2); + assert!(Rc::weak_count(&a) == 0); + drop(c); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::::new()), 0); + assert_eq!(Weak::strong_count(&Weak::::new()), 0); + + let a = Rc::new(0); + let w = Rc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 0); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Rc::new(3); + assert_eq!(Rc::try_unwrap(x), Ok(3)); + let x = Rc::new(4); + let _y = x.clone(); + assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_inner() { + let x = Rc::new(3); + assert_eq!(Rc::into_inner(x), Some(3)); + + let x = Rc::new(4); + let y = Rc::clone(&x); + assert_eq!(Rc::into_inner(x), None); + assert_eq!(Rc::into_inner(y), Some(4)); + + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::into_inner(x), Some(5)); +} + +#[test] +fn into_from_raw() { + let x = Rc::new(Box::new("hello")); + let y = x.clone(); + + let x_ptr = Rc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Rc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let rc: Rc = Rc::from("foo"); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(rc, rc2); + + let rc: Rc = Rc::new(123); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(rc2.to_string(), "123"); +} + +#[test] +fn into_from_weak_raw() { + let x = Rc::new(Box::new("hello")); + let y = Rc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Rc = Rc::from("foo"); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Rc = Rc::new(123); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + +#[test] +fn get_mut() { + let mut x = Rc::new(3); + *Rc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Rc::get_mut(&mut x).is_none()); + drop(y); + assert!(Rc::get_mut(&mut x).is_some()); + let _w = Rc::downgrade(&x); + assert!(Rc::get_mut(&mut x).is_none()); +} + +#[test] +fn test_cowrc_clone_make_unique() { + let mut cow0 = Rc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Rc::make_mut(&mut cow0)); + assert!(75 == *Rc::make_mut(&mut cow1)); + assert!(75 == *Rc::make_mut(&mut cow2)); + + *Rc::make_mut(&mut cow0) += 1; + *Rc::make_mut(&mut cow1) += 2; + *Rc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowrc_clone_unique2() { + let mut cow0 = Rc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowrc_clone_weak() { + let mut cow0 = Rc::new(75); + let cow1_weak = Rc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +/// This is similar to the doc-test for `Rc::make_mut()`, but on an unsized type (slice). +#[test] +fn test_cowrc_unsized() { + use std::rc::Rc; + + let mut data: Rc<[i32]> = Rc::new([10, 20, 30]); + + Rc::make_mut(&mut data)[0] += 1; // Won't clone anything + let mut other_data = Rc::clone(&data); // Won't clone inner data + Rc::make_mut(&mut data)[1] += 1; // Clones inner data + Rc::make_mut(&mut data)[2] += 1; // Won't clone anything + Rc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything + + // Now `data` and `other_data` point to different allocations. + assert_eq!(*data, [11, 21, 31]); + assert_eq!(*other_data, [110, 20, 30]); +} + +#[test] +fn test_show() { + let foo = Rc::new(75); + assert_eq!(format!("{foo:?}"), "75"); +} + +#[test] +fn test_unsized() { + let foo: Rc<[i32]> = Rc::new([1, 2, 3]); + assert_eq!(foo, foo.clone()); +} + +#[test] +fn test_maybe_thin_unsized() { + // If/when custom thin DSTs exist, this test should be updated to use one + use std::ffi::CStr; + + let x: Rc = Rc::from(c"swordfish"); + assert_eq!(format!("{x:?}"), "\"swordfish\""); + let y: Weak = Rc::downgrade(&x); + drop(x); + + // At this point, the weak points to a dropped DST + assert!(y.upgrade().is_none()); + // But we still need to be able to get the alloc layout to drop. + // CStr has no drop glue, but custom DSTs might, and need to work. + drop(y); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_rc = Rc::from(foo); + assert!(123 == *foo_rc); +} + +#[test] +fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Rc::new(5); + let same_five = five.clone(); + let other_five = Rc::new(5); + + assert!(Rc::ptr_eq(&five, &same_five)); + assert!(!Rc::ptr_eq(&five, &other_five)); +} + +#[test] +fn test_from_str() { + let r: Rc = Rc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Rc<[X]> = Rc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = + &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; + + // Should panic, but not cause memory corruption + let _r: Rc<[Fail]> = Rc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box = Box::new(123); + let r: Rc = Rc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + assert_eq!((&&&s).as_str(), "foo"); + + let r: Rc = Rc::from(s); + assert_eq!((&r).as_str(), "foo"); + assert_eq!(r.as_str(), "foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box = Box::new(123); + let r: Rc = Rc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box = Box::new(()); + let r: Rc = Rc::from(b); + + assert_eq!(format!("{r:?}"), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Rc = Rc::new(i32::MAX); + let r2: Rc = Rc::new("abc"); + + assert!(r1.clone().downcast::().is_err()); + + let r1i32 = r1.downcast::(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX)); + + assert!(r2.clone().downcast::().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Rc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} + +#[test] +fn test_rc_cyclic_with_zero_refs() { + struct ZeroRefs { + inner: Weak, + } + + let zero_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + ZeroRefs { inner: Weak::new() } + }); + + assert_eq!(Rc::strong_count(&zero_refs), 1); + assert_eq!(Rc::weak_count(&zero_refs), 0); + assert_eq!(zero_refs.inner.strong_count(), 0); + assert_eq!(zero_refs.inner.weak_count(), 0); +} + +#[test] +fn test_rc_cyclic_with_one_ref() { + struct OneRef { + inner: Weak, + } + + let one_ref = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + OneRef { inner: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&one_ref), 1); + assert_eq!(Rc::weak_count(&one_ref), 1); + + let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); + assert!(Rc::ptr_eq(&one_ref, &one_ref2)); + + assert_eq!(one_ref.inner.strong_count(), 2); + assert_eq!(one_ref.inner.weak_count(), 1); +} + +#[test] +fn test_rc_cyclic_with_two_ref() { + struct TwoRefs { + inner: Weak, + inner1: Weak, + } + + let two_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + TwoRefs { inner: inner.clone(), inner1: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&two_refs), 1); + assert_eq!(Rc::weak_count(&two_refs), 2); + + let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref3)); + + let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref2)); + + assert_eq!(Rc::strong_count(&two_refs), 3); + assert_eq!(Rc::weak_count(&two_refs), 2); +} + +#[test] +fn test_unique_rc_weak() { + let rc = UniqueRc::new(42); + let weak = UniqueRc::downgrade(&rc); + assert!(weak.upgrade().is_none()); + + let _rc = UniqueRc::into_rc(rc); + assert_eq!(*weak.upgrade().unwrap(), 42); +} + +#[test] +fn test_unique_rc_drop_weak() { + let rc = UniqueRc::new(42); + let weak = UniqueRc::downgrade(&rc); + mem::drop(weak); + + let rc = UniqueRc::into_rc(rc); + assert_eq!(*rc, 42); +} + +#[test] +fn test_unique_rc_drops_contents() { + let mut dropped = false; + struct DropMe<'a>(&'a mut bool); + impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } + } + { + let rc = UniqueRc::new(DropMe(&mut dropped)); + drop(rc); + } + assert!(dropped); +} + +/// Exercise the non-default allocator usage. +#[test] +fn test_unique_rc_with_alloc_drops_contents() { + let mut dropped = false; + struct DropMe<'a>(&'a mut bool); + impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } + } + { + let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System); + drop(rc); + } + assert!(dropped); +} + +#[test] +fn test_unique_rc_weak_clone_holding_ref() { + let mut v = UniqueRc::new(0u8); + let w = UniqueRc::downgrade(&v); + let r = &mut *v; + let _ = w.clone(); // touch weak count + *r = 123; +} + +#[test] +fn test_unique_rc_unsizing_coercion() { + let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]); + assert_eq!(rc.len(), 3); + rc[0] = 123; + let rc: Rc<[u8]> = UniqueRc::into_rc(rc); + assert_eq!(*rc, [123, 0, 0]); +} From 8c9fee037b23c1d8659c68b9aee81d9168d97fe8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:09:45 +0000 Subject: [PATCH 13/20] Move last remaining Rc test to alloctests --- library/alloc/src/{rc/mod.rs => rc.rs} | 3 --- library/alloc/src/rc/tests.rs | 15 --------------- library/alloctests/tests/rc.rs | 18 ++++++++++++++++++ 3 files changed, 18 insertions(+), 18 deletions(-) rename library/alloc/src/{rc/mod.rs => rc.rs} (99%) delete mode 100644 library/alloc/src/rc/tests.rs diff --git a/library/alloc/src/rc/mod.rs b/library/alloc/src/rc.rs similarity index 99% rename from library/alloc/src/rc/mod.rs rename to library/alloc/src/rc.rs index 09206c2f8b290..2a4d4f264444c 100644 --- a/library/alloc/src/rc/mod.rs +++ b/library/alloc/src/rc.rs @@ -276,9 +276,6 @@ use crate::string::String; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; -#[cfg(test)] -mod tests; - // This is repr(C) to future-proof against possible field-reordering, which // would interfere with otherwise safe [into|from]_raw() of transmutable // inner types. diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs deleted file mode 100644 index 35ff6b7d570d0..0000000000000 --- a/library/alloc/src/rc/tests.rs +++ /dev/null @@ -1,15 +0,0 @@ -use super::*; - -#[test] -fn is_unique() { - let x = Rc::new(3); - assert!(Rc::is_unique(&x)); - let y = x.clone(); - assert!(!Rc::is_unique(&x)); - drop(y); - assert!(Rc::is_unique(&x)); - let w = Rc::downgrade(&x); - assert!(!Rc::is_unique(&x)); - drop(w); - assert!(Rc::is_unique(&x)); -} diff --git a/library/alloctests/tests/rc.rs b/library/alloctests/tests/rc.rs index fc3189e7cc413..e967b3eebd13e 100644 --- a/library/alloctests/tests/rc.rs +++ b/library/alloctests/tests/rc.rs @@ -315,6 +315,24 @@ fn weak_self_cyclic() { // hopefully we don't double-free (or leak)... } +#[test] +fn is_unique() { + fn is_unique(this: &Rc) -> bool { + Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 + } + + let x = Rc::new(3); + assert!(is_unique(&x)); + let y = x.clone(); + assert!(!is_unique(&x)); + drop(y); + assert!(is_unique(&x)); + let w = Rc::downgrade(&x); + assert!(!is_unique(&x)); + drop(w); + assert!(is_unique(&x)); +} + #[test] fn test_strong_count() { let a = Rc::new(0); From 69ac9fc799a6fd410e65e711996af7b193e2990b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:46:33 +0000 Subject: [PATCH 14/20] Fully test the alloc crate through alloctests For the tests that make use of internal implementation details, we include the module to test using #[path] in alloctests now. --- ...le-f16-and-f128-in-compiler-builtins.patch | 6 +- library/Cargo.lock | 2 - library/alloc/Cargo.toml | 8 +- library/alloc/src/alloc.rs | 18 +- library/alloc/src/borrow.rs | 6 +- library/alloc/src/bstr.rs | 20 -- .../alloc/src/collections/binary_heap/mod.rs | 5 +- library/alloc/src/collections/mod.rs | 21 ++ .../alloc/src/collections/vec_deque/mod.rs | 1 + .../src/collections/vec_deque/spec_extend.rs | 2 + .../collections/vec_deque/spec_from_iter.rs | 1 + library/alloc/src/ffi/c_str.rs | 16 +- library/alloc/src/lib.rs | 39 +--- library/alloc/src/macros.rs | 23 +-- library/alloc/src/raw_vec/mod.rs | 1 + library/alloc/src/rc.rs | 7 +- library/alloc/src/slice.rs | 182 +++++++----------- library/alloc/src/str.rs | 3 - library/alloc/src/string.rs | 30 +-- library/alloc/src/sync.rs | 4 +- library/alloc/src/vec/into_iter.rs | 5 - library/alloc/src/vec/mod.rs | 47 +---- library/alloctests/Cargo.toml | 5 +- library/alloctests/lib.rs | 91 ++++++++- .../src => alloctests}/testing/crash_test.rs | 0 .../{alloc/src => alloctests}/testing/mod.rs | 0 .../src => alloctests}/testing/ord_chaos.rs | 0 .../{alloc/src => alloctests}/testing/rng.rs | 0 28 files changed, 232 insertions(+), 311 deletions(-) rename library/{alloc/src => alloctests}/testing/crash_test.rs (100%) rename library/{alloc/src => alloctests}/testing/mod.rs (100%) rename library/{alloc/src => alloctests}/testing/ord_chaos.rs (100%) rename library/{alloc/src => alloctests}/testing/rng.rs (100%) diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index e3a9512dda9c6..f430d16d7c181 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -12,15 +12,15 @@ index 7165c3e48af..968552ad435 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -11,7 +11,7 @@ test = { path = "../test" } - edition = "2021" + bench = false [dependencies] core = { path = "../core" } -compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } - [dev-dependencies] - rand = { version = "0.8.5", default-features = false, features = ["alloc"] } + [features] + compiler-builtins-mem = ['compiler_builtins/mem'] -- 2.34.1 diff --git a/library/Cargo.lock b/library/Cargo.lock index 7d83b93489ed6..c96ace2e78331 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -30,8 +30,6 @@ version = "0.0.0" dependencies = [ "compiler_builtins", "core", - "rand", - "rand_xorshift", ] [[package]] diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index b9d5bb53d918e..c7568f67be5ed 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -8,14 +8,14 @@ autotests = false autobenches = false edition = "2021" +[lib] +test = false +bench = false + [dependencies] core = { path = "../core" } compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } -[dev-dependencies] -rand = { version = "0.8.5", default-features = false, features = ["alloc"] } -rand_xorshift = "0.3.0" - [features] compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e686a02f29b0c..8bb616827f66d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -5,9 +5,7 @@ #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use core::alloc::*; -#[cfg(not(test))] use core::hint; -#[cfg(not(test))] use core::ptr::{self, NonNull}; unsafe extern "Rust" { @@ -44,14 +42,10 @@ unsafe extern "Rust" { /// accessed through the [free functions in `alloc`](self#functions). #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] -#[cfg(not(test))] // the compiler needs to know when a Box uses the global allocator vs a custom one #[lang = "global_alloc_ty"] pub struct Global; -#[cfg(test)] -pub use std::alloc::Global; - /// Allocates memory with the global allocator. /// /// This function forwards calls to the [`GlobalAlloc::alloc`] method @@ -180,7 +174,6 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { } } -#[cfg(not(test))] impl Global { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -246,7 +239,6 @@ impl Global { } #[unstable(feature = "allocator_api", issue = "32838")] -#[cfg(not(test))] unsafe impl Allocator for Global { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -340,7 +332,7 @@ unsafe impl Allocator for Global { } /// The allocator for `Box`. -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[lang = "exchange_malloc"] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -389,7 +381,7 @@ unsafe extern "Rust" { /// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[cold] #[optimize(size)] pub const fn handle_alloc_error(layout: Layout) -> ! { @@ -413,11 +405,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { ct_error(layout) } -// For alloc test `std::alloc::handle_alloc_error` can be used directly. -#[cfg(all(not(no_global_oom_handling), test))] -pub use std::alloc::handle_alloc_error; - -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[doc(hidden)] #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index dbfd2e74abee6..11ec8b194c7fa 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -32,7 +32,7 @@ where /// implementing the `Clone` trait. But `Clone` works only for going from `&T` /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data /// from any borrow of a given type. -#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")] +#[rustc_diagnostic_item = "ToOwned"] #[stable(feature = "rust1", since = "1.0.0")] pub trait ToOwned { /// The resulting type after obtaining ownership. @@ -54,7 +54,7 @@ pub trait ToOwned { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "cloning is often expensive and is not expected to have side effects"] - #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")] + #[rustc_diagnostic_item = "to_owned_method"] fn to_owned(&self) -> Self::Owned; /// Uses borrowed data to replace owned data, usually by cloning. @@ -175,7 +175,7 @@ where /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")] +#[rustc_diagnostic_item = "Cow"] pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned, diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index 61e61019b508c..338c7ac7f8876 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -12,13 +12,10 @@ use core::ops::{ Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use core::str::FromStr; use core::{fmt, hash}; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use crate::borrow::{Cow, ToOwned}; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use crate::boxed::Box; #[cfg(not(no_rc))] use crate::rc::Rc; @@ -181,7 +178,6 @@ impl Default for ByteString { // Omitted due to inference failures // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a, const N: usize> From<&'a [u8; N]> for ByteString { // #[inline] @@ -190,7 +186,6 @@ impl Default for ByteString { // } // } // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl From<[u8; N]> for ByteString { // #[inline] @@ -199,7 +194,6 @@ impl Default for ByteString { // } // } // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a> From<&'a [u8]> for ByteString { // #[inline] @@ -226,7 +220,6 @@ impl From for Vec { // Omitted due to inference failures // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a> From<&'a str> for ByteString { // #[inline] @@ -243,7 +236,6 @@ impl From for Vec { // } // } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteStr> for ByteString { #[inline] @@ -252,7 +244,6 @@ impl<'a> From<&'a ByteStr> for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From for Cow<'a, ByteStr> { #[inline] @@ -261,7 +252,6 @@ impl<'a> From for Cow<'a, ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteString> for Cow<'a, ByteStr> { #[inline] @@ -330,7 +320,6 @@ impl FromIterator for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl FromStr for ByteString { type Err = core::convert::Infallible; @@ -488,7 +477,6 @@ impl PartialEq for ByteString { macro_rules! impl_partial_eq_ord_cow { ($lhs:ty, $rhs:ty) => { - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialEq<$rhs> for $lhs { @@ -499,7 +487,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialEq<$lhs> for $rhs { @@ -510,7 +497,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialOrd<$rhs> for $lhs { @@ -521,7 +507,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialOrd<$lhs> for $rhs { @@ -572,7 +557,6 @@ impl PartialOrd for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl ToOwned for ByteStr { type Owned = ByteString; @@ -605,7 +589,6 @@ impl<'a> TryFrom<&'a ByteString> for &'a str { // Additional impls for `ByteStr` that require types from `alloc`: -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl Clone for Box { #[inline] @@ -614,7 +597,6 @@ impl Clone for Box { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { #[inline] @@ -623,7 +605,6 @@ impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl From> for Box { #[inline] @@ -633,7 +614,6 @@ impl From> for Box { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl From> for Box<[u8]> { #[inline] diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 965fd63a52981..b764b8fa5d977 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -153,7 +153,9 @@ use core::{fmt, ptr}; use crate::alloc::Global; use crate::collections::TryReserveError; use crate::slice; -use crate::vec::{self, AsVecIntoIter, Vec}; +#[cfg(not(test))] +use crate::vec::AsVecIntoIter; +use crate::vec::{self, Vec}; /// A priority queue implemented with a binary heap. /// @@ -1600,6 +1602,7 @@ unsafe impl InPlaceIterable for IntoIter { const MERGE_BY: Option> = NonZero::new(1); } +#[cfg(not(test))] unsafe impl AsVecIntoIter for IntoIter { type Item = I; diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 020cf4d736510..1414f797e8a45 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -24,41 +24,54 @@ pub mod btree_map { pub mod btree_set { //! An ordered set based on a B-Tree. #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(test))] pub use super::btree::set::*; } +#[cfg(not(test))] use core::fmt::Display; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use binary_heap::BinaryHeap; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use btree_map::BTreeMap; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use btree_set::BTreeSet; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use linked_list::LinkedList; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use vec_deque::VecDeque; +#[cfg(not(test))] use crate::alloc::{Layout, LayoutError}; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] pub struct TryReserveError { kind: TryReserveErrorKind, } +#[cfg(test)] +pub use realalloc::collections::TryReserveError; + +#[cfg(not(test))] impl TryReserveError { /// Details about the allocation that caused the error #[inline] @@ -80,6 +93,7 @@ impl TryReserveError { reason = "Uncertain how much info should be exposed", issue = "48043" )] +#[cfg(not(test))] pub enum TryReserveErrorKind { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). @@ -103,11 +117,15 @@ pub enum TryReserveErrorKind { }, } +#[cfg(test)] +pub use realalloc::collections::TryReserveErrorKind; + #[unstable( feature = "try_reserve_kind", reason = "Uncertain how much info should be exposed", issue = "48043" )] +#[cfg(not(test))] impl From for TryReserveError { #[inline] fn from(kind: TryReserveErrorKind) -> Self { @@ -116,6 +134,7 @@ impl From for TryReserveError { } #[unstable(feature = "try_reserve_kind", reason = "new API", issue = "48043")] +#[cfg(not(test))] impl From for TryReserveErrorKind { /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`]. #[inline] @@ -125,6 +144,7 @@ impl From for TryReserveErrorKind { } #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] impl Display for TryReserveError { fn fmt( &self, @@ -152,4 +172,5 @@ trait SpecExtend { } #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] impl core::error::Error for TryReserveError {} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 299c8b8679e3d..f8844e2d3a5cb 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -645,6 +645,7 @@ impl VecDeque { /// initialized rather than only supporting `0..len`. Requires that /// `initialized.start` ≤ `initialized.end` ≤ `capacity`. #[inline] + #[cfg(not(test))] pub(crate) unsafe fn from_contiguous_raw_parts_in( ptr: *mut T, initialized: Range, diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index d246385ca8419..7c7072c4c3a1b 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -3,6 +3,7 @@ use core::slice; use super::VecDeque; use crate::alloc::Allocator; +#[cfg(not(test))] use crate::vec; // Specialization trait used for VecDeque::extend @@ -78,6 +79,7 @@ where } } +#[cfg(not(test))] impl SpecExtend> for VecDeque { #[track_caller] fn spec_extend(&mut self, mut iterator: vec::IntoIter) { diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 1efe84d6d7d7d..c80a30c2103dd 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -19,6 +19,7 @@ where } } +#[cfg(not(test))] impl SpecFromIter> for VecDeque { #[inline] fn spec_from_iter(iterator: crate::vec::IntoIter) -> Self { diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index fd93045a5ac4d..f6743c6571095 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -10,7 +10,6 @@ use core::{fmt, mem, ops, ptr, slice}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::Rc; -use crate::slice::hack::into_vec; use crate::string::String; #[cfg(target_has_atomic = "ptr")] use crate::sync::Arc; @@ -103,7 +102,7 @@ use crate::vec::Vec; /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] -#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")] +#[rustc_diagnostic_item = "cstring_type"] #[stable(feature = "alloc_c_string", since = "1.64.0")] pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. @@ -491,7 +490,7 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes(self) -> Vec { - let mut vec = into_vec(self.into_inner()); + let mut vec = self.into_inner().into_vec(); let _nul = vec.pop(); debug_assert_eq!(_nul, Some(0u8)); vec @@ -512,7 +511,7 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec { - into_vec(self.into_inner()) + self.into_inner().into_vec() } /// Returns the contents of this `CString` as a slice of bytes. @@ -573,7 +572,7 @@ impl CString { #[inline] #[must_use] #[stable(feature = "as_c_str", since = "1.20.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")] + #[rustc_diagnostic_item = "cstring_as_c_str"] pub fn as_c_str(&self) -> &CStr { &*self } @@ -755,7 +754,6 @@ impl<'a> From> for CString { } } -#[cfg(not(test))] #[stable(feature = "box_from_c_str", since = "1.17.0")] impl From<&CStr> for Box { /// Converts a `&CStr` into a `Box`, @@ -766,7 +764,6 @@ impl From<&CStr> for Box { } } -#[cfg(not(test))] #[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Box { /// Converts a `&mut CStr` into a `Box`, @@ -845,7 +842,6 @@ impl TryFrom for String { } } -#[cfg(not(test))] #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box { #[inline] @@ -971,7 +967,6 @@ impl Default for Rc { } } -#[cfg(not(test))] #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box { fn default() -> Box { @@ -1080,7 +1075,7 @@ impl ToOwned for CStr { } fn clone_into(&self, target: &mut CString) { - let mut b = into_vec(mem::take(&mut target.inner)); + let mut b = mem::take(&mut target.inner).into_vec(); self.to_bytes_with_nul().clone_into(&mut b); target.inner = b.into_boxed_slice(); } @@ -1113,7 +1108,6 @@ impl AsRef for CString { } } -#[cfg(not(test))] impl CStr { /// Converts a `CStr` into a [Cow]<[str]>. /// diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1bb0f76106472..92720bad70a77 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -92,7 +92,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(test, feature(str_as_str))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] @@ -160,13 +159,11 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(test), feature(coroutine_trait))] -#![cfg_attr(test, feature(panic_update_hook))] -#![cfg_attr(test, feature(test))] #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] +#![feature(coroutine_trait)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(fundamental)] @@ -199,15 +196,6 @@ // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] -// Allow testing this library -#[cfg(test)] -#[macro_use] -extern crate std; -#[cfg(test)] -extern crate test; -#[cfg(test)] -mod testing; - // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] mod macros; @@ -215,7 +203,6 @@ mod macros; mod raw_vec; // Heaps provided for low-level allocation strategies - pub mod alloc; // Primitive types using the heaps above @@ -223,13 +210,8 @@ pub mod alloc; // Need to conditionally define the mod from `boxed.rs` to avoid // duplicating the lang-items when building in test cfg; but also need // to allow code to have `use boxed::Box;` declarations. -#[cfg(not(test))] -pub mod boxed; -#[cfg(test)] -mod boxed { - pub(crate) use std::boxed::Box; -} pub mod borrow; +pub mod boxed; #[unstable(feature = "bstr", issue = "134915")] pub mod bstr; pub mod collections; @@ -253,20 +235,3 @@ pub mod __export { pub use core::format_args; pub use core::hint::must_use; } - -#[cfg(test)] -#[allow(dead_code)] // Not used in all configurations -pub(crate) mod test_helpers { - /// Copied from `std::test_helpers::test_rng`, since these tests rely on the - /// seed not being the same for every RNG invocation too. - pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { - use std::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::hash::RandomState::new().build_hasher(); - std::panic::Location::caller().hash(&mut hasher); - let hc64 = hasher.finish(); - let seed_vec = - hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); - let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); - rand::SeedableRng::from_seed(seed) - } -} diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index c000fd6f4efa7..214192b8c9a9b 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -34,7 +34,7 @@ /// be mindful of side effects. /// /// [`Vec`]: crate::vec::Vec -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "vec_macro"] @@ -55,25 +55,6 @@ macro_rules! vec { ); } -// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is -// required for this macro definition, is not available. Instead use the -// `slice::into_vec` function which is only available with cfg(test) -// NB see the slice::hack module in slice.rs for more information -#[cfg(all(not(no_global_oom_handling), test))] -#[allow(unused_macro_rules)] -macro_rules! vec { - () => ( - $crate::vec::Vec::new() - ); - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - /// Creates a `String` using interpolation of runtime expressions. /// /// The first argument `format!` receives is a format string. This must be a string @@ -120,7 +101,7 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(hint_must_use, liballoc_internals)] -#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")] +#[rustc_diagnostic_item = "format_macro"] macro_rules! format { ($($arg:tt)*) => { $crate::__export::must_use({ diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index b80d1fc788947..fda4858f9d85d 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -1,4 +1,5 @@ #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] +#![cfg_attr(test, allow(dead_code))] use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2a4d4f264444c..fe0b25f31b923 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -262,14 +262,11 @@ use core::ptr::{self, NonNull, drop_in_place}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; -#[cfg(test)] -use std::boxed::Box; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; -#[cfg(not(test))] use crate::boxed::Box; #[cfg(not(no_global_oom_handling))] use crate::string::String; @@ -306,7 +303,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { /// /// [get_mut]: Rc::get_mut #[doc(search_unbox)] -#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] +#[rustc_diagnostic_item = "Rc"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct Rc< @@ -2981,7 +2978,7 @@ impl> ToRcSlice for I { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "rc_weak", since = "1.4.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")] +#[rustc_diagnostic_item = "RcWeak"] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 1cedead7aa243..1d21045d90fa5 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -8,9 +8,6 @@ //! A few functions are provided to create a slice from a value reference //! or from a raw pointer. #![stable(feature = "rust1", since = "1.0.0")] -// Many of the usings in this module are only used in the test configuration. -// It's cleaner to just turn off the unused_imports warning than to fix them. -#![cfg_attr(test, allow(unused_imports, dead_code))] use core::borrow::{Borrow, BorrowMut}; #[cfg(not(no_global_oom_handling))] @@ -63,16 +60,6 @@ pub use core::slice::{range, try_range}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// - -// HACK(japaric) needed for the implementation of `vec!` macro during testing -// N.B., see the `hack` module in this file for more details. -#[cfg(test)] -pub use hack::into_vec; -// HACK(japaric) needed for the implementation of `Vec::clone` during testing -// N.B., see the `hack` module in this file for more details. -#[cfg(test)] -pub use hack::to_vec; - use crate::alloc::Allocator; #[cfg(not(no_global_oom_handling))] use crate::alloc::Global; @@ -81,98 +68,6 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; -// HACK(japaric): With cfg(test) `impl [T]` is not available, these three -// functions are actually methods that are in `impl [T]` but not in -// `core::slice::SliceExt` - we need to supply these functions for the -// `test_permutations` test -#[allow(unreachable_pub)] // cfg(test) pub above -pub(crate) mod hack { - use core::alloc::Allocator; - - use crate::boxed::Box; - use crate::vec::Vec; - - // We shouldn't add inline attribute to this since this is used in - // `vec!` macro mostly and causes perf regression. See #71204 for - // discussion and perf results. - #[allow(missing_docs)] - pub fn into_vec(b: Box<[T], A>) -> Vec { - unsafe { - let len = b.len(); - let (b, alloc) = Box::into_raw_with_allocator(b); - Vec::from_raw_parts_in(b as *mut T, len, len, alloc) - } - } - - #[cfg(not(no_global_oom_handling))] - #[allow(missing_docs)] - #[inline] - pub fn to_vec(s: &[T], alloc: A) -> Vec { - T::to_vec(s, alloc) - } - - #[cfg(not(no_global_oom_handling))] - pub trait ConvertVec { - fn to_vec(s: &[Self], alloc: A) -> Vec - where - Self: Sized; - } - - #[cfg(not(no_global_oom_handling))] - impl ConvertVec for T { - #[inline] - default fn to_vec(s: &[Self], alloc: A) -> Vec { - struct DropGuard<'a, T, A: Allocator> { - vec: &'a mut Vec, - num_init: usize, - } - impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { - #[inline] - fn drop(&mut self) { - // SAFETY: - // items were marked initialized in the loop below - unsafe { - self.vec.set_len(self.num_init); - } - } - } - let mut vec = Vec::with_capacity_in(s.len(), alloc); - let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; - let slots = guard.vec.spare_capacity_mut(); - // .take(slots.len()) is necessary for LLVM to remove bounds checks - // and has better codegen than zip. - for (i, b) in s.iter().enumerate().take(slots.len()) { - guard.num_init = i; - slots[i].write(b.clone()); - } - core::mem::forget(guard); - // SAFETY: - // the vec was allocated and initialized above to at least this length. - unsafe { - vec.set_len(s.len()); - } - vec - } - } - - #[cfg(not(no_global_oom_handling))] - impl ConvertVec for T { - #[inline] - fn to_vec(s: &[Self], alloc: A) -> Vec { - let mut v = Vec::with_capacity_in(s.len(), alloc); - // SAFETY: - // allocated above with the capacity of `s`, and initialize to `s.len()` in - // ptr::copy_to_non_overlapping below. - unsafe { - s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); - v.set_len(s.len()); - } - v - } - } -} - -#[cfg(not(test))] impl [T] { /// Sorts the slice, preserving initial order of equal elements. /// @@ -501,8 +396,64 @@ impl [T] { where T: Clone, { - // N.B., see the `hack` module in this file for more details. - hack::to_vec(self, alloc) + return T::to_vec(self, alloc); + + trait ConvertVec { + fn to_vec(s: &[Self], alloc: A) -> Vec + where + Self: Sized; + } + + impl ConvertVec for T { + #[inline] + default fn to_vec(s: &[Self], alloc: A) -> Vec { + struct DropGuard<'a, T, A: Allocator> { + vec: &'a mut Vec, + num_init: usize, + } + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + #[inline] + fn drop(&mut self) { + // SAFETY: + // items were marked initialized in the loop below + unsafe { + self.vec.set_len(self.num_init); + } + } + } + let mut vec = Vec::with_capacity_in(s.len(), alloc); + let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; + let slots = guard.vec.spare_capacity_mut(); + // .take(slots.len()) is necessary for LLVM to remove bounds checks + // and has better codegen than zip. + for (i, b) in s.iter().enumerate().take(slots.len()) { + guard.num_init = i; + slots[i].write(b.clone()); + } + core::mem::forget(guard); + // SAFETY: + // the vec was allocated and initialized above to at least this length. + unsafe { + vec.set_len(s.len()); + } + vec + } + } + + impl ConvertVec for T { + #[inline] + fn to_vec(s: &[Self], alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(s.len(), alloc); + // SAFETY: + // allocated above with the capacity of `s`, and initialize to `s.len()` in + // ptr::copy_to_non_overlapping below. + unsafe { + s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); + v.set_len(s.len()); + } + v + } + } } /// Converts `self` into a vector without clones or allocation. @@ -522,10 +473,13 @@ impl [T] { #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")] + #[rustc_diagnostic_item = "slice_into_vec"] pub fn into_vec(self: Box) -> Vec { - // N.B., see the `hack` module in this file for more details. - hack::into_vec(self) + unsafe { + let len = self.len(); + let (b, alloc) = Box::into_raw_with_allocator(self); + Vec::from_raw_parts_in(b as *mut T, len, len, alloc) + } } /// Creates a vector by copying a slice `n` times. @@ -666,7 +620,6 @@ impl [T] { } } -#[cfg(not(test))] impl [u8] { /// Returns a vector containing a copy of this slice where each byte /// is mapped to its ASCII upper case equivalent. @@ -883,14 +836,9 @@ impl SpecCloneIntoVec for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for [T] { type Owned = Vec; - #[cfg(not(test))] - fn to_owned(&self) -> Vec { - self.to_vec() - } - #[cfg(test)] fn to_owned(&self) -> Vec { - hack::to_vec(self, Global) + self.to_vec() } fn clone_into(&self, target: &mut Vec) { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 6fee8d3fe3346..0664f2c3cf2c1 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -219,7 +219,6 @@ impl ToOwned for str { } /// Methods for string slices. -#[cfg(not(test))] impl str { /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. /// @@ -631,7 +630,6 @@ pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { #[unstable(feature = "str_internals", issue = "none")] #[doc(hidden)] #[inline] -#[cfg(not(test))] #[cfg(not(no_global_oom_handling))] pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { // Process the input in chunks of 16 bytes to enable auto-vectorization. @@ -704,7 +702,6 @@ pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { } } #[inline] -#[cfg(not(test))] #[cfg(not(no_global_oom_handling))] #[allow(dead_code)] /// Faster implementation of string replacement for ASCII to ASCII cases. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b29f740ef0f2a..e630b2940644c 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -358,7 +358,7 @@ use crate::vec::{self, Vec}; /// [`as_str()`]: String::as_str #[derive(PartialEq, PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), lang = "String")] +#[lang = "String"] pub struct String { vec: Vec, } @@ -440,7 +440,7 @@ impl String { /// ``` #[inline] #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")] + #[rustc_diagnostic_item = "string_new"] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> String { @@ -503,17 +503,6 @@ impl String { Ok(String { vec: Vec::try_with_capacity(capacity)? }) } - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Since we don't - // require this method for testing purposes, I'll just stub it - // NB see the slice::hack module in slice.rs for more information - #[inline] - #[cfg(test)] - #[allow(missing_docs)] - pub fn from_str(_: &str) -> String { - panic!("not available with cfg(test)"); - } - /// Converts a vector of bytes to a `String`. /// /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes @@ -572,7 +561,7 @@ impl String { /// [`into_bytes`]: String::into_bytes #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")] + #[rustc_diagnostic_item = "string_from_utf8"] pub fn from_utf8(vec: Vec) -> Result { match str::from_utf8(&vec) { Ok(..) => Ok(String { vec }), @@ -1076,7 +1065,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] + #[rustc_diagnostic_item = "string_as_str"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_str(&self) -> &str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error @@ -1099,7 +1088,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] + #[rustc_diagnostic_item = "string_as_mut_str"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_mut_str(&mut self) -> &mut str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error @@ -1122,7 +1111,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("append", "push")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")] + #[rustc_diagnostic_item = "string_push_str"] pub fn push_str(&mut self, string: &str) { self.vec.extend_from_slice(string.as_bytes()) } @@ -1759,7 +1748,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "insert_str", since = "1.16.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")] + #[rustc_diagnostic_item = "string_insert_str"] pub fn insert_str(&mut self, idx: usize, string: &str) { assert!(self.is_char_boundary(idx)); @@ -2702,7 +2691,7 @@ impl FromStr for String { /// implementation for free. /// /// [`Display`]: fmt::Display -#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] +#[rustc_diagnostic_item = "ToString"] #[stable(feature = "rust1", since = "1.0.0")] pub trait ToString { /// Converts the given value to a `String`. @@ -2717,7 +2706,7 @@ pub trait ToString { /// ``` #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] + #[rustc_diagnostic_item = "to_string_method"] fn to_string(&self) -> String; } @@ -2957,7 +2946,6 @@ impl From<&String> for String { } // note: test pulls in std, which causes errors here -#[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] impl From> for String { /// Converts the given boxed `str` slice to a [`String`]. diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index dba1449347ac0..ac88ac1034d44 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -234,7 +234,7 @@ macro_rules! acquire { /// /// [rc_examples]: crate::rc#examples #[doc(search_unbox)] -#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] +#[rustc_diagnostic_item = "Arc"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct Arc< @@ -311,7 +311,7 @@ impl Arc { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "arc_weak", since = "1.4.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")] +#[rustc_diagnostic_item = "ArcWeak"] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 9a6745fdbc0a3..80da2f9abe19d 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -472,14 +472,9 @@ where #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl Clone for IntoIter { - #[cfg(not(test))] fn clone(&self) -> Self { self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() } - #[cfg(test)] - fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 55cd0569538a8..2a10642a073fa 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -392,7 +392,7 @@ mod spec_extend; /// [`MaybeUninit`]: core::mem::MaybeUninit /// [owned slice]: Box #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")] +#[rustc_diagnostic_item = "Vec"] #[rustc_insignificant_dtor] pub struct Vec { buf: RawVec, @@ -416,7 +416,7 @@ impl Vec { /// ``` #[inline] #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")] + #[rustc_diagnostic_item = "vec_new"] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { @@ -477,7 +477,7 @@ impl Vec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")] + #[rustc_diagnostic_item = "vec_with_capacity"] #[track_caller] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) @@ -1267,7 +1267,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_reserve")] + #[rustc_diagnostic_item = "vec_reserve"] pub fn reserve(&mut self, additional: usize) { self.buf.reserve(self.len, additional); } @@ -1556,7 +1556,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")] + #[rustc_diagnostic_item = "vec_as_slice"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_slice(&self) -> &[T] { // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size @@ -1588,7 +1588,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")] + #[rustc_diagnostic_item = "vec_as_mut_slice"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of @@ -2499,7 +2499,7 @@ impl Vec { /// Takes *O*(1) time. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")] + #[rustc_diagnostic_item = "vec_pop"] pub fn pop(&mut self) -> Option { if self.len == 0 { None @@ -2700,7 +2700,7 @@ impl Vec { /// assert!(!v.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")] + #[rustc_diagnostic_item = "vec_is_empty"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn is_empty(&self) -> bool { self.len() == 0 @@ -3181,7 +3181,7 @@ impl Vec { #[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")] +#[rustc_diagnostic_item = "vec_from_elem"] #[track_caller] pub fn from_elem(elem: T, n: usize) -> Vec { ::from_elem(elem, n, Global) @@ -3281,23 +3281,12 @@ unsafe impl ops::DerefPure for Vec {} #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Vec { - #[cfg(not(test))] #[track_caller] fn clone(&self) -> Self { let alloc = self.allocator().clone(); <[T]>::to_vec_in(&**self, alloc) } - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn clone(&self) -> Self { - let alloc = self.allocator().clone(); - crate::slice::to_vec(&**self, alloc) - } - /// Overwrites the contents of `self` with a clone of the contents of `source`. /// /// This method is preferred over simply assigning `source.clone()` to `self`, @@ -3844,15 +3833,10 @@ impl From<&[T]> for Vec { /// ``` /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: &[T]) -> Vec { s.to_vec() } - #[cfg(test)] - fn from(s: &[T]) -> Vec { - crate::slice::to_vec(s, Global) - } } #[cfg(not(no_global_oom_handling))] @@ -3865,15 +3849,10 @@ impl From<&mut [T]> for Vec { /// ``` /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: &mut [T]) -> Vec { s.to_vec() } - #[cfg(test)] - fn from(s: &mut [T]) -> Vec { - crate::slice::to_vec(s, Global) - } } #[cfg(not(no_global_oom_handling))] @@ -3918,16 +3897,10 @@ impl From<[T; N]> for Vec { /// ``` /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: [T; N]) -> Vec { <[T]>::into_vec(Box::new(s)) } - - #[cfg(test)] - fn from(s: [T; N]) -> Vec { - crate::slice::into_vec(Box::new(s)) - } } #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] @@ -3956,7 +3929,6 @@ where } // note: test pulls in std, which causes errors here -#[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] impl From> for Vec { /// Converts a boxed slice into a vector by transferring ownership of @@ -3975,7 +3947,6 @@ impl From> for Vec { // note: test pulls in std, which causes errors here #[cfg(not(no_global_oom_handling))] -#[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] impl From> for Box<[T], A> { /// Converts a vector into a boxed slice. diff --git a/library/alloctests/Cargo.toml b/library/alloctests/Cargo.toml index 93c7c786e881b..f4ac6ffaaaaf7 100644 --- a/library/alloctests/Cargo.toml +++ b/library/alloctests/Cargo.toml @@ -10,8 +10,9 @@ edition = "2021" [lib] path = "lib.rs" -test = false -bench = false +test = true +bench = true +doc = false [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index b49208cd4eb3a..0b5aa2c575d9a 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -1 +1,90 @@ -// Intentionally left empty. +#![cfg(test)] +#![allow(unused_attributes)] +#![unstable(feature = "alloctests", issue = "none")] +#![no_std] +// Lints: +#![deny(unsafe_op_in_unsafe_fn)] +#![warn(deprecated_in_future)] +#![warn(missing_debug_implementations)] +#![allow(explicit_outlives_requirements)] +#![allow(internal_features)] +#![allow(rustdoc::redundant_explicit_links)] +#![warn(rustdoc::unescaped_backticks)] +#![deny(ffi_unwind_calls)] +// +// Library features: +// tidy-alphabetical-start +#![feature(alloc_layout_extra)] +#![feature(allocator_api)] +#![feature(array_into_iter_constructors)] +#![feature(assert_matches)] +#![feature(core_intrinsics)] +#![feature(exact_size_is_empty)] +#![feature(extend_one)] +#![feature(extend_one_unchecked)] +#![feature(hasher_prefixfree_extras)] +#![feature(inplace_iteration)] +#![feature(iter_advance_by)] +#![feature(iter_next_chunk)] +#![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_uninit_array_transpose)] +#![feature(ptr_internals)] +#![feature(sized_type_properties)] +#![feature(slice_iter_mut_as_mut_slice)] +#![feature(slice_ptr_get)] +#![feature(slice_range)] +#![feature(std_internals)] +#![feature(temporary_niche_types)] +#![feature(trusted_fused)] +#![feature(trusted_len)] +#![feature(trusted_random_access)] +#![feature(try_reserve_kind)] +#![feature(try_trait_v2)] +// tidy-alphabetical-end +// +// Language features: +// tidy-alphabetical-start +#![feature(cfg_sanitize)] +#![feature(dropck_eyepatch)] +#![feature(lang_items)] +#![feature(min_specialization)] +#![feature(negative_impls)] +#![feature(never_type)] +#![feature(optimize_attribute)] +#![feature(rustc_allow_const_fn_unstable)] +#![feature(rustc_attrs)] +#![feature(staged_api)] +#![feature(test)] +#![rustc_preserve_ub_checks] +// tidy-alphabetical-end + +// Allow testing this library +extern crate alloc as realalloc; +#[macro_use] +extern crate std; +#[cfg(test)] +extern crate test; +mod testing; +use realalloc::*; + +#[path = "../alloc/src/collections/mod.rs"] +mod collections; + +#[path = "../alloc/src/raw_vec/mod.rs"] +mod raw_vec; + +#[allow(dead_code)] // Not used in all configurations +pub(crate) mod test_helpers { + /// Copied from `std::test_helpers::test_rng`, since these tests rely on the + /// seed not being the same for every RNG invocation too. + pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { + use std::hash::{BuildHasher, Hash, Hasher}; + let mut hasher = std::hash::RandomState::new().build_hasher(); + std::panic::Location::caller().hash(&mut hasher); + let hc64 = hasher.finish(); + let seed_vec = + hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); + let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); + rand::SeedableRng::from_seed(seed) + } +} diff --git a/library/alloc/src/testing/crash_test.rs b/library/alloctests/testing/crash_test.rs similarity index 100% rename from library/alloc/src/testing/crash_test.rs rename to library/alloctests/testing/crash_test.rs diff --git a/library/alloc/src/testing/mod.rs b/library/alloctests/testing/mod.rs similarity index 100% rename from library/alloc/src/testing/mod.rs rename to library/alloctests/testing/mod.rs diff --git a/library/alloc/src/testing/ord_chaos.rs b/library/alloctests/testing/ord_chaos.rs similarity index 100% rename from library/alloc/src/testing/ord_chaos.rs rename to library/alloctests/testing/ord_chaos.rs diff --git a/library/alloc/src/testing/rng.rs b/library/alloctests/testing/rng.rs similarity index 100% rename from library/alloc/src/testing/rng.rs rename to library/alloctests/testing/rng.rs From 172667017f34f25cbed348be9c1e09083d58df41 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:38:07 +0000 Subject: [PATCH 15/20] Add comments --- library/alloc/src/collections/mod.rs | 3 +++ library/alloc/src/raw_vec/mod.rs | 3 +++ library/alloctests/lib.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 1414f797e8a45..fac4d1a65abcb 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -1,5 +1,8 @@ //! Collection types. +// Note: This module is also included in the alloctests crate using #[path] to +// run the tests. See the comment there for an explanation why this is the case. + #![stable(feature = "rust1", since = "1.0.0")] #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index fda4858f9d85d..9128057512b3c 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -1,6 +1,9 @@ #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] #![cfg_attr(test, allow(dead_code))] +// Note: This module is also included in the alloctests crate using #[path] to +// run the tests. See the comment there for an explanation why this is the case. + use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ptr::{self, NonNull, Unique}; diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 0b5aa2c575d9a..6ce8a6d9ca174 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -67,6 +67,9 @@ extern crate test; mod testing; use realalloc::*; +// We are directly including collections and raw_vec here as both use non-public +// methods and fields in tests and as such need to have the types to test in the +// same crate as the tests themself. #[path = "../alloc/src/collections/mod.rs"] mod collections; From 2f27236745fab41c73450cdb31cdf9d0db502dda Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Thu, 13 Feb 2025 09:13:33 -0700 Subject: [PATCH 16/20] alloc boxed: docs: use MaybeUninit::write instead of as_mut_ptr In the deferred initialization pattern, the docs were needlessly going through as_mut_ptr().write() to initialize, which is unnecessary use of a pointer, needs to be inside an unsafe block, and may weaken alias analysis. --- library/alloc/src/boxed.rs | 128 +++++++++++++------------------------ 1 file changed, 44 insertions(+), 84 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 8b38e6fc259af..60e46dc7a09cf 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -280,13 +280,9 @@ impl Box { /// /// ``` /// let mut five = Box::::new_uninit(); - /// - /// let five = unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; + /// // Deferred initialization: + /// five.write(5); + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -367,13 +363,9 @@ impl Box { /// #![feature(allocator_api)] /// /// let mut five = Box::::try_new_uninit()?; - /// - /// let five = unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; + /// // Deferred initialization: + /// five.write(5); + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) @@ -435,10 +427,8 @@ impl Box { A: Allocator, { let mut boxed = Self::new_uninit_in(alloc); - unsafe { - boxed.as_mut_ptr().write(x); - boxed.assume_init() - } + boxed.write(x); + unsafe { boxed.assume_init() } } /// Allocates memory in the given allocator then places `x` into it, @@ -463,10 +453,8 @@ impl Box { A: Allocator, { let mut boxed = Self::try_new_uninit_in(alloc)?; - unsafe { - boxed.as_mut_ptr().write(x); - Ok(boxed.assume_init()) - } + boxed.write(x); + unsafe { Ok(boxed.assume_init()) } } /// Constructs a new box with uninitialized contents in the provided allocator. @@ -479,13 +467,9 @@ impl Box { /// use std::alloc::System; /// /// let mut five = Box::::new_uninit_in(System); - /// - /// let five = unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; + /// // Deferred initialization: + /// five.write(5); + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -517,13 +501,9 @@ impl Box { /// use std::alloc::System; /// /// let mut five = Box::::try_new_uninit_in(System)?; - /// - /// let five = unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; + /// // Deferred initialization: + /// five.write(5); + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) @@ -669,15 +649,11 @@ impl Box<[T]> { /// /// ``` /// let mut values = Box::<[u32]>::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// values[0].as_mut_ptr().write(1); - /// values[1].as_mut_ptr().write(2); - /// values[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; + /// // Deferred initialization: + /// values[0].write(1); + /// values[1].write(2); + /// values[2].write(3); + /// let values = unsafe {values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` @@ -722,13 +698,11 @@ impl Box<[T]> { /// #![feature(allocator_api)] /// /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; - /// let values = unsafe { - /// // Deferred initialization: - /// values[0].as_mut_ptr().write(1); - /// values[1].as_mut_ptr().write(2); - /// values[2].as_mut_ptr().write(3); - /// values.assume_init() - /// }; + /// // Deferred initialization: + /// values[0].write(1); + /// values[1].write(2); + /// values[2].write(3); + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]); /// # Ok::<(), std::alloc::AllocError>(()) @@ -814,15 +788,11 @@ impl Box<[T], A> { /// use std::alloc::System; /// /// let mut values = Box::<[u32], _>::new_uninit_slice_in(3, System); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// values[0].as_mut_ptr().write(1); - /// values[1].as_mut_ptr().write(2); - /// values[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; + /// // Deferred initialization: + /// values[0].write(1); + /// values[1].write(2); + /// values[2].write(3); + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` @@ -873,13 +843,11 @@ impl Box<[T], A> { /// use std::alloc::System; /// /// let mut values = Box::<[u32], _>::try_new_uninit_slice_in(3, System)?; - /// let values = unsafe { - /// // Deferred initialization: - /// values[0].as_mut_ptr().write(1); - /// values[1].as_mut_ptr().write(2); - /// values[2].as_mut_ptr().write(3); - /// values.assume_init() - /// }; + /// // Deferred initialization: + /// values[0].write(1); + /// values[1].write(2); + /// values[2].write(3); + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]); /// # Ok::<(), std::alloc::AllocError>(()) @@ -959,13 +927,9 @@ impl Box, A> { /// /// ``` /// let mut five = Box::::new_uninit(); - /// - /// let five: Box = unsafe { - /// // Deferred initialization: - /// five.as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; + /// // Deferred initialization: + /// five.write(5); + /// let five: Box = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -1030,15 +994,11 @@ impl Box<[mem::MaybeUninit], A> { /// /// ``` /// let mut values = Box::<[u32]>::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// values[0].as_mut_ptr().write(1); - /// values[1].as_mut_ptr().write(2); - /// values[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; + /// // Deferred initialization: + /// values[0].write(1); + /// values[1].write(2); + /// values[2].write(3); + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` From fc5ff7f3f9a088b4f2882c51c845593f42a2faee Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Thu, 13 Feb 2025 18:10:22 +0100 Subject: [PATCH 17/20] ci: switch loongarch jobs to free runners --- src/ci/github-actions/jobs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index c08104e796b93..5c6a4d84e3eb2 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -168,10 +168,10 @@ auto: <<: *job-linux-4c - name: dist-loongarch64-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - name: dist-loongarch64-musl - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - name: dist-ohos <<: *job-linux-4c From 296625613386532e8a6963f821716db119c2ab62 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 13 Jan 2025 15:52:08 +0000 Subject: [PATCH 18/20] Make `-O` mean `-C opt-level=3` --- compiler/rustc_codegen_cranelift/src/lib.rs | 2 +- compiler/rustc_codegen_gcc/src/lib.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 4 +-- compiler/rustc_codegen_ssa/src/back/linker.rs | 16 ++++++------ compiler/rustc_codegen_ssa/src/back/write.rs | 4 +-- compiler/rustc_codegen_ssa/src/base.rs | 6 ++--- compiler/rustc_mir_transform/src/inline.rs | 3 +-- compiler/rustc_session/src/config.rs | 26 ++++++++++++------- src/doc/rustc/src/codegen-options/index.md | 2 +- src/doc/rustc/src/command-line-arguments.md | 2 +- .../src/external_deps/rustc.rs | 2 +- tests/run-make/rustc-help/help-v.stdout | 2 +- tests/run-make/rustc-help/help.stdout | 2 +- 13 files changed, 39 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index b015341990306..a3f4374487578 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -289,7 +289,7 @@ fn build_isa(sess: &Session) -> Arc { flags_builder.set("opt_level", "none").unwrap(); } OptLevel::Less - | OptLevel::Default + | OptLevel::More | OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index ce88ac390216a..6455bcec6851b 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -476,7 +476,7 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { Some(level) => match level { OptLevel::No => OptimizationLevel::None, OptLevel::Less => OptimizationLevel::Limited, - OptLevel::Default => OptimizationLevel::Standard, + OptLevel::More => OptimizationLevel::Standard, OptLevel::Aggressive => OptimizationLevel::Aggressive, OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited, }, diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 58933a77e53d1..9fa10e960680b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -141,7 +141,7 @@ fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm:: match cfg { No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone), Less => (llvm::CodeGenOptLevel::Less, llvm::CodeGenOptSizeNone), - Default => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone), + More => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone), Aggressive => (llvm::CodeGenOptLevel::Aggressive, llvm::CodeGenOptSizeNone), Size => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeDefault), SizeMin => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeAggressive), @@ -153,7 +153,7 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel match cfg { No => llvm::PassBuilderOptLevel::O0, Less => llvm::PassBuilderOptLevel::O1, - Default => llvm::PassBuilderOptLevel::O2, + More => llvm::PassBuilderOptLevel::O2, Aggressive => llvm::PassBuilderOptLevel::O3, Size => llvm::PassBuilderOptLevel::Os, SizeMin => llvm::PassBuilderOptLevel::Oz, diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8fb831471a9ba..05d6ff357514d 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -410,7 +410,7 @@ impl<'a> GccLinker<'a> { let opt_level = match self.sess.opts.optimize { config::OptLevel::No => "O0", config::OptLevel::Less => "O1", - config::OptLevel::Default | config::OptLevel::Size | config::OptLevel::SizeMin => "O2", + config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2", config::OptLevel::Aggressive => "O3", }; @@ -685,7 +685,7 @@ impl<'a> Linker for GccLinker<'a> { // GNU-style linkers support optimization with -O. GNU ld doesn't // need a numeric argument, but other linkers do. - if self.sess.opts.optimize == config::OptLevel::Default + if self.sess.opts.optimize == config::OptLevel::More || self.sess.opts.optimize == config::OptLevel::Aggressive { self.link_arg("-O1"); @@ -1213,7 +1213,7 @@ impl<'a> Linker for EmLinker<'a> { self.cc_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", @@ -1384,7 +1384,7 @@ impl<'a> Linker for WasmLd<'a> { self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2` // instead. @@ -1451,7 +1451,7 @@ impl<'a> WasmLd<'a> { let opt_level = match self.sess.opts.optimize { config::OptLevel::No => "O0", config::OptLevel::Less => "O1", - config::OptLevel::Default => "O2", + config::OptLevel::More => "O2", config::OptLevel::Aggressive => "O3", // wasm-ld only handles integer LTO opt levels. Use O2 config::OptLevel::Size | config::OptLevel::SizeMin => "O2", @@ -1525,7 +1525,7 @@ impl<'a> Linker for L4Bender<'a> { fn optimize(&mut self) { // GNU-style linkers support optimization with -O. GNU ld doesn't // need a numeric argument, but other linkers do. - if self.sess.opts.optimize == config::OptLevel::Default + if self.sess.opts.optimize == config::OptLevel::More || self.sess.opts.optimize == config::OptLevel::Aggressive { self.link_arg("-O1"); @@ -1929,7 +1929,7 @@ impl<'a> Linker for LlbcLinker<'a> { match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", @@ -2006,7 +2006,7 @@ impl<'a> Linker for BpfLinker<'a> { self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ce2161a07ebf6..f029c08a80821 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -236,7 +236,7 @@ impl ModuleConfig { // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. vectorize_loop: !sess.opts.cg.no_vectorize_loops - && (sess.opts.optimize == config::OptLevel::Default + && (sess.opts.optimize == config::OptLevel::More || sess.opts.optimize == config::OptLevel::Aggressive), vectorize_slp: !sess.opts.cg.no_vectorize_slp && sess.opts.optimize == config::OptLevel::Aggressive, @@ -260,7 +260,7 @@ impl ModuleConfig { MergeFunctions::Trampolines | MergeFunctions::Aliases => { use config::OptLevel::*; match sess.opts.optimize { - Aggressive | Default | SizeMin | Size => true, + Aggressive | More | SizeMin | Size => true, Less | No => false, } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index d9fbf539fd3d5..e800492dad02f 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1054,12 +1054,12 @@ pub(crate) fn provide(providers: &mut Providers) { config::OptLevel::No => return config::OptLevel::No, // If globally optimise-speed is already specified, just use that level. config::OptLevel::Less => return config::OptLevel::Less, - config::OptLevel::Default => return config::OptLevel::Default, + config::OptLevel::More => return config::OptLevel::More, config::OptLevel::Aggressive => return config::OptLevel::Aggressive, // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size) // are present). - config::OptLevel::Size => config::OptLevel::Default, - config::OptLevel::SizeMin => config::OptLevel::Default, + config::OptLevel::Size => config::OptLevel::More, + config::OptLevel::SizeMin => config::OptLevel::More, }; let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ab617e2ce6fd6..1f8392b211870 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -49,8 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for Inline { match sess.mir_opt_level() { 0 | 1 => false, 2 => { - (sess.opts.optimize == OptLevel::Default - || sess.opts.optimize == OptLevel::Aggressive) + (sess.opts.optimize == OptLevel::More || sess.opts.optimize == OptLevel::Aggressive) && sess.opts.incremental == None } _ => true, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2fb4b27b88905..7d473b86ff58a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -86,12 +86,18 @@ pub enum CFProtection { #[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)] pub enum OptLevel { - No, // -O0 - Less, // -O1 - Default, // -O2 - Aggressive, // -O3 - Size, // -Os - SizeMin, // -Oz + /// `-Copt-level=0` + No, + /// `-Copt-level=1` + Less, + /// `-Copt-level=2` + More, + /// `-Copt-level=3` / `-O` + Aggressive, + /// `-Copt-level=s` + Size, + /// `-Copt-level=z` + SizeMin, } /// This is what the `LtoCli` values get mapped to after resolving defaults and @@ -1253,7 +1259,7 @@ impl Options { Some(setting) => setting, None => match self.optimize { OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true, - OptLevel::Default | OptLevel::Aggressive => false, + OptLevel::More | OptLevel::Aggressive => false, }, } } @@ -1572,7 +1578,7 @@ pub fn rustc_optgroups() -> Vec { stack-protector-strategies|link-args|deployment-target]", ), opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), - opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""), + opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""), opt(Stable, Opt, "o", "", "Write output to ", "FILENAME"), opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), opt( @@ -2127,12 +2133,12 @@ fn parse_opt_level( }) .max(); if max_o > max_c { - OptLevel::Default + OptLevel::Aggressive } else { match cg.opt_level.as_ref() { "0" => OptLevel::No, "1" => OptLevel::Less, - "2" => OptLevel::Default, + "2" => OptLevel::More, "3" => OptLevel::Aggressive, "s" => OptLevel::Size, "z" => OptLevel::SizeMin, diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f45217c69ff0f..8c1769a8c7722 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -368,7 +368,7 @@ This flag controls the optimization level. * `s`: optimize for binary size. * `z`: optimize for binary size, but also turn off loop vectorization. -Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=2`. +Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=3`. The default is `0`. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 0942b5ebfee37..9dd2e7de1b330 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -308,7 +308,7 @@ A synonym for [`-C debuginfo=2`](codegen-options/index.md#debuginfo). ## `-O`: optimize your code -A synonym for [`-C opt-level=2`](codegen-options/index.md#opt-level). +A synonym for [`-C opt-level=3`](codegen-options/index.md#opt-level). ## `-o`: filename of the output diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 33dc57cbc0776..fd4a20278addd 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -84,7 +84,7 @@ impl Rustc { self } - /// Specify default optimization level `-O` (alias for `-C opt-level=2`). + /// Specify default optimization level `-O` (alias for `-C opt-level=3`). pub fn opt(&mut self) -> &mut Self { self.cmd.arg("-O"); self diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index 8f6fde69c29b1..382b1c96682cb 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -32,7 +32,7 @@ Options: --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 - -O Equivalent to -C opt-level=2 + -O Equivalent to -C opt-level=3 -o FILENAME Write output to --out-dir DIR Write output to compiler-chosen filename in --explain OPT Provide a detailed explanation of an error message diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 131efa93282fd..08bb7f85098d2 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -32,7 +32,7 @@ Options: --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 - -O Equivalent to -C opt-level=2 + -O Equivalent to -C opt-level=3 -o FILENAME Write output to --out-dir DIR Write output to compiler-chosen filename in --explain OPT Provide a detailed explanation of an error message From 06524b56bdfc7019154798659e2a72d6cc2c9c83 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 13 Feb 2025 14:32:50 -0800 Subject: [PATCH 19/20] Update backtrace --- library/backtrace | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/backtrace b/library/backtrace index f8cc6ac9acc4e..9d2c34e7e63af 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit f8cc6ac9acc4e663ecd96f9bcf1ff4542636d1b9 +Subproject commit 9d2c34e7e63afe1e71c333b247065e3b7ba4d883 From bfdc96114c4b591025dd6ec18b4282f0b21e641c Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Thu, 13 Feb 2025 15:04:39 -0800 Subject: [PATCH 20/20] [cg_llvm] Remove dead error message --- compiler/rustc_codegen_llvm/messages.ftl | 3 --- compiler/rustc_codegen_llvm/src/errors.rs | 5 ----- 2 files changed, 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 9585848cbf033..399d7ffea8e6d 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -38,9 +38,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit codegen_llvm_mismatch_data_layout = data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}` -codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found -codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err} - codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index f4c9491f75844..97f4925616595 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -131,8 +131,6 @@ pub enum LlvmError<'a> { LoadBitcode { name: CString }, #[diag(codegen_llvm_write_thinlto_key)] WriteThinLtoKey { err: std::io::Error }, - #[diag(codegen_llvm_multiple_source_dicompileunit)] - MultipleSourceDiCompileUnit, #[diag(codegen_llvm_prepare_thin_lto_module)] PrepareThinLtoModule, #[diag(codegen_llvm_parse_bitcode)] @@ -155,9 +153,6 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err, LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err, WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err, - MultipleSourceDiCompileUnit => { - fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err - } PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err,