Skip to content

Commit ec41d01

Browse files
authored
Rollup merge of #73778 - nbdd0121:const_likely, r=oli-obk
Make `likely` and `unlikely` const, gated by feature `const_unlikely` This PR also contains a fix to allow `#[allow_internal_unstable]` to work properly with `#[rustc_const_unstable]`. cc @RalfJung @nagisa r? @oli-obk
2 parents d6bee55 + 8b43012 commit ec41d01

File tree

6 files changed

+47
-6
lines changed

6 files changed

+47
-6
lines changed

src/libcore/intrinsics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,7 @@ extern "rust-intrinsic" {
952952
/// Any use other than with `if` statements will probably not have an effect.
953953
///
954954
/// This intrinsic does not have a stable counterpart.
955+
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
955956
pub fn likely(b: bool) -> bool;
956957

957958
/// Hints to the compiler that branch condition is likely to be false.
@@ -960,6 +961,7 @@ extern "rust-intrinsic" {
960961
/// Any use other than with `if` statements will probably not have an effect.
961962
///
962963
/// This intrinsic does not have a stable counterpart.
964+
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
963965
pub fn unlikely(b: bool) -> bool;
964966

965967
/// Executes a breakpoint trap, for inspection by a debugger.

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#![feature(const_slice_from_raw_parts)]
9393
#![feature(const_slice_ptr_len)]
9494
#![feature(const_type_name)]
95+
#![feature(const_likely)]
9596
#![feature(custom_inner_attributes)]
9697
#![feature(decl_macro)]
9798
#![feature(doc_cfg)]

src/librustc_mir/interpret/intrinsics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
409409
);
410410
self.copy_op(self.operand_index(args[0], index)?, dest)?;
411411
}
412+
sym::likely | sym::unlikely => {
413+
// These just return their argument
414+
self.copy_op(args[0], dest)?;
415+
}
412416
// FIXME(#73156): Handle source code coverage in const eval
413417
sym::count_code_region => (),
414418
_ => return Ok(false),

src/librustc_mir/transform/check_consts/validation.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
531531
if is_lang_panic_fn(self.tcx, def_id) {
532532
self.check_op(ops::Panic);
533533
} else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
534-
// Exempt unstable const fns inside of macros with
534+
// Exempt unstable const fns inside of macros or functions with
535535
// `#[allow_internal_unstable]`.
536-
if !self.span.allows_unstable(feature) {
536+
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
537+
if !self.span.allows_unstable(feature)
538+
&& !lib_feature_allowed(self.tcx, self.def_id, feature)
539+
{
537540
self.check_op(ops::FnCallUnstable(def_id, feature));
538541
}
539542
} else {

src/librustc_mir/transform/qualify_min_const_fn.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo
328328
.map_or(false, |mut features| features.any(|name| name == feature_gate))
329329
}
330330

331+
/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
332+
pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
333+
// All features require that the corresponding gate be enabled,
334+
// even if the function has `#[allow_internal_unstable(the_gate)]`.
335+
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
336+
return false;
337+
}
338+
339+
// If this crate is not using stability attributes, or this function is not claiming to be a
340+
// stable `const fn`, that is all that is required.
341+
if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
342+
return true;
343+
}
344+
345+
// However, we cannot allow stable `const fn`s to use unstable features without an explicit
346+
// opt-in via `allow_internal_unstable`.
347+
attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
348+
.map_or(false, |mut features| features.any(|name| name == feature_gate))
349+
}
350+
331351
fn check_terminator(
332352
tcx: TyCtxt<'tcx>,
333353
body: &'a Body<'tcx>,
@@ -367,8 +387,17 @@ fn check_terminator(
367387
fn_span: _,
368388
} => {
369389
let fn_ty = func.ty(body, tcx);
370-
if let ty::FnDef(def_id, _) = fn_ty.kind {
371-
if !crate::const_eval::is_min_const_fn(tcx, def_id) {
390+
if let ty::FnDef(fn_def_id, _) = fn_ty.kind {
391+
// Allow unstable const if we opt in by using #[allow_internal_unstable]
392+
// on function or macro declaration.
393+
if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
394+
&& !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
395+
.map(|feature| {
396+
span.allows_unstable(feature)
397+
|| lib_feature_allowed(tcx, def_id, feature)
398+
})
399+
.unwrap_or(false)
400+
{
372401
return Err((
373402
span,
374403
format!(
@@ -380,10 +409,10 @@ fn check_terminator(
380409
));
381410
}
382411

383-
check_operand(tcx, func, span, def_id, body)?;
412+
check_operand(tcx, func, span, fn_def_id, body)?;
384413

385414
for arg in args {
386-
check_operand(tcx, arg, span, def_id, body)?;
415+
check_operand(tcx, arg, span, fn_def_id, body)?;
387416
}
388417
Ok(())
389418
} else {

src/librustc_span/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ symbols! {
427427
lhs,
428428
lib,
429429
lifetime,
430+
likely,
430431
line,
431432
link,
432433
linkage,
@@ -813,6 +814,7 @@ symbols! {
813814
underscore_lifetimes,
814815
uniform_paths,
815816
universal_impl_trait,
817+
unlikely,
816818
unmarked_api,
817819
unreachable_code,
818820
unrestricted_attribute_tokens,

0 commit comments

Comments
 (0)