|
4 | 4 | //! |
5 | 5 | //! Hints may be compile time or runtime. |
6 | 6 |
|
| 7 | +use crate::marker::Destruct; |
7 | 8 | use crate::mem::MaybeUninit; |
8 | 9 | use crate::{intrinsics, ub_checks}; |
9 | 10 |
|
@@ -781,17 +782,35 @@ pub const fn cold_path() { |
781 | 782 | /// ``` |
782 | 783 | #[inline(always)] |
783 | 784 | #[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 } |
796 | 810 | } |
| 811 | + intrinsics::const_eval_select( |
| 812 | + (condition, true_val, false_val), |
| 813 | + select_predictable, |
| 814 | + select_actually_unpredictable, |
| 815 | + ) |
797 | 816 | } |
0 commit comments