Skip to content

Commit c07fc68

Browse files
committed
const select_unpredictable
1 parent 3c91be7 commit c07fc68

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

library/core/src/hint.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//!
55
//! Hints may be compile time or runtime.
66
7+
use crate::marker::Destruct;
78
use crate::mem::MaybeUninit;
89
use crate::{intrinsics, ub_checks};
910

@@ -781,17 +782,35 @@ pub const fn cold_path() {
781782
/// ```
782783
#[inline(always)]
783784
#[stable(feature = "select_unpredictable", since = "1.88.0")]
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()
785+
#[rustc_const_unstable(feature = "const_select_unpredictable", issue = "145938")]
786+
pub const fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
787+
where
788+
T: [const] Destruct,
789+
{
790+
#[inline(always)]
791+
fn select_actually_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T {
792+
// FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
793+
// Change this to use ManuallyDrop instead.
794+
let mut true_val = MaybeUninit::new(true_val);
795+
let mut false_val = MaybeUninit::new(false_val);
796+
// SAFETY: The value that is not selected is dropped, and the selected one
797+
// is returned. This is necessary because the intrinsic doesn't drop the
798+
// value that is not selected.
799+
unsafe {
800+
crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
801+
.assume_init_drop();
802+
crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
803+
}
804+
}
805+
const fn select_predictable<T>(condition: bool, true_val: T, false_val: T) -> T
806+
where
807+
T: [const] Destruct,
808+
{
809+
if condition { true_val } else { false_val }
796810
}
811+
intrinsics::const_eval_select(
812+
(condition, true_val, false_val),
813+
select_predictable,
814+
select_actually_unpredictable,
815+
)
797816
}

0 commit comments

Comments
 (0)