Skip to content

Commit 63b9144

Browse files
committed
Auto merge of rust-lang#147003 - matthiaskrgr:rollup-b5z9uiz, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#146556 (Fix duration_since panic on unix when std is built with integer overflow checks) - rust-lang#146679 (Clarify Display for error should not include source) - rust-lang#146753 (Improve the pretty print of UnstableFeature clause) - rust-lang#146894 (Improve derive suggestion of const param) - rust-lang#146950 (core: simplify `CStr::default()`) - rust-lang#146958 (Fix infinite recursion in Path::eq with String) - rust-lang#146971 (fix ICE in writeback due to bound regions) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e336ee8 + 5e0927e commit 63b9144

File tree

8 files changed

+66
-35
lines changed

8 files changed

+66
-35
lines changed

alloc/src/ffi/c_str.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -970,17 +970,14 @@ impl Default for Rc<CStr> {
970970
/// This may or may not share an allocation with other Rcs on the same thread.
971971
#[inline]
972972
fn default() -> Self {
973-
let rc = Rc::<[u8]>::from(*b"\0");
974-
// `[u8]` has the same layout as `CStr`, and it is `NUL` terminated.
975-
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
973+
Rc::from(c"")
976974
}
977975
}
978976

979977
#[stable(feature = "default_box_extra", since = "1.17.0")]
980978
impl Default for Box<CStr> {
981979
fn default() -> Box<CStr> {
982-
let boxed: Box<[u8]> = Box::from([0]);
983-
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
980+
Box::from(c"")
984981
}
985982
}
986983

core/src/error.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ use crate::fmt::{self, Debug, Display, Formatter};
1616
/// assert_eq!(err.to_string(), "invalid digit found in string");
1717
/// ```
1818
///
19+
/// # Error source
20+
///
1921
/// Errors may provide cause information. [`Error::source()`] is generally
2022
/// used when errors cross "abstraction boundaries". If one module must report
2123
/// an error that is caused by an error from a lower-level module, it can allow
22-
/// accessing that error via [`Error::source()`]. This makes it possible for the
24+
/// accessing that error via `Error::source()`. This makes it possible for the
2325
/// high-level module to provide its own errors while also revealing some of the
2426
/// implementation for debugging.
2527
///
28+
/// In error types that wrap an underlying error, the underlying error
29+
/// should be either returned by the outer error's `Error::source()`, or rendered
30+
/// by the outer error's `Display` implementation, but not both.
31+
///
2632
/// # Example
2733
///
2834
/// Implementing the `Error` trait only requires that `Debug` and `Display` are implemented too.

