Fix drop handling in hint::select_unpredictable
· rust-lang/rust@e5e5fb9 (original) (raw)
`@@ -4,6 +4,7 @@
`
4
4
`//!
`
5
5
`//! Hints may be compile time or runtime.
`
6
6
``
``
7
`+
use crate::mem::MaybeUninit;
`
7
8
`use crate::{intrinsics, ub_checks};
`
8
9
``
9
10
`/// Informs the compiler that the site which is calling this function is not
`
`@@ -735,9 +736,9 @@ pub const fn cold_path() {
`
735
736
`crate::intrinsics::cold_path()
`
736
737
`}
`
737
738
``
738
``
`` -
/// Returns either true_val
or false_val
depending on the value of b
,
``
739
``
`` -
/// with a hint to the compiler that b
is unlikely to be correctly
``
740
``
`-
/// predicted by a CPU’s branch predictor.
`
``
739
`` +
/// Returns either true_val
or false_val
depending on the value of
``
``
740
`` +
/// condition
, with a hint to the compiler that condition
is unlikely to be
``
``
741
`+
/// correctly predicted by a CPU’s branch predictor.
`
741
742
`///
`
742
743
`/// This method is functionally equivalent to
`
743
744
```` /// ```ignore (this is just for illustrative purposes)
`@@ -753,10 +754,10 @@ pub const fn cold_path() {
`
`753`
`754`
`/// search.
`
`754`
`755`
`///
`
`755`
`756`
`/// Note however that this lowering is not guaranteed (on any platform) and
`
`756`
``
`-
/// should not be relied upon when trying to write constant-time code. Also
`
`757`
``
`` -
/// be aware that this lowering might *decrease* performance if `condition`
``
`758`
``
`-
/// is well-predictable. It is advisable to perform benchmarks to tell if
`
`759`
``
`-
/// this function is useful.
`
``
`757`
`+
/// should not be relied upon when trying to write cryptographic constant-time
`
``
`758`
`+
/// code. Also be aware that this lowering might *decrease* performance if
`
``
`759`
`` +
/// `condition` is well-predictable. It is advisable to perform benchmarks to
``
``
`760`
`+
/// tell if this function is useful.
`
`760`
`761`
`///
`
`761`
`762`
`/// # Examples
`
`762`
`763`
`///
`
`@@ -780,6 +781,17 @@ pub const fn cold_path() {
`
`780`
`781`
```` /// ```
781
782
`#[inline(always)]
`
782
783
`#[unstable(feature = "select_unpredictable", issue = "133962")]
`
783
``
`-
pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T {
`
784
``
`-
crate::intrinsics::select_unpredictable(b, true_val, false_val)
`
``
784
`+
pub fn select_unpredictable(condition: bool, true_val: T, false_val: T) -> T {
`
``
785
`+
// FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
`
``
786
`+
// Change this to use ManuallyDrop instead.
`
``
787
`+
let mut true_val = MaybeUninit::new(true_val);
`
``
788
`+
let mut false_val = MaybeUninit::new(false_val);
`
``
789
`+
// SAFETY: The value that is not selected is dropped, and the selected one
`
``
790
`+
// is returned. This is necessary because the intrinsic doesn't drop the
`
``
791
`+
// value that is not selected.
`
``
792
`+
unsafe {
`
``
793
`+
crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
`
``
794
`+
.assume_init_drop();
`
``
795
`+
crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
`
``
796
`+
}
`
785
797
`}
`