44//!
55//! Hints may be compile time or runtime.
66
7+ use crate :: mem:: MaybeUninit ;
78use crate :: { intrinsics, ub_checks} ;
89
910/// Informs the compiler that the site which is calling this function is not
@@ -735,9 +736,9 @@ pub const fn cold_path() {
735736 crate :: intrinsics:: cold_path ( )
736737}
737738
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.
741742///
742743/// This method is functionally equivalent to
743744/// ```ignore (this is just for illustrative purposes)
@@ -753,10 +754,10 @@ pub const fn cold_path() {
753754/// search.
754755///
755756/// 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.
760761///
761762/// # Examples
762763///
@@ -780,6 +781,17 @@ pub const fn cold_path() {
780781/// ```
781782#[ inline( always) ]
782783#[ 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+ }
785797}
0 commit comments