const select_unpredictable
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
//!
|
||||
//! Hints may be compile time or runtime.
|
||||
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::{intrinsics, ub_checks};
|
||||
|
||||
@@ -771,7 +772,11 @@ pub const fn cold_path() {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[stable(feature = "select_unpredictable", since = "1.88.0")]
|
||||
pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T {
|
||||
#[rustc_const_unstable(feature = "const_select_unpredictable", issue = "145938")]
|
||||
pub const fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
|
||||
// Change this to use ManuallyDrop instead.
|
||||
let mut true_val = MaybeUninit::new(true_val);
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::ffi::va_list::{VaArgSafe, VaListImpl};
|
||||
use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple};
|
||||
use crate::marker::{ConstParamTy, Destruct, DiscriminantKind, PointeeSized, Tuple};
|
||||
use crate::ptr;
|
||||
|
||||
mod bounds;
|
||||
@@ -477,11 +477,15 @@ pub const fn unlikely(b: bool) -> bool {
|
||||
/// However unlike the public form, the intrinsic will not drop the value that
|
||||
/// is not selected.
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_select_unpredictable", issue = "145938")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[miri::intrinsic_fallback_is_spec]
|
||||
#[inline]
|
||||
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
|
||||
pub const fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
if b { true_val } else { false_val }
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#![feature(const_cmp)]
|
||||
#![feature(const_destruct)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_select_unpredictable)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(coverage_attribute)]
|
||||
#![feature(disjoint_bitor)]
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
#[test]
|
||||
fn select_unpredictable_drop() {
|
||||
use core::cell::Cell;
|
||||
|
||||
struct X<'a>(&'a Cell<bool>);
|
||||
impl Drop for X<'_> {
|
||||
impl const Drop for X<'_> {
|
||||
fn drop(&mut self) {
|
||||
self.0.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
let a_dropped = Cell::new(false);
|
||||
let b_dropped = Cell::new(false);
|
||||
let a = X(&a_dropped);
|
||||
let b = X(&b_dropped);
|
||||
assert!(!a_dropped.get());
|
||||
assert!(!b_dropped.get());
|
||||
let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b);
|
||||
assert!(!a_dropped.get());
|
||||
assert!(b_dropped.get());
|
||||
drop(selected);
|
||||
assert!(a_dropped.get());
|
||||
assert!(b_dropped.get());
|
||||
const fn do_test() {
|
||||
let a_dropped = Cell::new(false);
|
||||
let b_dropped = Cell::new(false);
|
||||
let a = X(&a_dropped);
|
||||
let b = X(&b_dropped);
|
||||
assert!(!a_dropped.get());
|
||||
assert!(!b_dropped.get());
|
||||
let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b);
|
||||
assert!(!a_dropped.get());
|
||||
assert!(b_dropped.get());
|
||||
drop(selected);
|
||||
assert!(a_dropped.get());
|
||||
assert!(b_dropped.get());
|
||||
}
|
||||
|
||||
do_test();
|
||||
const {
|
||||
do_test();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#![feature(const_option_ops)]
|
||||
#![feature(const_ref_cell)]
|
||||
#![feature(const_result_trait_fn)]
|
||||
#![feature(const_select_unpredictable)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(control_flow_ok)]
|
||||
#![feature(core_float_math)]
|
||||
|
||||
Reference in New Issue
Block a user