Skip to content

Commit e95db59

Browse files
committed
Auto merge of #146026 - Zalathar:rollup-urbmv0t, r=Zalathar
Rollup of 5 pull requests Successful merges: - #143462 (fix(lib-std-fs): handle `usize` overflow in `read*`) - #144651 (Implementation: `#[feature(nonpoison_condvar)]`) - #145465 (Stabilize `array_repeat` feature) - #145776 (Optimize `.ilog({2,10})` to `.ilog{2,10}()`) - #145969 (Add Duration::from_nanos_u128) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 846e377 + f655e6a commit e95db59

File tree

19 files changed

+844
-278
lines changed

19 files changed

+844
-278
lines changed

library/core/src/array/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,14 @@ pub use iter::IntoIter;
4141
///
4242
/// Creating multiple copies of a `String`:
4343
/// ```rust
44-
/// #![feature(array_repeat)]
45-
///
4644
/// use std::array;
4745
///
4846
/// let string = "Hello there!".to_string();
4947
/// let strings = array::repeat(string);
5048
/// assert_eq!(strings, ["Hello there!", "Hello there!"]);
5149
/// ```
5250
#[inline]
53-
#[unstable(feature = "array_repeat", issue = "126695")]
51+
#[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")]
5452
pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
5553
from_trusted_iterator(repeat_n(val, N))
5654
}

library/core/src/num/uint_macros.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,20 @@ macro_rules! uint_impl {
14911491
without modifying the original"]
14921492
#[inline]
14931493
pub const fn checked_ilog(self, base: Self) -> Option<u32> {
1494+
// Inform compiler of optimizations when the base is known at
1495+
// compile time and there's a cheaper method available.
1496+
//
1497+
// Note: Like all optimizations, this is not guaranteed to be
1498+
// applied by the compiler. If you want those specific bases,
1499+
// use `.checked_ilog2()` or `.checked_ilog10()` directly.
1500+
if core::intrinsics::is_val_statically_known(base) {
1501+
if base == 2 {
1502+
return self.checked_ilog2();
1503+
} else if base == 10 {
1504+
return self.checked_ilog10();
1505+
}
1506+
}
1507+
14941508
if self <= 0 || base <= 1 {
14951509
None
14961510
} else if self < base {

library/core/src/time.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,42 @@ impl Duration {
308308
Duration { secs, nanos: subsec_nanos }
309309
}
310310

311+
/// Creates a new `Duration` from the specified number of nanoseconds.
312+
///
313+
/// # Panics
314+
///
315+
/// Panics if the given number of nanoseconds is greater than [`Duration::MAX`].
316+
///
317+
/// # Examples
318+
///
319+
/// ```
320+
/// #![feature(duration_from_nanos_u128)]
321+
/// use std::time::Duration;
322+
///
323+
/// let nanos = 10_u128.pow(24) + 321;
324+
/// let duration = Duration::from_nanos_u128(nanos);
325+
///
326+
/// assert_eq!(10_u64.pow(15), duration.as_secs());
327+
/// assert_eq!(321, duration.subsec_nanos());
328+
/// ```
329+
#[unstable(feature = "duration_from_nanos_u128", issue = "139201")]
330+
// This is necessary because of const `try_from`, but can be removed if a trait-free impl is used instead
331+
#[rustc_const_unstable(feature = "duration_from_nanos_u128", issue = "139201")]
332+
#[must_use]
333+
#[inline]
334+
#[track_caller]
335+
pub const fn from_nanos_u128(nanos: u128) -> Duration {
336+
const NANOS_PER_SEC: u128 = self::NANOS_PER_SEC as u128;
337+
let Ok(secs) = u64::try_from(nanos / NANOS_PER_SEC) else {
338+
panic!("overflow in `Duration::from_nanos_u128`");
339+
};
340+
let subsec_nanos = (nanos % NANOS_PER_SEC) as u32;
341+
// SAFETY: x % 1_000_000_000 < 1_000_000_000 also, subsec_nanos >= 0 since u128 >=0 and u32 >=0
342+
let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) };
343+
344+
Duration { secs: secs as u64, nanos: subsec_nanos }
345+
}
346+
311347
/// Creates a new `Duration` from the specified number of weeks.
312348
///
313349
/// # Panics

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#![feature(drop_guard)]
3737
#![feature(duration_constants)]
3838
#![feature(duration_constructors)]
39+
#![feature(duration_from_nanos_u128)]
3940
#![feature(error_generic_member_access)]
4041
#![feature(exact_div)]
4142
#![feature(exact_size_is_empty)]

library/coretests/tests/time.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ fn from_weeks_overflow() {
4545
let _ = Duration::from_weeks(overflow);
4646
}
4747

48+
#[test]
49+
#[should_panic]
50+
fn from_nanos_u128_overflow() {
51+
let nanos_per_sec: u128 = 1_000_000_000;
52+
let overflow = (u64::MAX as u128 * nanos_per_sec) + (nanos_per_sec - 1) + 1;
53+
let _ = Duration::from_nanos_u128(overflow);
54+
}
55+
4856
#[test]
4957
fn constructor_weeks() {
5058
assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60));
@@ -81,6 +89,8 @@ fn secs() {
8189
assert_eq!(Duration::from_micros(1_000_001).as_secs(), 1);
8290
assert_eq!(Duration::from_nanos(999_999_999).as_secs(), 0);
8391
assert_eq!(Duration::from_nanos(1_000_000_001).as_secs(), 1);
92+
assert_eq!(Duration::from_nanos_u128(999_999_999).as_secs(), 0);
93+
assert_eq!(Duration::from_nanos_u128(1_000_000_001).as_secs(), 1);
8494
}
8595

