1
Fork 0

Rollup merge of #107801 - davidtwco:stability-implies-const, r=Nilstrieb

const_eval: `implies_by` in `rustc_const_unstable`

Fixes #107605.

Extend support for `implies_by` (from `#[stable]` and `#[unstable]`) to `#[rustc_const_stable]` and `#[rustc_const_unstable]`.

cc ``@steffahn``
This commit is contained in:
Matthias Krüger 2023-03-06 16:41:56 +01:00 committed by GitHub
commit 9c99a4ca2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 177 additions and 7 deletions

View file

@ -1,3 +1,4 @@
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
@ -5,11 +6,17 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
/// Whether the `def_id` is an unstable const fn and what feature gate(s) are necessary to enable
/// it.
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<(Symbol, Option<Symbol>)> {
if tcx.is_const_fn_raw(def_id) {
let const_stab = tcx.lookup_const_stability(def_id)?;
if const_stab.is_const_unstable() { Some(const_stab.feature) } else { None }
match const_stab.level {
attr::StabilityLevel::Unstable { implied_by, .. } => {
Some((const_stab.feature, implied_by))
}
attr::StabilityLevel::Stable { .. } => None,
}
} else {
None
}

View file

@ -926,15 +926,24 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// If the `const fn` we are trying to call is not const-stable, ensure that we have
// the proper feature gate enabled.
if let Some(gate) = is_unstable_const_fn(tcx, callee) {
if let Some((gate, implied_by)) = is_unstable_const_fn(tcx, callee) {
trace!(?gate, "calling unstable const fn");
if self.span.allows_unstable(gate) {
return;
}
if let Some(implied_by_gate) = implied_by && self.span.allows_unstable(implied_by_gate) {
return;
}
// Calling an unstable function *always* requires that the corresponding gate
// be enabled, even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`.
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
// (or implied gate) be enabled, even if the function has
// `#[rustc_allow_const_fn_unstable(the_gate)]`.
let gate_declared = |gate| {
tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate)
};
let feature_gate_declared = gate_declared(gate);
let implied_gate_declared = implied_by.map(gate_declared).unwrap_or(false);
if !feature_gate_declared && !implied_gate_declared {
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}
@ -947,7 +956,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
// Otherwise, we are something const-stable calling a const-unstable fn.
if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
trace!("rustc_allow_const_fn_unstable gate active");
return;