Skip to content

Commit 7a17d4a

Browse files
committed
const select_unpredictable
1 parent 235a4c0 commit 7a17d4a

File tree

5 files changed

+39
-19
lines changed

5 files changed

+39
-19
lines changed

library/core/src/hint.rs

Lines changed: 6 additions & 1 deletion
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

@@ -771,7 +772,11 @@ pub const fn cold_path() {
771772
/// ```
772773
#[inline(always)]
773774
#[stable(feature = "select_unpredictable", since = "1.88.0")]
774-
pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T {
775+
#[rustc_const_unstable(feature = "const_select_unpredictable", issue = "145938")]
776+
pub const fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
777+
where
778+
T: [const] Destruct,
779+
{
775780
// FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
776781
// Change this to use ManuallyDrop instead.
777782
let mut true_val = MaybeUninit::new(true_val);

library/core/src/intrinsics/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
#![allow(missing_docs)]
5656

5757
use crate::ffi::va_list::{VaArgSafe, VaListImpl};
58-
use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple};
58+
use crate::marker::{ConstParamTy, Destruct, DiscriminantKind, PointeeSized, Tuple};
5959
use crate::ptr;
6060

6161
mod bounds;
@@ -477,11 +477,15 @@ pub const fn unlikely(b: bool) -> bool {
477477
/// However unlike the public form, the intrinsic will not drop the value that
478478
/// is not selected.
479479
#[unstable(feature = "core_intrinsics", issue = "none")]
480+
#[rustc_const_unstable(feature = "const_select_unpredictable", issue = "145938")]
480481
#[rustc_intrinsic]
481482
#[rustc_nounwind]
482483
#[miri::intrinsic_fallback_is_spec]
483484
#[inline]
484-
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
485+
pub const fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T
486+
where
487+
T: [const] Destruct,
488+
{
485489
if b { true_val } else { false_val }
486490
}
487491

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
#![feature(const_cmp)]
107107
#![feature(const_destruct)]
108108
#![feature(const_eval_select)]
109+
#![feature(const_select_unpredictable)]
109110
#![feature(core_intrinsics)]
110111
#![feature(coverage_attribute)]
111112
#![feature(disjoint_bitor)]

library/coretests/tests/hint.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
#[test]
22
fn select_unpredictable_drop() {
3-
use core::cell::Cell;
4-
struct X<'a>(&'a Cell<bool>);
5-
impl Drop for X<'_> {
3+
struct X(*mut bool);
4+
impl const Drop for X {
65
fn drop(&mut self) {
7-
self.0.set(true);
6+
// FIXME(const-hack): Once const cells work, we could remove unsafe code here.
7+
unsafe {
8+
*self.0 = true;
9+
}
810
}
911
}
1012

11-
let a_dropped = Cell::new(false);
12-
let b_dropped = Cell::new(false);
13-
let a = X(&a_dropped);
14-
let b = X(&b_dropped);
15-
assert!(!a_dropped.get());
16-
assert!(!b_dropped.get());
17-
let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b);
18-
assert!(!a_dropped.get());
19-
assert!(b_dropped.get());
20-
drop(selected);
21-
assert!(a_dropped.get());
22-
assert!(b_dropped.get());
13+
const fn do_test() {
14+
let mut a_dropped = false;
15+
let mut b_dropped = false;
16+
let a = X(&raw mut a_dropped);
17+
let b = X(&raw mut b_dropped);
18+
assert!(!a_dropped);
19+
assert!(!b_dropped);
20+
let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b);
21+
assert!(!a_dropped);
22+
assert!(b_dropped);
23+
drop(selected);
24+
assert!(a_dropped);
25+
assert!(b_dropped);
26+
}
27+
28+
do_test();
29+
const {
30+
do_test();
31+
}
2332
}
2433

2534
#[test]

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#![feature(const_option_ops)]
2727
#![feature(const_ref_cell)]
2828
#![feature(const_result_trait_fn)]
29+
#![feature(const_select_unpredictable)]
2930
#![feature(const_trait_impl)]
3031
#![feature(control_flow_ok)]
3132
#![feature(core_float_math)]

0 commit comments

Comments
 (0)