diff --git a/compiler/rustc_target/src/spec/base/wasm.rs b/compiler/rustc_target/src/spec/base/wasm.rs index 7ede45766ea59..1f0f564a77908 100644 --- a/compiler/rustc_target/src/spec/base/wasm.rs +++ b/compiler/rustc_target/src/spec/base/wasm.rs @@ -28,16 +28,6 @@ pub(crate) fn options() -> TargetOptions { // stack overflow will be guaranteed to trap as it underflows instead of // corrupting static data. concat!($prefix, "--stack-first"), - // FIXME we probably shouldn't pass this but instead pass an explicit list - // of symbols we'll allow to be undefined. We don't currently have a - // mechanism of knowing, however, which symbols are intended to be imported - // from the environment and which are intended to be imported from other - // objects linked elsewhere. This is a coarse approximation but is sure to - // hide some bugs and frustrate someone at some point, so we should ideally - // work towards a world where we can explicitly list symbols that are - // supposed to be imported and have all other symbols generate errors if - // they remain undefined. - concat!($prefix, "--allow-undefined"), // LLD only implements C++-like demangling, which doesn't match our own // mangling scheme. Tell LLD to not demangle anything and leave it up to // us to demangle these symbols later. Currently rustc does not perform diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ae16a8401552d..2c87d47246498 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -695,6 +695,15 @@ impl Box { /// does the same as [Box::into_pin]\([Box::new_in]\(x, alloc)). Consider using /// [`into_pin`](Box::into_pin) if you already have a `Box`, or if you want to /// construct a (pinned) `Box` in a different way than with [`Box::new_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::alloc::System; + /// + /// let x = Box::pin_in(1, System); + /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index d46b1972b5b00..34de563fe4f33 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -549,8 +549,8 @@ impl BinaryHeap { /// /// use std::alloc::System; /// use std::collections::BinaryHeap; - /// let mut heap = BinaryHeap::new_in(System); - /// heap.push(4); + /// + /// let heap : BinaryHeap = BinaryHeap::new_in(System); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] @@ -573,8 +573,8 @@ impl BinaryHeap { /// /// use std::alloc::System; /// use std::collections::BinaryHeap; - /// let mut heap = BinaryHeap::with_capacity_in(10, System); - /// heap.push(4); + /// + /// let heap: BinaryHeap = BinaryHeap::with_capacity_in(10, System); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e3a6e90566f5e..8094356910f8c 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -684,13 +684,11 @@ impl BTreeMap { /// ``` /// # #![feature(allocator_api)] /// # #![feature(btreemap_alloc)] + /// /// use std::collections::BTreeMap; /// use std::alloc::Global; /// - /// let mut map = BTreeMap::new_in(Global); - /// - /// // entries can now be inserted into the empty map - /// map.insert(1, "a"); + /// let map: BTreeMap = BTreeMap::new_in(Global); /// ``` #[unstable(feature = "btreemap_alloc", issue = "32838")] #[must_use] diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index db8007834432c..2a483b3d3982e 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -355,10 +355,11 @@ impl BTreeSet { /// # #![allow(unused_mut)] /// # #![feature(allocator_api)] /// # #![feature(btreemap_alloc)] + /// /// use std::collections::BTreeSet; /// use std::alloc::Global; /// - /// let mut set: BTreeSet = BTreeSet::new_in(Global); + /// let set: BTreeSet = BTreeSet::new_in(Global); /// ``` #[unstable(feature = "btreemap_alloc", issue = "32838")] #[must_use] diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1816349e45f4f..ca3b2eab30402 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -509,7 +509,7 @@ impl LinkedList { /// use std::alloc::System; /// use std::collections::LinkedList; /// - /// let list: LinkedList = LinkedList::new_in(System); + /// let list: LinkedList = LinkedList::new_in(System); /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 3185fd56d8c08..43a6df7ddf753 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -790,7 +790,7 @@ impl VecDeque { /// ``` /// use std::collections::VecDeque; /// - /// let deque: VecDeque = VecDeque::with_capacity(10); + /// let deque: VecDeque = VecDeque::with_capacity(10); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -830,9 +830,12 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(allocator_api)] + /// /// use std::collections::VecDeque; + /// use std::alloc::Global; /// - /// let deque: VecDeque = VecDeque::new(); + /// let deque: VecDeque = VecDeque::new_in(Global); /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] @@ -845,9 +848,12 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(allocator_api)] + /// /// use std::collections::VecDeque; + /// use std::alloc::Global; /// - /// let deque: VecDeque = VecDeque::with_capacity(10); + /// let deque: VecDeque = VecDeque::with_capacity_in(10, Global); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index cfca2d9ec970e..cbb801bd6d736 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -737,6 +737,7 @@ impl Rc { /// /// ``` /// #![feature(allocator_api)] + /// /// use std::rc::Rc; /// use std::alloc::System; /// diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 35eb7549738df..a4c4c19682195 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -130,20 +130,25 @@ where A: Allocator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let peek = if self.idx < self.end { - // This has to use pointer arithmetic as `self.vec[self.idx]` or - // `self.vec.get_unchecked(self.idx)` wouldn't work since we - // temporarily set the length of `self.vec` to zero. - // - // SAFETY: - // Since `self.idx` is smaller than `self.end` and `self.end` is - // smaller than `self.old_len`, `idx` is valid for indexing the - // buffer. Also, per the invariant of `self.idx`, this element - // has not been inspected/moved out yet. - Some(unsafe { &*self.vec.as_ptr().add(self.idx) }) - } else { - None - }; - f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive() + // We have to use pointer arithmetics here, + // because the length of `self.vec` is temporarily set to 0. + let start = self.vec.as_ptr(); + + // SAFETY: we always keep first `self.idx - self.del` elements valid. + let retained = unsafe { slice::from_raw_parts(start, self.idx - self.del) }; + + // SAFETY: we have not yet touched elements starting at `self.idx`. + let valid_tail = + unsafe { slice::from_raw_parts(start.add(self.idx), self.old_len - self.idx) }; + + // SAFETY: `end - idx <= old_len - idx`, because `end <= old_len`. Also `idx <= end` by invariant. + let (remainder, skipped_tail) = + unsafe { valid_tail.split_at_unchecked(self.end - self.idx) }; + + f.debug_struct("ExtractIf") + .field("retained", &retained) + .field("remainder", &remainder) + .field("skipped_tail", &skipped_tail) + .finish_non_exhaustive() } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 942b2b9d2dadf..5a0f6d3dc571c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1062,8 +1062,7 @@ impl Vec { /// /// use std::alloc::System; /// - /// # #[allow(unused_mut)] - /// let mut vec: Vec = Vec::new_in(System); + /// let vec: Vec = Vec::new_in(System); /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs index db7da0db47d74..d85d2e44cd2ba 100644 --- a/library/alloctests/tests/vec.rs +++ b/library/alloctests/tests/vec.rs @@ -1651,13 +1651,17 @@ fn extract_if_unconsumed() { #[test] fn extract_if_debug() { - let mut vec = vec![1, 2]; - let mut drain = vec.extract_if(.., |&mut x| x % 2 != 0); - assert!(format!("{drain:?}").contains("Some(1)")); - drain.next(); - assert!(format!("{drain:?}").contains("Some(2)")); - drain.next(); - assert!(format!("{drain:?}").contains("None")); + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let mut drain = vec.extract_if(1..5, |&mut x| x % 2 != 0); + assert_eq!( + format!("{drain:?}"), + "ExtractIf { retained: [1], remainder: [2, 3, 4, 5], skipped_tail: [6, 7, 8], .. }" + ); + drain.next().unwrap(); + assert_eq!( + format!("{drain:?}"), + "ExtractIf { retained: [1, 2], remainder: [4, 5], skipped_tail: [6, 7, 8], .. }" + ); } #[test] diff --git a/library/coretests/tests/num/floats.rs b/library/coretests/tests/num/floats.rs index d87f850944503..a388e75469c8c 100644 --- a/library/coretests/tests/num/floats.rs +++ b/library/coretests/tests/num/floats.rs @@ -2,6 +2,9 @@ use std::hint::black_box; use std::num::FpCategory as Fp; use std::ops::{Add, Div, Mul, Rem, Sub}; +/// i586 has issues with floating point precision. +const I586: bool = cfg!(target_arch = "x86") && cfg!(not(target_feature = "sse2")); + pub(crate) trait TestableFloat: Sized { const BITS: u32; /// Unsigned int with the same size, for converting to/from bits. @@ -59,6 +62,7 @@ pub(crate) trait TestableFloat: Sized { const NEG_MUL_ADD_RESULT: Self; /// Reciprocal of the maximum val const MAX_RECIP: Self; + const ASINH_ACOSH_MAX: Self; } impl TestableFloat for f16 { @@ -103,6 +107,7 @@ impl TestableFloat for f16 { const MUL_ADD_RESULT: Self = 62.031; const NEG_MUL_ADD_RESULT: Self = 48.625; const MAX_RECIP: Self = 1.526624e-5; + const ASINH_ACOSH_MAX: Self = 11.781; } impl TestableFloat for f32 { @@ -120,8 +125,20 @@ impl TestableFloat for f32 { const LOG_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; const LOG2_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; const LOG10_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; - const ASINH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; - const ACOSH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; + const ASINH_APPROX: Self = if cfg!(miri) { + 1e-3 + } else if I586 { + 1e-5 + } else { + Self::APPROX + }; + const ACOSH_APPROX: Self = if cfg!(miri) { + 1e-3 + } else if I586 { + 1e-5 + } else { + Self::APPROX + }; const ATANH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; const GAMMA_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX }; const GAMMA_APPROX_LOOSE: Self = if cfg!(miri) { 1e-2 } else { 1e-4 }; @@ -149,6 +166,7 @@ impl TestableFloat for f32 { const MUL_ADD_RESULT: Self = 62.05; const NEG_MUL_ADD_RESULT: Self = 48.65; const MAX_RECIP: Self = 2.938736e-39; + const ASINH_ACOSH_MAX: Self = 89.4159851; } impl TestableFloat for f64 { @@ -180,6 +198,7 @@ impl TestableFloat for f64 { const MUL_ADD_RESULT: Self = 62.050000000000004; const NEG_MUL_ADD_RESULT: Self = 48.650000000000006; const MAX_RECIP: Self = 5.562684646268003e-309; + const ASINH_ACOSH_MAX: Self = 710.47586007394398; } impl TestableFloat for f128 { @@ -221,6 +240,7 @@ impl TestableFloat for f128 { const MUL_ADD_RESULT: Self = 62.0500000000000000000000000000000037; const NEG_MUL_ADD_RESULT: Self = 48.6500000000000000000000000000000049; const MAX_RECIP: Self = 8.40525785778023376565669454330438228902076605e-4933; + const ASINH_ACOSH_MAX: Self = 11357.216553474703894801348310092223; } /// Determine the tolerance for values of the argument type. @@ -1705,6 +1725,9 @@ float_test! { assert_approx_eq!(flt(-200.0).asinh(), -5.991470797049389, Float::ASINH_APPROX); + // issue 153878: large values were rounding to infinity + assert_approx_eq!(Float::MAX.asinh(), Float::ASINH_ACOSH_MAX, Float::ASINH_APPROX); + #[allow(overflowing_literals)] if Float::MAX > flt(66000.0) { // regression test for the catastrophic cancellation fixed in 72486 @@ -1733,6 +1756,9 @@ float_test! { assert_approx_eq!(flt(2.0).acosh(), 1.31695789692481670862504634730796844, Float::ACOSH_APPROX); assert_approx_eq!(flt(3.0).acosh(), 1.76274717403908605046521864995958461, Float::ACOSH_APPROX); + // issue 153878: large values were rounding to infinity + assert_approx_eq!(Float::MAX.acosh(), Float::ASINH_ACOSH_MAX, Float::ACOSH_APPROX); + #[allow(overflowing_literals)] if Float::MAX > flt(66000.0) { // test for low accuracy from issue 104548 diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index fe49660325e65..4192254f6c824 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -301,8 +301,11 @@ impl HashMap { /// # Examples /// /// ``` + /// # #![feature(allocator_api)] /// use std::collections::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::new(); + /// use std::alloc::Global; + /// + /// let map: HashMap = HashMap::new_in(Global); /// ``` #[inline] #[must_use] @@ -321,8 +324,11 @@ impl HashMap { /// # Examples /// /// ``` + /// # #![feature(allocator_api)] /// use std::collections::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10); + /// use std::alloc::Global; + /// + /// let map: HashMap = HashMap::with_capacity_in(10, Global); /// ``` #[inline] #[must_use] @@ -410,6 +416,18 @@ impl HashMap { /// /// The `hash_builder` passed should implement the [`BuildHasher`] trait for /// the `HashMap` to be useful, see its documentation for details. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::alloc::Global; + /// use std::collections::HashMap; + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// let map: HashMap = HashMap::with_hasher_in(s, Global); + /// ``` #[inline] #[must_use] #[unstable(feature = "allocator_api", issue = "32838")] @@ -432,6 +450,17 @@ impl HashMap { /// The `hasher` passed should implement the [`BuildHasher`] trait for /// the `HashMap` to be useful, see its documentation for details. /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::alloc::Global; + /// use std::collections::HashMap; + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// let map: HashMap = HashMap::with_capacity_and_hasher_in(10, s, Global); + /// ``` #[inline] #[must_use] #[unstable(feature = "allocator_api", issue = "32838")] diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 0fe26848fe7bb..fadd62652c62d 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -176,6 +176,15 @@ impl HashSet { /// /// The hash set is initially created with a capacity of 0, so it will not allocate until it /// is first inserted into. + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// use std::alloc::Global; + /// use std::collections::HashSet; + /// + /// let set: HashSet = HashSet::new_in(Global); + /// ``` #[inline] #[must_use] #[unstable(feature = "allocator_api", issue = "32838")] @@ -192,9 +201,11 @@ impl HashSet { /// # Examples /// /// ``` + /// # #![feature(allocator_api)] /// use std::collections::HashSet; - /// let set: HashSet = HashSet::with_capacity(10); - /// assert!(set.capacity() >= 10); + /// use std::alloc::Global; + /// + /// let set: HashSet = HashSet::with_capacity_in(10, Global); /// ``` #[inline] #[must_use] @@ -282,6 +293,18 @@ impl HashSet { /// /// The `hash_builder` passed should implement the [`BuildHasher`] trait for /// the `HashSet` to be useful, see its documentation for details. + /// + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// use std::alloc::Global; + /// use std::collections::HashSet; + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// let set: HashSet = HashSet::with_hasher_in(s, Global); + /// ``` #[inline] #[must_use] #[unstable(feature = "allocator_api", issue = "32838")] @@ -303,6 +326,18 @@ impl HashSet { /// /// The `hash_builder` passed should implement the [`BuildHasher`] trait for /// the `HashSet` to be useful, see its documentation for details. + /// + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// use std::alloc::Global; + /// use std::collections::HashSet; + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// let set: HashSet = HashSet::with_capacity_and_hasher_in(10, s, Global); + /// ``` #[inline] #[must_use] #[unstable(feature = "allocator_api", issue = "32838")] diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index 8214ad381f1f7..cae14e34e73e7 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -189,11 +189,6 @@ impl ToSocketAddrs for (Ipv6Addr, u16) { } } -fn lookup_host(host: &str, port: u16) -> io::Result> { - let addrs = crate::sys::net::lookup_host(host, port)?; - Ok(Vec::from_iter(addrs).into_iter()) -} - #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (&str, u16) { type Iter = vec::IntoIter; @@ -207,7 +202,7 @@ impl ToSocketAddrs for (&str, u16) { } // Otherwise, make the system look it up. - lookup_host(host, port) + crate::sys::net::lookup_host(host, port).map(|addrs| Vec::from_iter(addrs).into_iter()) } } @@ -229,16 +224,8 @@ impl ToSocketAddrs for str { return Ok(vec![addr].into_iter()); } - // Otherwise, split the string by ':' and convert the second part to u16... - let Some((host, port_str)) = self.rsplit_once(':') else { - return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid socket address")); - }; - let Ok(port) = port_str.parse::() else { - return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid port value")); - }; - - // ... and make the system look up the host. - lookup_host(host, port) + // Otherwise, make the system look it up. + crate::sys::net::lookup_host_string(self).map(|addrs| Vec::from_iter(addrs).into_iter()) } } diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs index 2c8898a6aa86a..d7c7a82674bf0 100644 --- a/library/std/src/num/f128.rs +++ b/library/std/src/num/f128.rs @@ -867,9 +867,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asinh(self) -> f128 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinhf128(self) } /// Inverse hyperbolic cosine function. @@ -900,11 +898,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acosh(self) -> f128 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acoshf128(self) } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs index 7ca266c8a5f60..ef610eacb05d7 100644 --- a/library/std/src/num/f16.rs +++ b/library/std/src/num/f16.rs @@ -832,9 +832,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asinh(self) -> f16 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinhf(self as f32) as f16 } /// Inverse hyperbolic cosine function. @@ -865,11 +863,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acosh(self) -> f16 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acoshf(self as f32) as f16 } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index 77e6824784605..771a0cae6dcd8 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -1091,9 +1091,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinhf(self) } /// Inverse hyperbolic cosine function. @@ -1119,11 +1117,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acoshf(self) } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index e0b9948a924db..59ef39a382b27 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -1091,9 +1091,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinh(self) } /// Inverse hyperbolic cosine function. @@ -1119,11 +1117,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acosh(self) } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index c01ee17eecda3..4cfd9d19df74a 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -16,7 +16,7 @@ use crate::sys::sync as sys; /// /// In comparison, a [`Mutex`] does not distinguish between readers or writers /// that acquire the lock, therefore blocking any threads waiting for the lock to -/// become available. An `RwLock` will allow any number of readers to acquire the +/// become available. An `RwLock` will allow multiple readers to acquire the /// lock as long as a writer is not holding the lock. /// /// The priority policy of the lock is dependent on the underlying operating diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 1592218ead8b0..2104087141d1a 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -4,7 +4,9 @@ // or by `compiler-builtins` on unsupported platforms. unsafe extern "C" { pub safe fn acos(n: f64) -> f64; + pub safe fn acosh(n: f64) -> f64; pub safe fn asin(n: f64) -> f64; + pub safe fn asinh(n: f64) -> f64; pub safe fn atan(n: f64) -> f64; pub safe fn atan2(a: f64, b: f64) -> f64; pub safe fn cosh(n: f64) -> f64; @@ -30,7 +32,9 @@ unsafe extern "C" { pub safe fn erfcf(n: f32) -> f32; pub safe fn acosf128(n: f128) -> f128; + pub safe fn acoshf128(n: f128) -> f128; pub safe fn asinf128(n: f128) -> f128; + pub safe fn asinhf128(n: f128) -> f128; pub safe fn atanf128(n: f128) -> f128; pub safe fn atan2f128(a: f128, b: f128) -> f128; pub safe fn cbrtf128(n: f128) -> f128; @@ -57,6 +61,16 @@ cfg_select! { f64::acos(n as f64) as f32 } + #[inline] + pub fn acoshf(n: f32) -> f32 { + f64::acosh(n as f64) as f32 + } + + #[inline] + pub fn asinhf(n: f32) -> f32 { + f64::asinh(n as f64) as f32 + } + #[inline] pub fn asinf(n: f32) -> f32 { f64::asin(n as f64) as f32 @@ -95,7 +109,9 @@ cfg_select! { _ => { unsafe extern "C" { pub safe fn acosf(n: f32) -> f32; + pub safe fn acoshf(n: f32) -> f32; pub safe fn asinf(n: f32) -> f32; + pub safe fn asinhf(n: f32) -> f32; pub safe fn atan2f(a: f32, b: f32) -> f32; pub safe fn atanf(n: f32) -> f32; pub safe fn coshf(n: f32) -> f32; diff --git a/library/std/src/sys/net/connection/mod.rs b/library/std/src/sys/net/connection/mod.rs index 2f064914a8317..84b53fd375c93 100644 --- a/library/std/src/sys/net/connection/mod.rs +++ b/library/std/src/sys/net/connection/mod.rs @@ -59,3 +59,22 @@ where None => Err(Error::NO_ADDRESSES), } } + +// Default implementation, may be overridden by platform-specific implementations. +#[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))] +pub(crate) fn lookup_host_string( + addr: &str, +) -> crate::io::Result> { + use crate::io; + + // Split the string by ':' and convert the second part to u16... + let Some((host, port_str)) = addr.rsplit_once(':') else { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid socket address")); + }; + let Ok(port) = port_str.parse::() else { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid port value")); + }; + + // ... and make the system look up the host. + crate::sys::net::lookup_host(host, port) +} diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs index 6a625664494b5..5735a5db488fb 100644 --- a/library/std/src/sys/net/connection/sgx.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -506,9 +506,23 @@ impl Iterator for LookupHost { } } +pub(crate) fn lookup_host_string(addr: impl Into) -> io::Result { + Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host: addr.into() })) +} + pub fn lookup_host(host: &str, port: u16) -> io::Result { - Err(io::Error::new( - io::ErrorKind::Uncategorized, - NonIpSockAddr { host: format!("{host}:{port}") }, - )) + lookup_host_string(format!("{host}:{port}")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn unparseable_sockaddr() { + let addr = "local"; + let error = addr.to_socket_addrs().unwrap_err(); + let non_ip_addr = error.downcast::().unwrap(); + assert_eq!(addr, non_ip_addr.host); + } } diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index 6b919bde80bb5..6de5577504c43 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -18,7 +18,7 @@ impl RwLock { pub fn read(&self) { let m = self.mode.get(); if m >= 0 { - self.mode.set(m + 1); + self.mode.set(m.checked_add(1).expect("rwlock overflowed read locks")); } else { rtabort!("rwlock locked for writing"); } @@ -28,6 +28,9 @@ impl RwLock { pub fn try_read(&self) -> bool { let m = self.mode.get(); if m >= 0 { + if m == isize::MAX { + return false; + } self.mode.set(m + 1); true } else { @@ -56,16 +59,19 @@ impl RwLock { #[inline] pub unsafe fn read_unlock(&self) { - self.mode.set(self.mode.get() - 1); + assert!( + self.mode.replace(self.mode.get() - 1) > 0, + "rwlock has not been locked for reading" + ); } #[inline] pub unsafe fn write_unlock(&self) { - assert_eq!(self.mode.replace(0), -1); + assert_eq!(self.mode.replace(0), -1, "rwlock has not been locked for writing"); } #[inline] pub unsafe fn downgrade(&self) { - assert_eq!(self.mode.replace(1), -1); + assert_eq!(self.mode.replace(1), -1, "rwlock has not been locked for writing"); } } diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs index 392c45c8ba05d..d6287305481ea 100644 --- a/library/std/tests/sync/rwlock.rs +++ b/library/std/tests/sync/rwlock.rs @@ -7,7 +7,7 @@ use std::sync::{ Arc, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, }; -use std::{hint, mem, thread}; +use std::{hint, mem, thread, u32}; use rand::Rng; @@ -883,3 +883,66 @@ fn test_rwlock_with_mut() { assert_eq!(*rwlock.read(), 5); assert_eq!(result, 10); } + +// To note: there are (currently) four different implementations of Rwlock: +// - On Windows (but not Win 7), Linux, Android, FreeBSD, OpenBSD, DragonFly, +// Fuchsia, WASM, Hermit, and Motor OSs, it relies on rwlock/futex.rs, which has +// a max reader of 1 << 30 - 2 (or 1073741822). A "too many active reader" error +// is displayed after it exceeds the max number of readers. +// - On Unix, Win 7, Fortranix (target env of sgx), Xous, and TeeOS, it leans +// on rwlock/queue.rs, which uses a linked list under the hood stored on the stack +// to hold a queue of waiters. Assuming no stack overflow, the max number of readers +// that can be queued up at one time is limited to usize::MAX - (1 << 4) as the first +// four bits are reserved for LOCKED, QUEUED, QUEUE_LOCKED, and DOWNGRADED flags. Any +// pending readers after that max count, parks the thread and tries to acquire a read lock +// again when the thread wakes up. +// - On SolidASP3, it leans on rwlock/solid.rs, which utilizes rwl_loc_rdl, so the max +// number of readers depends on the internal implementation of rwl_loc_rdl. +// - Every other platforms utilizes rwlock/no_threads.rs, which has a max reader of +// isize::MAX. An arithmetic overflow error occurs if it exceeds the max reader count. +#[test] +fn test_rwlock_max_readers() { + let mut read_lock_ctr: u32 = 0; + let rwlock: RwLock = RwLock::new(0); + + const MAX_READERS: u32 = cfg_select! { + miri => 100, + any( + all(target_os = "windows", not(target_vendor = "win7")), + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "fuchsia", + all(target_family = "wasm", target_feature = "atomics"), + target_os = "hermit", + target_os = "motor", + ) => { + (1 << 30) - 2 + }, + any( + target_family = "unix", + all(target_os = "windows", target_vendor = "win7"), + all(target_vendor = "fortanix", target_env = "sgx"), + target_os = "xous", + target_os = "teeos", + ) => { + u32::MAX + }, + target_os = "solid_asp3" => { + (1 << 30) + }, + _ => { + u32::MAX + } + }; + + while read_lock_ctr < MAX_READERS { + let lock = rwlock.read(); + mem::forget(lock); + read_lock_ctr += 1; + } + + assert_eq!(read_lock_ctr, MAX_READERS); +} diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 85a76054a12dd..e8343b2e21c81 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2799,6 +2799,8 @@ class DocSearch { result_list.sort((aaa, bbb) => { const aai = aaa.item; const bbi = bbb.item; + const ap = aai.modulePath !== undefined ? aai.modulePath : ""; + const bp = bbi.modulePath !== undefined ? bbi.modulePath : ""; /** @type {number} */ let a; /** @type {number} */ @@ -2829,14 +2831,25 @@ class DocSearch { if (a !== b) { return a - b; } - } - // Sort by distance in the path part, if specified - // (less changes required to match means higher rankings) - a = Number(aaa.path_dist); - b = Number(bbb.path_dist); - if (a !== b) { - return a - b; + if (parsedQuery.elems[0] && + parsedQuery.elems[0].pathWithoutLast.length !== 0 + ) { + // Sort by distance in the path part, if specified + // (less changes required to match means higher rankings) + a = Number(aaa.path_dist); + b = Number(bbb.path_dist); + if (a !== b) { + return a - b; + } + + // sort by path (longer goes later) + a = ap.length + (aai.parent ? aai.parent.name.length + 2 : 0); + b = bp.length + (bbi.parent ? bbi.parent.name.length + 2 : 0); + if (a !== b) { + return a - b; + } + } } // (later literal occurrence, if any, goes later) @@ -2890,8 +2903,8 @@ class DocSearch { } // sort by item name (lexicographically larger goes later) - let aw = aai.normalizedName; - let bw = bbi.normalizedName; + const aw = aai.normalizedName; + const bw = bbi.normalizedName; if (aw !== bw) { return (aw > bw ? +1 : -1); } @@ -2914,12 +2927,8 @@ class DocSearch { } // sort by path (lexicographically larger goes later) - const ap = aai.modulePath; - const bp = bbi.modulePath; - aw = ap === undefined ? "" : ap; - bw = bp === undefined ? "" : bp; - if (aw !== bw) { - return (aw > bw ? +1 : -1); + if (ap !== bp) { + return (ap > bp ? +1 : -1); } // que sera, sera @@ -3848,13 +3857,19 @@ class DocSearch { let dist_total = 0; for (let x = 0; x < clength; ++x) { const [p, c] = [path[i + x], contains[x]]; + const indexOf = p.indexOf(c); if (parsedQuery.literalSearch && p !== c) { continue pathiter; - } else if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance && - p.indexOf(c) !== -1 - ) { + } else if (indexOf !== -1) { // discount distance on substring match - dist_total += Math.floor((p.length - c.length) / 3); + // if component is surrounded by underscores or edges, + // count the distance as zero + if ( + (indexOf !== 0 && p[indexOf - 1] !== "_") || + (indexOf + c.length !== p.length && p[indexOf + c.length] !== "_") + ) { + dist_total += Math.floor((p.length - c.length) / 3); + } } else { const dist = editDistance(p, c, maxPathEditDistance); if (dist > maxPathEditDistance) { diff --git a/src/tools/miri/src/shims/math.rs b/src/tools/miri/src/shims/math.rs index 1da7fbbdac0ce..479e129579b2b 100644 --- a/src/tools/miri/src/shims/math.rs +++ b/src/tools/miri/src/shims/math.rs @@ -30,6 +30,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | "acosf" | "asinf" | "atanf" + | "acoshf" + | "asinhf" | "log1pf" | "expm1f" | "tgammaf" @@ -52,6 +54,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "acosf" => f_host.acos(), "asinf" => f_host.asin(), "atanf" => f_host.atan(), + "acoshf" => f_host.acosh(), + "asinhf" => f_host.asinh(), "log1pf" => f_host.ln_1p(), "expm1f" => f_host.exp_m1(), "tgammaf" => f_host.gamma(), @@ -113,6 +117,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | "acos" | "asin" | "atan" + | "acosh" + | "asinh" | "log1p" | "expm1" | "tgamma" @@ -135,6 +141,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "acos" => f_host.acos(), "asin" => f_host.asin(), "atan" => f_host.atan(), + "acosh" => f_host.acosh(), + "asinh" => f_host.asinh(), "log1p" => f_host.ln_1p(), "expm1" => f_host.exp_m1(), "tgamma" => f_host.gamma(), diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index e5454905bb525..8961693f32393 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1611,9 +1611,9 @@ fn test_non_determinism() { check_nondet(|| 1.0f32.sinh()); check_nondet(|| 1.0f32.cosh()); check_nondet(|| 1.0f32.tanh()); + check_nondet(|| 1.0f32.asinh()); + check_nondet(|| 2.0f32.acosh()); } - check_nondet(|| 1.0f32.asinh()); - check_nondet(|| 2.0f32.acosh()); check_nondet(|| 0.5f32.atanh()); check_nondet(|| 5.0f32.gamma()); check_nondet(|| 5.0f32.ln_gamma()); diff --git a/tests/run-make/wasm-stringify-ints-small/foo.rs b/tests/run-make/wasm-stringify-ints-small/foo.rs index 7a947f013ad48..50ced86f3bc24 100644 --- a/tests/run-make/wasm-stringify-ints-small/foo.rs +++ b/tests/run-make/wasm-stringify-ints-small/foo.rs @@ -1,5 +1,6 @@ #![crate_type = "cdylib"] +#[link(wasm_import_module = "the-world")] extern "C" { fn observe(ptr: *const u8, len: usize); } @@ -7,6 +8,7 @@ extern "C" { macro_rules! s { ( $( $f:ident -> $t:ty );* $(;)* ) => { $( + #[link(wasm_import_module = "the-world")] extern "C" { fn $f() -> $t; } diff --git a/tests/run-make/wasm-unexpected-features/foo.rs b/tests/run-make/wasm-unexpected-features/foo.rs index 20c7bc0839ec4..40b61fcc6e284 100644 --- a/tests/run-make/wasm-unexpected-features/foo.rs +++ b/tests/run-make/wasm-unexpected-features/foo.rs @@ -17,6 +17,11 @@ unsafe extern "Rust" { fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } +#[rustc_std_internal_symbol] +pub unsafe fn __rdl_alloc_error_handler(_size: usize, _align: usize) -> ! { + loop {} +} + #[used] static mut BUF: [u8; 1024] = [0; 1024]; diff --git a/tests/rustdoc-js-std/path-maxeditdistance.js b/tests/rustdoc-js-std/path-maxeditdistance.js index b22a506eee5fa..96d58d239865c 100644 --- a/tests/rustdoc-js-std/path-maxeditdistance.js +++ b/tests/rustdoc-js-std/path-maxeditdistance.js @@ -10,15 +10,24 @@ const EXPECTED = [ query: 'vec::iter', others: [ // std::net::ToSocketAttrs::iter should not show up here + { 'path': 'std::collections::vec_deque', 'name': 'Iter' }, { 'path': 'std::collections::VecDeque', 'name': 'iter' }, + { 'path': 'std::collections::vec_deque', 'name': 'IterMut' }, { 'path': 'std::collections::VecDeque', 'name': 'iter_mut' }, - { 'path': 'std::vec::Vec', 'name': 'from_iter' }, { 'path': 'std::vec', 'name': 'IntoIter' }, + { 'path': 'std::vec::Vec', 'name': 'from_iter' }, { 'path': 'std::vec::Vec', 'name': 'into_iter' }, - { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, { 'path': 'std::vec::Drain', 'name': 'into_iter' }, - { 'path': 'std::vec::IntoIter', 'name': 'into_iter' }, { 'path': 'std::vec::Splice', 'name': 'into_iter' }, + { 'path': 'std::vec::IntoIter', 'name': 'into_iter' }, + { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque', 'name': 'IntoIter' }, + { 'path': 'std::collections::vec_deque::Iter', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque::Drain', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque::Splice', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque::IterMut', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque::IntoIter', 'name': 'into_iter' }, + { 'path': 'std::collections::vec_deque::ExtractIf', 'name': 'into_iter' }, { 'path': 'std::collections::VecDeque', 'name': 'from_iter' }, { 'path': 'std::collections::VecDeque', 'name': 'into_iter' }, ], diff --git a/tests/rustdoc-js/path-substring.js b/tests/rustdoc-js/path-substring.js new file mode 100644 index 0000000000000..86529e4f100c9 --- /dev/null +++ b/tests/rustdoc-js/path-substring.js @@ -0,0 +1,75 @@ +// exact-check +// ignore-tidy-linelength +const EXPECTED = [ + // should match (substring) + { + 'query': 'struct:now::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + { + 'query': 'struct:is::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + { + 'query': 'struct:is_the::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + { + 'query': 'struct:the::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + { + 'query': 'struct:their::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + // should not match + { + 'query': 'struct:ood::Country', + 'others': [], + }, + { + 'query': 'struct:goo::Country', + 'others': [], + }, + { + 'query': 'struct:he::Country', + 'others': [], + }, + { + 'query': 'struct:heir::Country', + 'others': [], + }, + { + 'query': 'struct:hei::Country', + 'others': [], + }, + { + 'query': 'struct:no::Country', + 'others': [], + }, + // should match (edit distance) + { + 'query': 'struct:nowisthetimeforallgoodmentocometotheaidoftheir::Country', + 'others': [ + { 'path': 'x::nowisthetimeforallgoodmentocometotheaidoftheir', 'name': 'Country' }, + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + ], + }, + { + 'query': 'struct:now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their::Country', + 'others': [ + { 'path': 'x::now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their', 'name': 'Country' }, + { 'path': 'x::nowisthetimeforallgoodmentocometotheaidoftheir', 'name': 'Country' }, + ], + }, +]; diff --git a/tests/rustdoc-js/path-substring.rs b/tests/rustdoc-js/path-substring.rs new file mode 100644 index 0000000000000..0d093d84c1c97 --- /dev/null +++ b/tests/rustdoc-js/path-substring.rs @@ -0,0 +1,7 @@ +#![crate_name = "x"] +pub mod now_is_the_time_for_all_good_men_to_come_to_the_aid_of_their { + pub struct Country; +} +pub mod nowisthetimeforallgoodmentocometotheaidoftheir { + pub struct Country; +} diff --git a/tests/ui/linking/executable-no-mangle-strip.rs b/tests/ui/linking/executable-no-mangle-strip.rs index cc283dc53ee3a..240c16af67bdb 100644 --- a/tests/ui/linking/executable-no-mangle-strip.rs +++ b/tests/ui/linking/executable-no-mangle-strip.rs @@ -1,5 +1,6 @@ //@ run-pass //@ ignore-windows-gnu: only statics marked with used can be GC-ed on windows-gnu +//@ ignore-wasm: wasm, for better or worse, exports all #[no_mangle] // Regression test for . // Functions in the binary marked with no_mangle should be GC-ed if they