8696
#[test]
@@ -95,6 +105,8 @@ fn millis() {
95105
assert_eq!(Duration::from_micros(1_001_000).subsec_millis(), 1);
96106
assert_eq!(Duration::from_nanos(999_999_999).subsec_millis(), 999);
97107
assert_eq!(Duration::from_nanos(1_001_000_000).subsec_millis(), 1);
108+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_millis(), 999);
109+
assert_eq!(Duration::from_nanos_u128(1_001_000_001).subsec_millis(), 1);
98110
}
99111

100112
#[test]
@@ -109,6 +121,8 @@ fn micros() {
109121
assert_eq!(Duration::from_micros(1_000_001).subsec_micros(), 1);
110122
assert_eq!(Duration::from_nanos(999_999_999).subsec_micros(), 999_999);
111123
assert_eq!(Duration::from_nanos(1_000_001_000).subsec_micros(), 1);
124+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_micros(), 999_999);
125+
assert_eq!(Duration::from_nanos_u128(1_000_001_000).subsec_micros(), 1);
112126
}
113127

114128
#[test]
@@ -123,6 +137,8 @@ fn nanos() {
123137
assert_eq!(Duration::from_micros(1_000_001).subsec_nanos(), 1000);
124138
assert_eq!(Duration::from_nanos(999_999_999).subsec_nanos(), 999_999_999);
125139
assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1);
140+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_nanos(), 999_999_999);
141+
assert_eq!(Duration::from_nanos_u128(1_000_000_001).subsec_nanos(), 1);
126142
}
127143

128144
#[test]
@@ -520,6 +536,9 @@ fn duration_const() {
520536
const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
521537
assert_eq!(FROM_NANOS, Duration::SECOND);
522538

539+
const FROM_NANOS_U128: Duration = Duration::from_nanos_u128(NANOS);
540+
assert_eq!(FROM_NANOS_U128, Duration::SECOND);
541+
523542
const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
524543

525544
const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND);

