Auto merge of #107980 - Dylan-DPC:rollup-u4b19bl, r=Dylan-DPC

Rollup of 7 pull requests

Successful merges:

 - #107654 (reword descriptions of the deprecated int modules)
 - #107915 (Add `array::map` benchmarks)
 - #107961 (Avoid copy-pasting the `ilog` panic string in a bunch of places)
 - #107962 (Add a doc note about why `Chain` is not `ExactSizeIterator`)
 - #107966 (Update browser-ui-test version to 0.14.3)
 - #107970 (Hermit: Remove floor symbol)
 - #107973 (Fix unintentional UB in SIMD tests)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-02-13 07:07:33 +00:00
commit 20081880ad
24 changed files with 155 additions and 178 deletions

View file

@ -0,0 +1,19 @@
use test::black_box;
use test::Bencher;
macro_rules! map_array {
($func_name:ident, $start_item: expr, $map_item: expr, $arr_size: expr) => {
#[bench]
fn $func_name(b: &mut Bencher) {
let arr = [$start_item; $arr_size];
b.iter(|| black_box(arr).map(|_| black_box($map_item)));
}
};
}
map_array!(map_8byte_8byte_8, 0u64, 1u64, 800);
map_array!(map_8byte_8byte_64, 0u64, 1u64, 6400);
map_array!(map_8byte_8byte_256, 0u64, 1u64, 25600);
map_array!(map_8byte_256byte_256, 0u64, [0u64; 4], 25600);
map_array!(map_256byte_8byte_256, [0u64; 4], 0u64, 25600);

View file

@ -9,6 +9,7 @@
extern crate test;
mod any;
mod array;
mod ascii;
mod char;
mod fmt;

View file

@ -21,6 +21,16 @@
///
/// [`len`]: ExactSizeIterator::len
///
/// # When *shouldn't* an adapter be `ExactSizeIterator`?
///
/// If an adapter makes an iterator *longer*, then it's usually incorrect for
/// that adapter to implement `ExactSizeIterator`. The inner exact-sized
/// iterator might already be `usize::MAX`-long, and thus the length of the
/// longer adapted iterator would no longer be exactly representable in `usize`.
///
/// This is why [`Chain<A, B>`](crate::iter::Chain) isn't `ExactSizeIterator`,
/// even when `A` and `B` are both `ExactSizeIterator`.
///
/// # Examples
///
/// Basic usage:

View file

@ -31,6 +31,17 @@ impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}
/// The iterator must produce exactly the number of elements it reported
/// or diverge before reaching the end.
///
/// # When *shouldn't* an adapter be `TrustedLen`?
///
/// If an adapter makes an iterator *shorter* by a given amount, then it's
/// usually incorrect for that adapter to implement `TrustedLen`. The inner
/// iterator might return more than `usize::MAX` items, but there's no way to
/// know what `k` elements less than that will be, since the `size_hint` from
/// the inner iterator has already saturated and lost that information.
///
/// This is why [`Skip<I>`](crate::iter::Skip) isn't `TrustedLen`, even when
/// `I` implements `TrustedLen`.
///
/// # Safety
///
/// This trait must only be implemented when the contract is upheld. Consumers

View file

