summaryrefslogtreecommitdiffstats
path: root/library/core/tests
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/tests')
-rw-r--r--library/core/tests/any.rs18
-rw-r--r--library/core/tests/fmt/float.rs124
-rw-r--r--library/core/tests/hash/mod.rs38
-rw-r--r--library/core/tests/hash/sip.rs15
-rw-r--r--library/core/tests/iter/adapters/array_chunks.rs3
-rw-r--r--library/core/tests/iter/adapters/take.rs20
-rw-r--r--library/core/tests/iter/sources.rs49
-rw-r--r--library/core/tests/lib.rs10
-rw-r--r--library/core/tests/mem.rs20
-rw-r--r--library/core/tests/num/flt2dec/mod.rs4
-rw-r--r--library/core/tests/option.rs2
-rw-r--r--library/core/tests/ptr.rs291
-rw-r--r--library/core/tests/slice.rs60
13 files changed, 636 insertions, 18 deletions
diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs
index 9538b8139..e98dac8d1 100644
--- a/library/core/tests/any.rs
+++ b/library/core/tests/any.rs
@@ -131,6 +131,24 @@ fn distinct_type_names() {
assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),);
}
+#[cfg(not(bootstrap))]
+#[test]
+fn dyn_type_name() {
+ trait Foo {
+ type Bar;
+ }
+
+ assert_eq!(
+ "dyn core::ops::function::Fn(i32, i32) -> i32",
+ std::any::type_name::<dyn Fn(i32, i32) -> i32>()
+ );
+ assert_eq!(
+ "dyn coretests::any::dyn_type_name::Foo<Bar = i32> \
+ + core::marker::Send + core::marker::Sync",
+ std::any::type_name::<dyn Foo<Bar = i32> + Send + Sync>()
+ );
+}
+
// Test the `Provider` API.
struct SomeConcreteType {
diff --git a/library/core/tests/fmt/float.rs b/library/core/tests/fmt/float.rs
index 47a7400f7..003782f34 100644
--- a/library/core/tests/fmt/float.rs
+++ b/library/core/tests/fmt/float.rs
@@ -5,7 +5,7 @@ fn test_format_f64() {
assert_eq!("10", format!("{:.0}", 9.9f64));
assert_eq!("9.8", format!("{:.1}", 9.849f64));
assert_eq!("9.9", format!("{:.1}", 9.851f64));
- assert_eq!("1", format!("{:.0}", 0.5f64));
+ assert_eq!("0", format!("{:.0}", 0.5f64));
assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
@@ -25,13 +25,73 @@ fn test_format_f64() {
}
#[test]
+fn test_format_f64_rounds_ties_to_even() {
+ assert_eq!("0", format!("{:.0}", 0.5f64));
+ assert_eq!("2", format!("{:.0}", 1.5f64));
+ assert_eq!("2", format!("{:.0}", 2.5f64));
+ assert_eq!("4", format!("{:.0}", 3.5f64));
+ assert_eq!("4", format!("{:.0}", 4.5f64));
+ assert_eq!("6", format!("{:.0}", 5.5f64));
+ assert_eq!("128", format!("{:.0}", 127.5f64));
+ assert_eq!("128", format!("{:.0}", 128.5f64));
+ assert_eq!("0.2", format!("{:.1}", 0.25f64));
+ assert_eq!("0.8", format!("{:.1}", 0.75f64));
+ assert_eq!("0.12", format!("{:.2}", 0.125f64));
+ assert_eq!("0.88", format!("{:.2}", 0.875f64));
+ assert_eq!("0.062", format!("{:.3}", 0.062f64));
+ assert_eq!("-0", format!("{:.0}", -0.5f64));
+ assert_eq!("-2", format!("{:.0}", -1.5f64));
+ assert_eq!("-2", format!("{:.0}", -2.5f64));
+ assert_eq!("-4", format!("{:.0}", -3.5f64));
+ assert_eq!("-4", format!("{:.0}", -4.5f64));
+ assert_eq!("-6", format!("{:.0}", -5.5f64));
+ assert_eq!("-128", format!("{:.0}", -127.5f64));
+ assert_eq!("-128", format!("{:.0}", -128.5f64));
+ assert_eq!("-0.2", format!("{:.1}", -0.25f64));
+ assert_eq!("-0.8", format!("{:.1}", -0.75f64));
+ assert_eq!("-0.12", format!("{:.2}", -0.125f64));
+ assert_eq!("-0.88", format!("{:.2}", -0.875f64));
+ assert_eq!("-0.062", format!("{:.3}", -0.062f64));
+
+ assert_eq!("2e0", format!("{:.0e}", 1.5f64));
+ assert_eq!("2e0", format!("{:.0e}", 2.5f64));
+ assert_eq!("4e0", format!("{:.0e}", 3.5f64));
+ assert_eq!("4e0", format!("{:.0e}", 4.5f64));
+ assert_eq!("6e0", format!("{:.0e}", 5.5f64));
+ assert_eq!("1.28e2", format!("{:.2e}", 127.5f64));
+ assert_eq!("1.28e2", format!("{:.2e}", 128.5f64));
+ assert_eq!("-2e0", format!("{:.0e}", -1.5f64));
+ assert_eq!("-2e0", format!("{:.0e}", -2.5f64));
+ assert_eq!("-4e0", format!("{:.0e}", -3.5f64));
+ assert_eq!("-4e0", format!("{:.0e}", -4.5f64));
+ assert_eq!("-6e0", format!("{:.0e}", -5.5f64));
+ assert_eq!("-1.28e2", format!("{:.2e}", -127.5f64));
+ assert_eq!("-1.28e2", format!("{:.2e}", -128.5f64));
+
+ assert_eq!("2E0", format!("{:.0E}", 1.5f64));
+ assert_eq!("2E0", format!("{:.0E}", 2.5f64));
+ assert_eq!("4E0", format!("{:.0E}", 3.5f64));
+ assert_eq!("4E0", format!("{:.0E}", 4.5f64));
+ assert_eq!("6E0", format!("{:.0E}", 5.5f64));
+ assert_eq!("1.28E2", format!("{:.2E}", 127.5f64));
+ assert_eq!("1.28E2", format!("{:.2E}", 128.5f64));
+ assert_eq!("-2E0", format!("{:.0E}", -1.5f64));
+ assert_eq!("-2E0", format!("{:.0E}", -2.5f64));
+ assert_eq!("-4E0", format!("{:.0E}", -3.5f64));
+ assert_eq!("-4E0", format!("{:.0E}", -4.5f64));
+ assert_eq!("-6E0", format!("{:.0E}", -5.5f64));
+ assert_eq!("-1.28E2", format!("{:.2E}", -127.5f64));
+ assert_eq!("-1.28E2", format!("{:.2E}", -128.5f64));
+}
+
+#[test]
fn test_format_f32() {
assert_eq!("1", format!("{:.0}", 1.0f32));
assert_eq!("9", format!("{:.0}", 9.4f32));
assert_eq!("10", format!("{:.0}", 9.9f32));
assert_eq!("9.8", format!("{:.1}", 9.849f32));
assert_eq!("9.9", format!("{:.1}", 9.851f32));
- assert_eq!("1", format!("{:.0}", 0.5f32));
+ assert_eq!("0", format!("{:.0}", 0.5f32));
assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
@@ -50,6 +110,66 @@ fn test_format_f32() {
assert_eq!("1234.6", format!("{:.1?}", 1234.56789f32));
}
+#[test]
+fn test_format_f32_rounds_ties_to_even() {
+ assert_eq!("0", format!("{:.0}", 0.5f32));
+ assert_eq!("2", format!("{:.0}", 1.5f32));
+ assert_eq!("2", format!("{:.0}", 2.5f32));
+ assert_eq!("4", format!("{:.0}", 3.5f32));
+ assert_eq!("4", format!("{:.0}", 4.5f32));
+ assert_eq!("6", format!("{:.0}", 5.5f32));
+ assert_eq!("128", format!("{:.0}", 127.5f32));
+ assert_eq!("128", format!("{:.0}", 128.5f32));
+ assert_eq!("0.2", format!("{:.1}", 0.25f32));
+ assert_eq!("0.8", format!("{:.1}", 0.75f32));
+ assert_eq!("0.12", format!("{:.2}", 0.125f32));
+ assert_eq!("0.88", format!("{:.2}", 0.875f32));
+ assert_eq!("0.062", format!("{:.3}", 0.062f32));
+ assert_eq!("-0", format!("{:.0}", -0.5f32));
+ assert_eq!("-2", format!("{:.0}", -1.5f32));
+ assert_eq!("-2", format!("{:.0}", -2.5f32));
+ assert_eq!("-4", format!("{:.0}", -3.5f32));
+ assert_eq!("-4", format!("{:.0}", -4.5f32));
+ assert_eq!("-6", format!("{:.0}", -5.5f32));
+ assert_eq!("-128", format!("{:.0}", -127.5f32));
+ assert_eq!("-128", format!("{:.0}", -128.5f32));
+ assert_eq!("-0.2", format!("{:.1}", -0.25f32));
+ assert_eq!("-0.8", format!("{:.1}", -0.75f32));
+ assert_eq!("-0.12", format!("{:.2}", -0.125f32));
+ assert_eq!("-0.88", format!("{:.2}", -0.875f32));
+ assert_eq!("-0.062", format!("{:.3}", -0.062f32));
+
+ assert_eq!("2e0", format!("{:.0e}", 1.5f32));
+ assert_eq!("2e0", format!("{:.0e}", 2.5f32));
+ assert_eq!("4e0", format!("{:.0e}", 3.5f32));
+ assert_eq!("4e0", format!("{:.0e}", 4.5f32));
+ assert_eq!("6e0", format!("{:.0e}", 5.5f32));
+ assert_eq!("1.28e2", format!("{:.2e}", 127.5f32));
+ assert_eq!("1.28e2", format!("{:.2e}", 128.5f32));
+ assert_eq!("-2e0", format!("{:.0e}", -1.5f32));
+ assert_eq!("-2e0", format!("{:.0e}", -2.5f32));
+ assert_eq!("-4e0", format!("{:.0e}", -3.5f32));
+ assert_eq!("-4e0", format!("{:.0e}", -4.5f32));
+ assert_eq!("-6e0", format!("{:.0e}", -5.5f32));
+ assert_eq!("-1.28e2", format!("{:.2e}", -127.5f32));
+ assert_eq!("-1.28e2", format!("{:.2e}", -128.5f32));
+
+ assert_eq!("2E0", format!("{:.0E}", 1.5f32));
+ assert_eq!("2E0", format!("{:.0E}", 2.5f32));
+ assert_eq!("4E0", format!("{:.0E}", 3.5f32));
+ assert_eq!("4E0", format!("{:.0E}", 4.5f32));
+ assert_eq!("6E0", format!("{:.0E}", 5.5f32));
+ assert_eq!("1.28E2", format!("{:.2E}", 127.5f32));
+ assert_eq!("1.28E2", format!("{:.2E}", 128.5f32));
+ assert_eq!("-2E0", format!("{:.0E}", -1.5f32));
+ assert_eq!("-2E0", format!("{:.0E}", -2.5f32));
+ assert_eq!("-4E0", format!("{:.0E}", -3.5f32));
+ assert_eq!("-4E0", format!("{:.0E}", -4.5f32));
+ assert_eq!("-6E0", format!("{:.0E}", -5.5f32));
+ assert_eq!("-1.28E2", format!("{:.2E}", -127.5f32));
+ assert_eq!("-1.28E2", format!("{:.2E}", -128.5f32));
+}
+
fn is_exponential(s: &str) -> bool {
s.contains("e") || s.contains("E")
}
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index f7934d062..267245f05 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -9,16 +9,19 @@ struct MyHasher {
hash: u64,
}
-impl Default for MyHasher {
+impl const Default for MyHasher {
fn default() -> MyHasher {
MyHasher { hash: 0 }
}
}
-impl Hasher for MyHasher {
+impl const Hasher for MyHasher {
fn write(&mut self, buf: &[u8]) {
- for byte in buf {
- self.hash += *byte as u64;
+ // FIXME(const_trait_impl): change to for loop
+ let mut i = 0;
+ while i < buf.len() {
+ self.hash += buf[i] as u64;
+ i += 1;
}
}
fn write_str(&mut self, s: &str) {
@@ -32,12 +35,25 @@ impl Hasher for MyHasher {
#[test]
fn test_writer_hasher() {
- fn hash<T: Hash>(t: &T) -> u64 {
+ const fn hash<T: ~const Hash>(t: &T) -> u64 {
let mut s = MyHasher { hash: 0 };
t.hash(&mut s);
s.finish()
}
+ const {
+ // FIXME(fee1-dead): assert_eq
+ assert!(hash(&()) == 0);
+ assert!(hash(&5_u8) == 5);
+ assert!(hash(&5_u16) == 5);
+ assert!(hash(&5_u32) == 5);
+
+ assert!(hash(&'a') == 97);
+
+ let s: &str = "a";
+ assert!(hash(&s) == 97 + 0xFF);
+ };
+
assert_eq!(hash(&()), 0);
assert_eq!(hash(&5_u8), 5);
@@ -97,7 +113,7 @@ struct CustomHasher {
output: u64,
}
-impl Hasher for CustomHasher {
+impl const Hasher for CustomHasher {
fn finish(&self) -> u64 {
self.output
}
@@ -109,27 +125,29 @@ impl Hasher for CustomHasher {
}
}
-impl Default for CustomHasher {
+impl const Default for CustomHasher {
fn default() -> CustomHasher {
CustomHasher { output: 0 }
}
}
-impl Hash for Custom {
- fn hash<H: Hasher>(&self, state: &mut H) {
+impl const Hash for Custom {
+ fn hash<H: ~const Hasher>(&self, state: &mut H) {
state.write_u64(self.hash);
}
}
#[test]
fn test_custom_state() {
- fn hash<T: Hash>(t: &T) -> u64 {
+ const fn hash<T: ~const Hash>(t: &T) -> u64 {
let mut c = CustomHasher { output: 0 };
t.hash(&mut c);
c.finish()
}
assert_eq!(hash(&Custom { hash: 5 }), 5);
+
+ const { assert!(hash(&Custom { hash: 6 }) == 6) };
}
// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten.
diff --git a/library/core/tests/hash/sip.rs b/library/core/tests/hash/sip.rs
index 877d08418..3abf6efcf 100644
--- a/library/core/tests/hash/sip.rs
+++ b/library/core/tests/hash/sip.rs
@@ -8,7 +8,6 @@ use core::{mem, slice};
struct Bytes<'a>(&'a [u8]);
impl<'a> Hash for Bytes<'a> {
- #[allow(unused_must_use)]
fn hash<H: Hasher>(&self, state: &mut H) {
let Bytes(v) = *self;
state.write(v);
@@ -25,6 +24,20 @@ fn hash<T: Hash>(x: &T) -> u64 {
}
#[test]
+const fn test_const_sip() {
+ let val1 = 0x45;
+ let val2 = 0xfeed;
+
+ const fn const_hash<T: ~const Hash>(x: &T) -> u64 {
+ let mut st = SipHasher::new();
+ x.hash(&mut st);
+ st.finish()
+ }
+
+ assert!(const_hash(&(val1)) != const_hash(&(val2)));
+}
+
+#[test]
#[allow(unused_must_use)]
fn test_siphash_1_3() {
let vecs: [[u8; 8]; 64] = [
diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/core/tests/iter/adapters/array_chunks.rs
index 4e9d89e1e..ef4a7e53b 100644
--- a/library/core/tests/iter/adapters/array_chunks.rs
+++ b/library/core/tests/iter/adapters/array_chunks.rs
@@ -139,7 +139,8 @@ fn test_iterator_array_chunks_fold() {
let result =
(0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>().fold(0, |acc, _item| acc + 1);
assert_eq!(result, 3);
- assert_eq!(count.get(), 10);
+ // fold impls may or may not process the remainder
+ assert!(count.get() <= 10 && count.get() >= 9);
}
#[test]
diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs
index bfb659f0a..3e26b43a2 100644
--- a/library/core/tests/iter/adapters/take.rs
+++ b/library/core/tests/iter/adapters/take.rs
@@ -146,3 +146,23 @@ fn test_take_try_folds() {
assert_eq!(iter.try_for_each(Err), Err(2));
assert_eq!(iter.try_for_each(Err), Ok(()));
}
+
+#[test]
+fn test_byref_take_consumed_items() {
+ let mut inner = 10..90;
+
+ let mut count = 0;
+ inner.by_ref().take(0).for_each(|_| count += 1);
+ assert_eq!(count, 0);
+ assert_eq!(inner, 10..90);
+
+ let mut count = 0;
+ inner.by_ref().take(10).for_each(|_| count += 1);
+ assert_eq!(count, 10);
+ assert_eq!(inner, 20..90);
+
+ let mut count = 0;
+ inner.by_ref().take(100).for_each(|_| count += 1);
+ assert_eq!(count, 70);
+ assert_eq!(inner, 90..90);
+}
diff --git a/library/core/tests/iter/sources.rs b/library/core/tests/iter/sources.rs
index d0114ade6..a15f3a514 100644
--- a/library/core/tests/iter/sources.rs
+++ b/library/core/tests/iter/sources.rs
@@ -106,3 +106,52 @@ fn test_empty() {
let mut it = empty::<i32>();
assert_eq!(it.next(), None);
}
+
+#[test]
+fn test_repeat_n_drop() {
+ #[derive(Clone, Debug)]
+ struct DropCounter<'a>(&'a Cell<usize>);
+ impl Drop for DropCounter<'_> {
+ fn drop(&mut self) {
+ self.0.set(self.0.get() + 1);
+ }
+ }
+
+ // `repeat_n(x, 0)` drops `x` immediately
+ let count = Cell::new(0);
+ let item = DropCounter(&count);
+ let mut it = repeat_n(item, 0);
+ assert_eq!(count.get(), 1);
+ assert!(it.next().is_none());
+ assert_eq!(count.get(), 1);
+ drop(it);
+ assert_eq!(count.get(), 1);
+
+ // Dropping the iterator needs to drop the item if it's non-empty
+ let count = Cell::new(0);
+ let item = DropCounter(&count);
+ let it = repeat_n(item, 3);
+ assert_eq!(count.get(), 0);
+ drop(it);
+ assert_eq!(count.get(), 1);
+
+ // Dropping the iterator doesn't drop the item if it was exhausted
+ let count = Cell::new(0);
+ let item = DropCounter(&count);
+ let mut it = repeat_n(item, 3);
+ assert_eq!(count.get(), 0);
+ let x0 = it.next().unwrap();
+ assert_eq!(count.get(), 0);
+ let x1 = it.next().unwrap();
+ assert_eq!(count.get(), 0);
+ let x2 = it.next().unwrap();
+ assert_eq!(count.get(), 0);
+ assert!(it.next().is_none());
+ assert_eq!(count.get(), 0);
+ assert!(it.next().is_none());
+ assert_eq!(count.get(), 0);
+ drop(it);
+ assert_eq!(count.get(), 0);
+ drop((x0, x1, x2));
+ assert_eq!(count.get(), 3);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 51f858ade..99d4a40c4 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -4,18 +4,22 @@
#![feature(array_windows)]
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
+#![feature(const_align_offset)]
#![feature(const_assume)]
+#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]
#![feature(const_bool_to_option)]
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_convert)]
+#![feature(const_hash)]
#![feature(const_heap)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_maybe_uninit_assume_init_read)]
#![feature(const_nonnull_new)]
#![feature(const_num_from_num)]
#![feature(const_pointer_byte_offsets)]
+#![feature(const_pointer_is_aligned)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_read)]
#![feature(const_ptr_write)]
@@ -42,6 +46,7 @@
#![feature(try_find)]
#![feature(inline_const)]
#![feature(is_sorted)]
+#![feature(layout_for_ptr)]
#![feature(pattern)]
#![feature(pin_macro)]
#![feature(sort_internals)]
@@ -62,7 +67,6 @@
#![feature(try_trait_v2)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
-#![feature(int_log)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iter_collect_into)]
@@ -71,6 +75,7 @@
#![feature(iter_is_partitioned)]
#![feature(iter_next_chunk)]
#![feature(iter_order_by)]
+#![feature(iter_repeat_n)]
#![feature(iterator_try_collect)]
#![feature(iterator_try_reduce)]
#![feature(const_mut_refs)]
@@ -79,6 +84,7 @@
#![feature(never_type)]
#![feature(unwrap_infallible)]
#![feature(pointer_byte_offsets)]
+#![feature(pointer_is_aligned)]
#![feature(portable_simd)]
#![feature(ptr_metadata)]
#![feature(once_cell)]
@@ -102,7 +108,9 @@
#![feature(provide_any)]
#![feature(utf8_chunks)]
#![feature(is_ascii_octdigit)]
+#![feature(get_many_mut)]
#![deny(unsafe_op_in_unsafe_fn)]
+#![deny(fuzzy_provenance_casts)]
extern crate test;
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 0362e1c8a..1cfb4fd9f 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -1,4 +1,5 @@
use core::mem::*;
+use core::ptr;
#[cfg(panic = "unwind")]
use std::rc::Rc;
@@ -76,6 +77,25 @@ fn align_of_val_basic() {
}
#[test]
+#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails
+fn align_of_val_raw_packed() {
+ #[repr(C, packed)]
+ struct B {
+ f: [u32],
+ }
+ let storage = [0u8; 4];
+ let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
+ assert_eq!(unsafe { align_of_val_raw(b) }, 1);
+
+ const ALIGN_OF_VAL_RAW: usize = {
+ let storage = [0u8; 4];
+ let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
+ unsafe { align_of_val_raw(b) }
+ };
+ assert_eq!(ALIGN_OF_VAL_RAW, 1);
+}
+
+#[test]
fn test_swap() {
let mut x = 31337;
let mut y = 42;
diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
index 798473bbd..30843cc3d 100644
--- a/library/core/tests/num/flt2dec/mod.rs
+++ b/library/core/tests/num/flt2dec/mod.rs
@@ -138,7 +138,7 @@ where
// check exact rounding for zero- and negative-width cases
let start;
- if expected[0] >= b'5' {
+ if expected[0] > b'5' {
try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1;
"zero-width rounding-up mismatch for v={v}: \
actual {actual:?}, expected {expected:?}",
@@ -1007,7 +1007,7 @@ where
assert_eq!(to_string(f, 999.5, Minus, 3), "999.500");
assert_eq!(to_string(f, 999.5, Minus, 30), "999.500000000000000000000000000000");
- assert_eq!(to_string(f, 0.5, Minus, 0), "1");
+ assert_eq!(to_string(f, 0.5, Minus, 0), "0");
assert_eq!(to_string(f, 0.5, Minus, 1), "0.5");
assert_eq!(to_string(f, 0.5, Minus, 2), "0.50");
assert_eq!(to_string(f, 0.5, Minus, 3), "0.500");
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index f36f7c268..dca6321cf 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -57,7 +57,7 @@ fn test_get_resource() {
}
#[test]
-#[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))]
+#[allow(for_loops_over_fallibles)]
fn test_option_dance() {
let x = Some(());
let mut y = Some(5);
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 97a369810..90bc83510 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -359,6 +359,23 @@ fn align_offset_zst() {
}
#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_zst_const() {
+ const {
+ // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
+ // all, because no amount of elements will align the pointer.
+ let mut p = 1;
+ while p < 1024 {
+ assert!(ptr::invalid::<()>(p).align_offset(p) == 0);
+ if p != 1 {
+ assert!(ptr::invalid::<()>(p + 1).align_offset(p) == !0);
+ }
+ p = (p + 1).next_power_of_two();
+ }
+ }
+}
+
+#[test]
fn align_offset_stride_one() {
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
// number of bytes.
@@ -380,6 +397,26 @@ fn align_offset_stride_one() {
}
#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_stride_one_const() {
+ const {
+ // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
+ // number of bytes.
+ let mut align = 1;
+ while align < 1024 {
+ let mut ptr = 1;
+ while ptr < 2 * align {
+ let expected = ptr % align;
+ let offset = if expected == 0 { 0 } else { align - expected };
+ assert!(ptr::invalid::<u8>(ptr).align_offset(align) == offset);
+ ptr += 1;
+ }
+ align = (align + 1).next_power_of_two();
+ }
+ }
+}
+
+#[test]
fn align_offset_various_strides() {
unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
let numptr = ptr as usize;
@@ -456,6 +493,260 @@ fn align_offset_various_strides() {
}
#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_various_strides_const() {
+ const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
+ let mut expected = usize::MAX;
+ // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
+ let mut el = 0;
+ while el < align {
+ if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
+ expected = el;
+ break;
+ }
+ el += 1;
+ }
+ let got = ptr.align_offset(align);
+ assert!(got == expected);
+ }
+
+ const {
+ // For pointers of stride != 1, we verify the algorithm against the naivest possible
+ // implementation
+ let mut align = 1;
+ let limit = 32;
+ while align < limit {
+ let mut ptr = 1;
+ while ptr < 4 * align {
+ unsafe {
+ #[repr(packed)]
+ struct A3(u16, u8);
+ test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
+
+ struct A4(u32);
+ test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A5(u32, u8);
+ test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A6(u32, u16);
+ test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A7(u32, u16, u8);
+ test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A8(u32, u32);
+ test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A9(u32, u32, u8);
+ test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
+
+ #[repr(packed)]
+ struct A10(u32, u32, u16);
+ test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
+
+ test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
+ test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
+ }
+ ptr += 1;
+ }
+ align = (align + 1).next_power_of_two();
+ }
+ }
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_with_provenance_const() {
+ const {
+ // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4.
+ #[repr(align(4))]
+ struct AlignedI32(i32);
+
+ let data = AlignedI32(42);
+
+ // `stride % align == 0` (usual case)
+
+ let ptr: *const i32 = &data.0;
+ assert!(ptr.align_offset(1) == 0);
+ assert!(ptr.align_offset(2) == 0);
+ assert!(ptr.align_offset(4) == 0);
+ assert!(ptr.align_offset(8) == usize::MAX);
+ assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
+ assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
+ assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
+ assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
+ assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
+ assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
+
+ assert!(ptr.wrapping_add(42).align_offset(4) == 0);
+ assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
+
+ let ptr1: *const i8 = ptr.cast();
+ assert!(ptr1.align_offset(1) == 0);
+ assert!(ptr1.align_offset(2) == 0);
+ assert!(ptr1.align_offset(4) == 0);
+ assert!(ptr1.align_offset(8) == usize::MAX);
+ assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
+ assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
+ assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
+ assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
+ assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
+ assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
+ assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+ assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
+ assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
+ assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
+ assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
+
+ let ptr2: *const i16 = ptr.cast();
+ assert!(ptr2.align_offset(1) == 0);
+ assert!(ptr2.align_offset(2) == 0);
+ assert!(ptr2.align_offset(4) == 0);
+ assert!(ptr2.align_offset(8) == usize::MAX);
+ assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
+ assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
+ assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
+ assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
+ assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+ assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
+ assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
+
+ let ptr3: *const i64 = ptr.cast();
+ assert!(ptr3.align_offset(1) == 0);
+ assert!(ptr3.align_offset(2) == 0);
+ assert!(ptr3.align_offset(4) == 0);
+ assert!(ptr3.align_offset(8) == usize::MAX);
+ assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
+
+ // `stride % align != 0` (edge case)
+
+ let ptr4: *const [u8; 3] = ptr.cast();
+ assert!(ptr4.align_offset(1) == 0);
+ assert!(ptr4.align_offset(2) == 0);
+ assert!(ptr4.align_offset(4) == 0);
+ assert!(ptr4.align_offset(8) == usize::MAX);
+ assert!(ptr4.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr4.wrapping_byte_add(1).align_offset(2) == 1);
+ assert!(ptr4.wrapping_byte_add(1).align_offset(4) == 1);
+ assert!(ptr4.wrapping_byte_add(1).align_offset(8) == usize::MAX);
+ assert!(ptr4.wrapping_byte_add(2).align_offset(1) == 0);
+ assert!(ptr4.wrapping_byte_add(2).align_offset(2) == 0);
+ assert!(ptr4.wrapping_byte_add(2).align_offset(4) == 2);
+ assert!(ptr4.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+ assert!(ptr4.wrapping_byte_add(3).align_offset(1) == 0);
+ assert!(ptr4.wrapping_byte_add(3).align_offset(2) == 1);
+ assert!(ptr4.wrapping_byte_add(3).align_offset(4) == 3);
+ assert!(ptr4.wrapping_byte_add(3).align_offset(8) == usize::MAX);
+
+ let ptr5: *const [u8; 5] = ptr.cast();
+ assert!(ptr5.align_offset(1) == 0);
+ assert!(ptr5.align_offset(2) == 0);
+ assert!(ptr5.align_offset(4) == 0);
+ assert!(ptr5.align_offset(8) == usize::MAX);
+ assert!(ptr5.wrapping_byte_add(1).align_offset(1) == 0);
+ assert!(ptr5.wrapping_byte_add(1).align_offset(2) == 1);
+ assert!(ptr5.wrapping_byte_add(1).align_offset(4) == 3);
+ assert!(ptr5.wrapping_byte_add(1).align_offset(8) == usize::MAX);
+ assert!(ptr5.wrapping_byte_add(2).align_offset(1) == 0);
+ assert!(ptr5.wrapping_byte_add(2).align_offset(2) == 0);
+ assert!(ptr5.wrapping_byte_add(2).align_offset(4) == 2);
+ assert!(ptr5.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+ assert!(ptr5.wrapping_byte_add(3).align_offset(1) == 0);
+ assert!(ptr5.wrapping_byte_add(3).align_offset(2) == 1);
+ assert!(ptr5.wrapping_byte_add(3).align_offset(4) == 1);
+ assert!(ptr5.wrapping_byte_add(3).align_offset(8) == usize::MAX);
+ }
+}
+
+#[test]
+fn align_offset_issue_103361() {
+ #[cfg(target_pointer_width = "64")]
+ const SIZE: usize = 1 << 47;
+ #[cfg(target_pointer_width = "32")]
+ const SIZE: usize = 1 << 30;
+ #[cfg(target_pointer_width = "16")]
+ const SIZE: usize = 1 << 13;
+ struct HugeSize([u8; SIZE - 1]);
+ let _ = ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_issue_103361_const() {
+ #[cfg(target_pointer_width = "64")]
+ const SIZE: usize = 1 << 47;
+ #[cfg(target_pointer_width = "32")]
+ const SIZE: usize = 1 << 30;
+ #[cfg(target_pointer_width = "16")]
+ const SIZE: usize = 1 << 13;
+ struct HugeSize([u8; SIZE - 1]);
+
+ const {
+ assert!(ptr::invalid::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
+ assert!(ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE) == 0);
+ assert!(ptr::invalid::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
+ }
+}
+
+#[test]
+fn is_aligned() {
+ let data = 42;
+ let ptr: *const i32 = &data;
+ assert!(ptr.is_aligned());
+ assert!(ptr.is_aligned_to(1));
+ assert!(ptr.is_aligned_to(2));
+ assert!(ptr.is_aligned_to(4));
+ assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
+ assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
+ assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
+
+ // At runtime either `ptr` or `ptr+1` is aligned to 8.
+ assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn is_aligned_const() {
+ const {
+ let data = 42;
+ let ptr: *const i32 = &data;
+ assert!(ptr.is_aligned());
+ assert!(ptr.is_aligned_to(1));
+ assert!(ptr.is_aligned_to(2));
+ assert!(ptr.is_aligned_to(4));
+ assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
+ assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
+ assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
+
+ // At comptime neither `ptr` nor `ptr+1` is aligned to 8.
+ assert!(!ptr.is_aligned_to(8));
+ assert!(!ptr.wrapping_add(1).is_aligned_to(8));
+ }
+}
+
+#[test]
+#[cfg(bootstrap)]
+fn is_aligned_const() {
+ const {
+ let data = 42;
+ let ptr: *const i32 = &data;
+ // The bootstrap compiler always returns false for is_aligned.
+ assert!(!ptr.is_aligned());
+ assert!(!ptr.is_aligned_to(1));
+ }
+}
+
+#[test]
fn offset_from() {
let mut a = [0; 5];
let ptr1: *mut i32 = &mut a[1];
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 9e1fbea79..4e06e0f43 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -2595,3 +2595,63 @@ fn test_flatten_mut_size_overflow() {
let x = &mut [[(); usize::MAX]; 2][..];
let _ = x.flatten_mut();
}
+
+#[test]
+fn test_get_many_mut_normal_2() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let [a, b] = v.get_many_mut([3, 0]).unwrap();
+ *a += 10;
+ *b += 100;
+ assert_eq!(v, vec![101, 2, 3, 14, 5]);
+}
+
+#[test]
+fn test_get_many_mut_normal_3() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let [a, b, c] = v.get_many_mut([0, 4, 2]).unwrap();
+ *a += 10;
+ *b += 100;
+ *c += 1000;
+ assert_eq!(v, vec![11, 2, 1003, 4, 105]);
+}
+
+#[test]
+fn test_get_many_mut_empty() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let [] = v.get_many_mut([]).unwrap();
+ assert_eq!(v, vec![1, 2, 3, 4, 5]);
+}
+
+#[test]
+fn test_get_many_mut_single_first() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let [a] = v.get_many_mut([0]).unwrap();
+ *a += 10;
+ assert_eq!(v, vec![11, 2, 3, 4, 5]);
+}
+
+#[test]
+fn test_get_many_mut_single_last() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ let [a] = v.get_many_mut([4]).unwrap();
+ *a += 10;
+ assert_eq!(v, vec![1, 2, 3, 4, 15]);
+}
+
+#[test]
+fn test_get_many_mut_oob_nonempty() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ assert!(v.get_many_mut([5]).is_err());
+}
+
+#[test]
+fn test_get_many_mut_oob_empty() {
+ let mut v: Vec<i32> = vec![];
+ assert!(v.get_many_mut([0]).is_err());
+}
+
+#[test]
+fn test_get_many_mut_duplicate() {
+ let mut v = vec![1, 2, 3, 4, 5];
+ assert!(v.get_many_mut([1, 3, 3, 4]).is_err());
+}