library/std/src/fs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ pub struct DirBuilder {
304304
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
305305
fn inner(path: &Path) -> io::Result<Vec<u8>> {
306306
let mut file = File::open(path)?;
307-
let size = file.metadata().map(|m| m.len() as usize).ok();
307+
let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();
308308
let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?;
309309
io::default_read_to_end(&mut file, &mut bytes, size)?;
310310
Ok(bytes)
@@ -346,7 +346,7 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
346346
pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
347347
fn inner(path: &Path) -> io::Result<String> {
348348
let mut file = File::open(path)?;
349-
let size = file.metadata().map(|m| m.len() as usize).ok();
349+
let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();
350350
let mut string = String::new();
351351
string.try_reserve_exact(size.unwrap_or(0))?;
352352
io::default_read_to_string(&mut file, &mut string, size)?;

library/std/src/sync/barrier.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::fmt;
2-
// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available
3-
use crate::sync::{Condvar, Mutex};
2+
use crate::sync::nonpoison::{Condvar, Mutex};
43

54
/// A barrier enables multiple threads to synchronize the beginning
65
/// of some computation.
@@ -118,12 +117,11 @@ impl Barrier {
118117
/// ```
119118
#[stable(feature = "rust1", since = "1.0.0")]
120119
pub fn wait(&self) -> BarrierWaitResult {
121-
let mut lock = self.lock.lock().unwrap();
120+
let mut lock = self.lock.lock();
122121
let local_gen = lock.generation_id;
123122
lock.count += 1;
124123
if lock.count < self.num_threads {
125-
let _guard =
126-
self.cvar.wait_while(lock, |state| local_gen == state.generation_id).unwrap();
124+
let _guard = self.cvar.wait_while(lock, |state| local_gen == state.generation_id);
127125
BarrierWaitResult(false)
128126
} else {
129127
lock.count = 0;

library/std/src/sync/mod.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ pub use self::poison::{LockResult, PoisonError};
209209
#[doc(inline)]
210210
pub use self::poison::{
211211
Mutex, MutexGuard, TryLockError, TryLockResult,
212-
Condvar, WaitTimeoutResult,
212+
Condvar,
213213
Once, OnceState,
214214
RwLock, RwLockReadGuard, RwLockWriteGuard,
215215
};
@@ -234,3 +234,66 @@ mod barrier;
234234
mod lazy_lock;
235235
mod once_lock;
236236
mod reentrant_lock;
237+
238+
/// A type indicating whether a timed wait on a condition variable returned
239+
/// due to a time out or not.
240+
///
241+
/// It is returned by the [`wait_timeout`] method.
242+
///
243+
/// [`wait_timeout`]: Condvar::wait_timeout
244+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
245+
#[stable(feature = "wait_timeout", since = "1.5.0")]
246+
pub struct WaitTimeoutResult(bool);
247+
248+
impl WaitTimeoutResult {
249+
/// Returns `true` if the wait was known to have timed out.
250+
///
251+
/// # Examples
252+
///
253+
/// This example spawns a thread which will sleep 20 milliseconds before
254+
/// updating a boolean value and then notifying the condvar.
255+
///
256+
/// The main thread will wait with a 10 millisecond timeout on the condvar
257+
/// and will leave the loop upon timeout.
258+
///
259+
/// ```
260+
/// use std::sync::{Arc, Condvar, Mutex};
261+
/// use std::thread;
262+
/// use std::time::Duration;
263+
///
264+
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
265+
/// let pair2 = Arc::clone(&pair);
266+
///
267+
/// # let handle =
268+
/// thread::spawn(move || {
269+
/// let (lock, cvar) = &*pair2;
270+
///
271+
/// // Let's wait 20 milliseconds before notifying the condvar.
272+
/// thread::sleep(Duration::from_millis(20));
273+
///
274+
/// let mut started = lock.lock().unwrap();
275+
/// // We update the boolean value.
276+
/// *started = true;
277+
/// cvar.notify_one();
278+
/// });
279+
///
280+
/// // Wait for the thread to start up.
281+
/// let (lock, cvar) = &*pair;
282+
/// loop {
283+
/// // Let's put a timeout on the condvar's wait.
284+
/// let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap();
285+
/// // 10 milliseconds have passed.
286+
/// if result.1.timed_out() {
287+
/// // timed out now and we can leave.
288+
/// break
289+
/// }
290+
/// }
291+
/// # // Prevent leaks for Miri.
292+
/// # let _ = handle.join();
293+
/// ```
294+
#[must_use]
295+
#[stable(feature = "wait_timeout", since = "1.5.0")]
296+
pub fn timed_out(&self) -> bool {
297+
self.0
298+
}
299+
}

library/std/src/sync/nonpoison.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ impl fmt::Display for WouldBlock {
2929
}
3030
}
3131

32+
#[unstable(feature = "nonpoison_condvar", issue = "134645")]
33+
pub use self::condvar::Condvar;
3234
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
3335
pub use self::mutex::MappedMutexGuard;
3436
#[unstable(feature = "nonpoison_mutex", issue = "134645")]
@@ -38,5 +40,6 @@ pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
3840
#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
3941
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
4042

43+
mod condvar;
4144
mod mutex;
4245
mod rwlock;

0 commit comments

Comments
 (0)