@ -138,3 +138,11 @@ pub const fn i64(val: i64) -> u32 {
pub const fn i128(val: i128) -> u32 {
u128(val as u128)
}
/// Instantiate this panic logic once, rather than for all the ilog methods
/// on every single primitive type.
#[cold]
#[track_caller]
pub const fn panic_for_nonpositive_argument() -> ! {
panic!("argument of integer logarithm must be positive")
}

View file

@ -2331,14 +2331,17 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog(self, base: Self) -> u32 {
assert!(base >= 2, "base of integer logarithm must be at least 2");
self.checked_ilog(base).expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog(base) {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the base 2 logarithm of the number, rounded down.
@ -2354,13 +2357,16 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog2(self) -> u32 {
self.checked_ilog2().expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog2() {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the base 10 logarithm of the number, rounded down.
@ -2376,13 +2382,16 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog10(self) -> u32 {
self.checked_ilog10().expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog10() {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the logarithm of the number with respect to an arbitrary base,

View file

@ -1,6 +1,4 @@
//! Constants for the 128-bit signed integer type.
//!
//! *[See also the `i128` primitive type][i128].*
//! Redundant constants module for the [`i128` primitive type][i128].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 16-bit signed integer type.
//!
//! *[See also the `i16` primitive type][i16].*
//! Redundant constants module for the [`i16` primitive type][i16].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 32-bit signed integer type.
//!
//! *[See also the `i32` primitive type][i32].*
//! Redundant constants module for the [`i32` primitive type][i32].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 64-bit signed integer type.
//!
//! *[See also the `i64` primitive type][i64].*
//! Redundant constants module for the [`i64` primitive type][i64].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 8-bit signed integer type.
//!
//! *[See also the `i8` primitive type][i8].*
//! Redundant constants module for the [`i8` primitive type][i8].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the pointer-sized signed integer type.
//!
//! *[See also the `isize` primitive type][isize].*
//! Redundant constants module for the [`isize` primitive type][isize].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 128-bit unsigned integer type.
//!
//! *[See also the `u128` primitive type][u128].*
//! Redundant constants module for the [`u128` primitive type][u128].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 16-bit unsigned integer type.
//!
//! *[See also the `u16` primitive type][u16].*
//! Redundant constants module for the [`i16` primitive type][i16].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 32-bit unsigned integer type.
//!
//! *[See also the `u32` primitive type][u32].*
//! Redundant constants module for the [`u32` primitive type][u32].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 64-bit unsigned integer type.
//!
//! *[See also the `u64` primitive type][u64].*
//! Redundant constants module for the [`u64` primitive type][u64].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the 8-bit unsigned integer type.
//!
//! *[See also the `u8` primitive type][u8].*
//! Redundant constants module for the [`u8` primitive type][u8].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -1,6 +1,4 @@
//! Constants for the pointer-sized unsigned integer type.
//!
//! *[See also the `usize` primitive type][usize].*
//! Redundant constants module for the [`usize` primitive type][usize].
//!
//! New code should use the associated constants directly on the primitive type.

View file

@ -705,14 +705,17 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog(self, base: Self) -> u32 {
assert!(base >= 2, "base of integer logarithm must be at least 2");
self.checked_ilog(base).expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog(base) {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the base 2 logarithm of the number, rounded down.
@ -728,13 +731,16 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog2(self) -> u32 {
self.checked_ilog2().expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog2() {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the base 10 logarithm of the number, rounded down.
@ -750,13 +756,16 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog10(self) -> u32 {
self.checked_ilog10().expect("argument of integer logarithm must be positive")
if let Some(log) = self.checked_ilog10() {
log
} else {
int_log10::panic_for_nonpositive_argument()
}
}
/// Returns the logarithm of the number with respect to an arbitrary base,

View file

@ -72,11 +72,6 @@ pub fn unsupported_err() -> crate::io::Error {
)
}
#[no_mangle]
pub extern "C" fn floor(x: f64) -> f64 {
unsafe { intrinsics::floorf64(x) }
}
pub fn abort_internal() -> ! {
unsafe {
abi::abort();

View file

@ -1,121 +1,59 @@
// run-pass
#![allow(unused_must_use)]
// ignore-emscripten FIXME(#45351) hits an LLVM assert
#![feature(repr_simd, platform_intrinsics, concat_idents, test)]
#![allow(non_camel_case_types)]
extern crate test;
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct i32x4(i32, i32, i32, i32);
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct i8x4(i8, i8, i8, i8);
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct u32x4(u32, u32, u32, u32);
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct u8x4(u8, u8, u8, u8);
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct f32x4(f32, f32, f32, f32);
#[repr(simd)]
#[derive(PartialEq, Debug)]
struct f64x4(f64, f64, f64, f64);
#![feature(repr_simd, platform_intrinsics)]
extern "platform-intrinsic" {
fn simd_cast<T, U>(x: T) -> U;
}
const A: i32 = -1234567;
const B: i32 = 12345678;
const C: i32 = -123456789;
const D: i32 = 1234567890;
use std::cmp::{max, min};
trait Foo {
fn is_float() -> bool { false }
fn in_range(x: i32) -> bool;
}
impl Foo for i32 {
fn in_range(_: i32) -> bool { true }
}
impl Foo for i8 {
fn in_range(x: i32) -> bool { -128 <= x && x < 128 }
}
impl Foo for u32 {
fn in_range(x: i32) -> bool { 0 <= x }
}
impl Foo for u8 {
fn in_range(x: i32) -> bool { 0 <= x && x < 128 }
}
impl Foo for f32 {
fn is_float() -> bool { true }
fn in_range(_: i32) -> bool { true }
}
impl Foo for f64 {
fn is_float() -> bool { true }
fn in_range(_: i32) -> bool { true }
}
#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 2]);
fn main() {
macro_rules! test {
($from: ident, $to: ident) => {{
// force the casts to actually happen, or else LLVM/rustc
// may fold them and get slightly different results.
let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from));
// the SIMD vectors are all FOOx4, so we can concat_idents
// so we don't have to pass in the extra args to the macro
let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d));
let mut to = concat_idents!($to, x4)(a as $to,
b as $to,
c as $to,
d as $to);
// assist type inference, it needs to know what `from` is
// for the `if` statements.
to == from;
// there are platform differences for some out of range
// casts, so we just normalize such things: it's OK for
// "invalid" calculations to result in nonsense answers.
// (e.g., negative float to unsigned integer goes through a
// library routine on the default i686 platforms, and the
// implementation of that routine differs on e.g., Linux
// vs. macOS, resulting in different answers.)
if $from::is_float() {
if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; }
if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; }
if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; }
if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; }
}
assert!(to == from,
"{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to),
from, to);
}}
}
macro_rules! tests {
(: $($to: ident),*) => { () };
// repeating the list twice is easier than writing a cartesian
// product macro
($from: ident $(, $from_: ident)*: $($to: ident),*) => {
fn $from() { unsafe { $( test!($from, $to); )* } }
tests!($($from_),*: $($to),*)
};
($($types: ident),*) => {{
tests!($($types),* : $($types),*);
$($types();)*
}}
unsafe {
let u = V::<u32>([i16::MIN as u32, i16::MAX as u32]);
let i: V<i16> = simd_cast(u);
assert_eq!(i.0[0], u.0[0] as i16);
assert_eq!(i.0[1], u.0[1] as i16);
}
// test various combinations, including truncation,
// signed/unsigned extension, and floating point casts.
tests!(i32, i8, u32, u8, f32);
tests!(i32, u32, f32, f64)
unsafe {
let f = V::<f32>([i16::MIN as f32, i16::MAX as f32]);
let i: V<i16> = simd_cast(f);
assert_eq!(i.0[0], f.0[0] as i16);
assert_eq!(i.0[1], f.0[1] as i16);
}
unsafe {
let f = V::<f32>([u8::MIN as f32, u8::MAX as f32]);
let u: V<u8> = simd_cast(f);
assert_eq!(u.0[0], f.0[0] as u8);
assert_eq!(u.0[1], f.0[1] as u8);
}
unsafe {
// We would like to do isize::MIN..=isize::MAX, but those values are not representable in
// an f64, so we clamp to the range of an i32 to prevent running into UB.
let f = V::<f64>([
max(isize::MIN, i32::MIN as isize) as f64,
min(isize::MAX, i32::MAX as isize) as f64,
]);
let i: V<isize> = simd_cast(f);
assert_eq!(i.0[0], f.0[0] as isize);
assert_eq!(i.0[1], f.0[1] as isize);
}
unsafe {
let f = V::<f64>([
max(usize::MIN, u32::MIN as usize) as f64,
min(usize::MAX, u32::MAX as usize) as f64,
]);
let u: V<usize> = simd_cast(f);
assert_eq!(u.0[0], f.0[0] as usize);
assert_eq!(u.0[1], f.0[1] as usize);
}
}

View file

@ -24,9 +24,9 @@ fn main() {
// reading from *const
unsafe {
let pointer = &x[0] as *const f32;
let pointer = x.as_ptr();
let pointers = x4(
pointer.offset(0) as *const f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@ -39,9 +39,9 @@ fn main() {
// reading from *mut
unsafe {
let pointer = &mut x[0] as *mut f32;
let pointer = x.as_mut_ptr();
let pointers = x4(
pointer.offset(0) as *mut f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@ -54,9 +54,9 @@ fn main() {
// writing to *mut
unsafe {
let pointer = &mut x[0] as *mut f32;
let pointer = x.as_mut_ptr();
let pointers = x4(
pointer.offset(0) as *mut f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@ -85,9 +85,9 @@ fn main() {
// reading from *const
unsafe {
let pointer = &y[0] as *const *const f32;
let pointer = y.as_ptr();
let pointers = x4(
pointer.offset(0) as *const *const f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@ -100,9 +100,9 @@ fn main() {
// reading from *mut
unsafe {
let pointer = &mut y[0] as *mut *const f32;
let pointer = y.as_mut_ptr();
let pointers = x4(
pointer.offset(0) as *mut *const f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@ -115,9 +115,9 @@ fn main() {
// writing to *mut
unsafe {
let pointer = &mut y[0] as *mut *const f32;
let pointer = y.as_mut_ptr();
let pointers = x4(
pointer.offset(0) as *mut *const f32,
pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)

View file

@ -17,13 +17,14 @@ extern "platform-intrinsic" {
fn main() {
let x: [usize; 4] = [10, 11, 12, 13];
let default = x4(0_usize, 1, 2, 3);
let mask = x4(1_i32, 1, 1, 1);
let all_set = u8::MAX as i8; // aka -1
let mask = x4(all_set, all_set, all_set, all_set);
let expected = x4(10_usize, 11, 12, 13);
unsafe {
let pointer = &x[0] as *const usize;
let pointer = x.as_ptr();
let pointers = x4(
pointer.offset(0) as *const usize,
pointer.offset(0),
pointer.offset(1),
pointer.offset(2),
pointer.offset(3)
@ -38,9 +39,9 @@ fn main() {
let expected = x4(10_isize, 11, 12, 13);
unsafe {
let pointer = &x[0] as *const isize;
let pointer = x.as_ptr();
let pointers = x4(
pointer.offset(0) as *const isize,
pointer.offset(0),
pointer.offset(1),
pointer.offset(2),
pointer.offset(3)