core/src/ffi/c_str.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,7 @@ impl fmt::Debug for CStr {
179179
impl Default for &CStr {
180180
#[inline]
181181
fn default() -> Self {
182-
const SLICE: &[c_char] = &[0];
183-
// SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string.
184-
unsafe { CStr::from_ptr(SLICE.as_ptr()) }
182+
c""
185183
}
186184
}
187185

std/src/path.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,31 +2107,31 @@ impl PartialEq for PathBuf {
21072107
impl cmp::PartialEq<str> for PathBuf {
21082108
#[inline]
21092109
fn eq(&self, other: &str) -> bool {
2110-
Path::eq(self, other)
2110+
self.as_path() == other
21112111
}
21122112
}
21132113

21142114
#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
21152115
impl cmp::PartialEq<PathBuf> for str {
21162116
#[inline]
21172117
fn eq(&self, other: &PathBuf) -> bool {
2118-
other == self
2118+
self == other.as_path()
21192119
}
21202120
}
21212121

21222122
#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
21232123
impl cmp::PartialEq<String> for PathBuf {
21242124
#[inline]
21252125
fn eq(&self, other: &String) -> bool {
2126-
**self == **other
2126+
self.as_path() == other.as_str()
21272127
}
21282128
}
21292129

21302130
#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
21312131
impl cmp::PartialEq<PathBuf> for String {
21322132
#[inline]
21332133
fn eq(&self, other: &PathBuf) -> bool {
2134-
other == self
2134+
self.as_str() == other.as_path()
21352135
}
21362136
}
21372137

@@ -3426,15 +3426,15 @@ impl cmp::PartialEq<Path> for str {
34263426
impl cmp::PartialEq<String> for Path {
34273427
#[inline]
34283428
fn eq(&self, other: &String) -> bool {
3429-
self == &*other
3429+
self == other.as_str()
34303430
}
34313431
}
34323432

34333433
#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
34343434
impl cmp::PartialEq<Path> for String {
34353435
#[inline]
34363436
fn eq(&self, other: &Path) -> bool {
3437-
other == self
3437+
self.as_str() == other
34383438
}
34393439
}
34403440

std/src/sys/pal/hermit/time.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,22 @@ impl Timespec {
2626
}
2727

2828
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
29+
fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
30+
debug_assert!(a >= b);
31+
a.wrapping_sub(b).cast_unsigned()
32+
}
33+
2934
if self >= other {
35+
// Logic here is identical to Unix version of `Timestamp::sub_timespec`,
36+
// check comments there why operations do not overflow.
3037
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
3138
Duration::new(
32-
(self.t.tv_sec - other.t.tv_sec) as u64,
39+
sub_ge_to_unsigned(self.t.tv_sec, other.t.tv_sec),
3340
(self.t.tv_nsec - other.t.tv_nsec) as u32,
3441
)
3542
} else {
3643
Duration::new(
37-
(self.t.tv_sec - 1 - other.t.tv_sec) as u64,
44+
sub_ge_to_unsigned(self.t.tv_sec - 1, other.t.tv_sec),
3845
(self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32,
3946
)
4047
})

std/src/sys/pal/unix/time.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,28 +134,25 @@ impl Timespec {
134134
}
135135

136136
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
137+
// When a >= b, the difference fits in u64.
138+
fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
139+
debug_assert!(a >= b);
140+
a.wrapping_sub(b).cast_unsigned()
141+
}
142+
137143
if self >= other {
138-
// NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
139-
// to optimize it into a branchless form (see also #75545):
140-
//
141-
// 1. `self.tv_sec - other.tv_sec` shows up as a common expression
142-
// in both branches, i.e. the `else` must have its `- 1`
143-
// subtraction after the common one, not interleaved with it
144-
// (it used to be `self.tv_sec - 1 - other.tv_sec`)
145-
//
146-
// 2. the `Duration::new` call (or any other additional complexity)
147-
// is outside of the `if`-`else`, not duplicated in both branches
148-
//
149-
// Ideally this code could be rearranged such that it more
150-
// directly expresses the lower-cost behavior we want from it.
151144
let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() {
152145
(
153-
(self.tv_sec - other.tv_sec) as u64,
146+
sub_ge_to_unsigned(self.tv_sec, other.tv_sec),
154147
self.tv_nsec.as_inner() - other.tv_nsec.as_inner(),
155148
)
156149
} else {
150+
// Following sequence of assertions explain why `self.tv_sec - 1` does not underflow.
151+
debug_assert!(self.tv_nsec < other.tv_nsec);
152+
debug_assert!(self.tv_sec > other.tv_sec);
153+
debug_assert!(self.tv_sec > i64::MIN);
157154
(
158-
(self.tv_sec - other.tv_sec - 1) as u64,
155+
sub_ge_to_unsigned(self.tv_sec - 1, other.tv_sec),
159156
self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(),
160157
)
161158
};

std/tests/path.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,7 +2528,17 @@ fn normalize_lexically() {
25282528
}
25292529

25302530
#[test]
2531-
/// See issue#146183
2532-
fn compare_path_to_str() {
2533-
assert!(&PathBuf::from("x") == "x");
2531+
/// See issue#146183 and issue#146940
2532+
fn compare_path_like_to_str_like() {
2533+
let path_buf = PathBuf::from("x");
2534+
let path = Path::new("x");
2535+
let s = String::from("x");
2536+
assert!(path == "x");
2537+
assert!("x" == path);
2538+
assert!(path == &s);
2539+
assert!(&s == path);
2540+
assert!(&path_buf == "x");
2541+
assert!("x" == &path_buf);
2542+
assert!(path_buf == s);
2543+
assert!(s == path_buf);
25342544
}

std/tests/time.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,19 @@ fn big_math() {
227227
check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub);
228228
check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub);
229229
}
230+
231+
#[test]
232+
#[cfg(unix)]
233+
fn system_time_duration_since_max_range_on_unix() {
234+
// Repro regression https://github.com/rust-lang/rust/issues/146228
235+
236+
// Min and max values of `SystemTime` on Unix.
237+
let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0));
238+
let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999));
239+
240+
let delta_a = max.duration_since(min).expect("duration_since overflow");
241+
let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration();
242+
243+
assert_eq!(Duration::MAX, delta_a);
244+
assert_eq!(Duration::MAX, delta_b);
245+
}

0 commit comments

Comments
 (0)