Skip to content

Commit

Permalink
Rollup merge of rust-lang#73778 - nbdd0121:const_likely, r=oli-obk
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Dylan-DPC committed Jul 1, 2020
2 parents 51a0cfd + 8b43012 commit ea718a6
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ extern "rust-intrinsic" {
/// Any use other than with `if` statements will probably not have an effect.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
pub fn likely(b: bool) -> bool;

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

/// Executes a breakpoint trap, for inspection by a debugger.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#![feature(const_slice_from_raw_parts)]
#![feature(const_slice_ptr_len)]
#![feature(const_type_name)]
#![feature(const_likely)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
);
self.copy_op(self.operand_index(args[0], index)?, dest)?;
}
sym::likely | sym::unlikely => {
// These just return their argument
self.copy_op(args[0], dest)?;
}
// FIXME(#73156): Handle source code coverage in const eval
sym::count_code_region => (),
_ => return Ok(false),
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_mir/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
if is_lang_panic_fn(self.tcx, def_id) {
self.check_op(ops::Panic);
} else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
// Exempt unstable const fns inside of macros with
// Exempt unstable const fns inside of macros or functions with
// `#[allow_internal_unstable]`.
if !self.span.allows_unstable(feature) {
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
if !self.span.allows_unstable(feature)
&& !lib_feature_allowed(self.tcx, self.def_id, feature)
{
self.check_op(ops::FnCallUnstable(def_id, feature));
}
} else {
Expand Down
37 changes: 33 additions & 4 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo
.map_or(false, |mut features| features.any(|name| name == feature_gate))
}

/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
// All features require that the corresponding gate be enabled,
// even if the function has `#[allow_internal_unstable(the_gate)]`.
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
return false;
}

// If this crate is not using stability attributes, or this function is not claiming to be a
// stable `const fn`, that is all that is required.
if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
return true;
}

// However, we cannot allow stable `const fn`s to use unstable features without an explicit
// opt-in via `allow_internal_unstable`.
attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
.map_or(false, |mut features| features.any(|name| name == feature_gate))
}

fn check_terminator(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
Expand Down Expand Up @@ -367,8 +387,17 @@ fn check_terminator(
fn_span: _,
} => {
let fn_ty = func.ty(body, tcx);
if let ty::FnDef(def_id, _) = fn_ty.kind {
if !crate::const_eval::is_min_const_fn(tcx, def_id) {
if let ty::FnDef(fn_def_id, _) = fn_ty.kind {
// Allow unstable const if we opt in by using #[allow_internal_unstable]
// on function or macro declaration.
if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
&& !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
.map(|feature| {
span.allows_unstable(feature)
|| lib_feature_allowed(tcx, def_id, feature)
})
.unwrap_or(false)
{
return Err((
span,
format!(
Expand All @@ -380,10 +409,10 @@ fn check_terminator(
));
}

check_operand(tcx, func, span, def_id, body)?;
check_operand(tcx, func, span, fn_def_id, body)?;

for arg in args {
check_operand(tcx, arg, span, def_id, body)?;
check_operand(tcx, arg, span, fn_def_id, body)?;
}
Ok(())
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_span/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ symbols! {
lhs,
lib,
lifetime,
likely,
line,
link,
linkage,
Expand Down Expand Up @@ -813,6 +814,7 @@ symbols! {
underscore_lifetimes,
uniform_paths,
universal_impl_trait,
unlikely,
unmarked_api,
unreachable_code,
unrestricted_attribute_tokens,
Expand Down

0 comments on commit ea718a6

Please sign in to comment.