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 < T > ( b : bool , true_val : T , false_val : T ) -> T {
784
- crate :: intrinsics:: select_unpredictable ( b, true_val, false_val)
784
+ pub fn select_unpredictable < T > ( 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
}
0 commit comments