Skip to content

Commit f28f5aa

Browse files
authored
Rollup merge of rust-lang#49906 - kennytm:stable-unreachable, r=sfackler
Stabilize `std::hint::unreachable_unchecked`. Closes rust-lang#43751.
2 parents 2701c17 + 5fe8c59 commit f28f5aa

File tree

6 files changed

+71
-16
lines changed

6 files changed

+71
-16
lines changed

src/libcore/hint.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![stable(feature = "core_hint", since = "1.27.0")]
12+
13+
//! Hints to compiler that affects how code should be emitted or optimized.
14+
15+
use intrinsics;
16+
17+
/// Informs the compiler that this point in the code is not reachable, enabling
18+
/// further optimizations.
19+
///
20+
/// # Safety
21+
///
22+
/// Reaching this function is completely *undefined behavior* (UB). In
23+
/// particular, the compiler assumes that all UB must never happen, and
24+
/// therefore will eliminate all branches that reach to a call to
25+
/// `unreachable_unchecked()`.
26+
///
27+
/// Like all instances of UB, if this assumption turns out to be wrong, i.e. the
28+
/// `unreachable_unchecked()` call is actually reachable among all possible
29+
/// control flow, the compiler will apply the wrong optimization strategy, and
30+
/// may sometimes even corrupt seemingly unrelated code, causing
31+
/// difficult-to-debug problems.
32+
///
33+
/// Use this function only when you can prove that the code will never call it.
34+
///
35+
/// The [`unreachable!()`] macro is the safe counterpart of this function, which
36+
/// will panic instead when executed.
37+
///
38+
/// [`unreachable!()`]: ../macro.unreachable.html
39+
///
40+
/// # Example
41+
///
42+
/// ```
43+
/// fn div_1(a: u32, b: u32) -> u32 {
44+
/// use std::hint::unreachable_unchecked;
45+
///
46+
/// // `b.saturating_add(1)` is always positive (not zero),
47+
/// // hence `checked_div` will never return None.
48+
/// // Therefore, the else branch is unreachable.
49+
/// a.checked_div(b.saturating_add(1))
50+
/// .unwrap_or_else(|| unsafe { unreachable_unchecked() })
51+
/// }
52+
///
53+
/// assert_eq!(div_1(7, 0), 7);
54+
/// assert_eq!(div_1(9, 1), 4);
55+
/// assert_eq!(div_1(11, std::u32::MAX), 0);
56+
/// ```
57+
#[inline]
58+
#[stable(feature = "unreachable", since = "1.27.0")]
59+
pub unsafe fn unreachable_unchecked() -> ! {
60+
intrinsics::unreachable()
61+
}

src/libcore/intrinsics.rs

+3
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,9 @@ extern "rust-intrinsic" {
638638
/// NB: This is very different from the `unreachable!()` macro: Unlike the
639639
/// macro, which panics when it is executed, it is *undefined behavior* to
640640
/// reach code marked with this function.
641+
///
642+
/// The stabilized version of this intrinsic is
643+
/// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html).
641644
pub fn unreachable() -> !;
642645

643646
/// Informs the optimizer that a condition is always true.

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ pub mod intrinsics;
163163
pub mod mem;
164164
pub mod nonzero;
165165
pub mod ptr;
166+
pub mod hint;
166167

167168
/* Core language traits */
168169

src/libcore/macros.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,13 @@ macro_rules! writeln {
421421
/// * Iterators that dynamically terminate.
422422
///
423423
/// If the determination that the code is unreachable proves incorrect, the
424-
/// program immediately terminates with a [`panic!`]. The function [`unreachable`],
425-
/// which belongs to the [`std::intrinsics`] module, informs the compilier to
424+
/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`],
425+
/// which belongs to the [`std::hint`] module, informs the compilier to
426426
/// optimize the code out of the release version entirely.
427427
///
428428
/// [`panic!`]: ../std/macro.panic.html
429-
/// [`unreachable`]: ../std/intrinsics/fn.unreachable.html
430-
/// [`std::intrinsics`]: ../std/intrinsics/index.html
429+
/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
430+
/// [`std::hint`]: ../std/hint/index.html
431431
///
432432
/// # Panics
433433
///

src/libcore/mem.rs

-12
Original file line numberDiff line numberDiff line change
@@ -1094,18 +1094,6 @@ impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
10941094
}
10951095
}
10961096

1097-
/// Tells LLVM that this point in the code is not reachable, enabling further
1098-
/// optimizations.
1099-
///
1100-
/// NB: This is very different from the `unreachable!()` macro: Unlike the
1101-
/// macro, which panics when it is executed, it is *undefined behavior* to
1102-
/// reach code marked with this function.
1103-
#[inline]
1104-
#[unstable(feature = "unreachable", issue = "43751")]
1105-
pub unsafe fn unreachable() -> ! {
1106-
intrinsics::unreachable()
1107-
}
1108-
11091097
/// A pinned reference.
11101098
///
11111099
/// A pinned reference is a lot like a mutable reference, except that it is not

src/libstd/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@ pub use alloc_crate::vec;
461461
pub use core::char;
462462
#[stable(feature = "i128", since = "1.26.0")]
463463
pub use core::u128;
464+
#[stable(feature = "core_hint", since = "1.27.0")]
465+
pub use core::hint;
464466

465467
pub mod f32;
466468
pub mod f64;

0 commit comments

Comments
 (0)