ensure that all publicly reachable const fn have const stability info
This commit is contained in:
parent
686eeb83e9
commit
e96808162a
12 changed files with 177 additions and 204 deletions
|
@ -709,6 +709,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
// Intrinsics are language primitives, not regular calls, so treat them separately.
|
||||
if let Some(intrinsic) = tcx.intrinsic(callee) {
|
||||
if !tcx.is_const_fn(callee) {
|
||||
// Non-const intrinsic.
|
||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||
// If we allowed this, we're in miri-unleashed mode, so we might
|
||||
// as well skip the remaining checks.
|
||||
return;
|
||||
}
|
||||
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
|
||||
// stable code, rather than `const_stable_indirect`. This is to make
|
||||
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
|
||||
|
@ -716,17 +723,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// fallback body is safe to expose on stable.
|
||||
let is_const_stable = intrinsic.const_stable
|
||||
|| (!intrinsic.must_be_overridden
|
||||
&& tcx.is_const_fn(callee)
|
||||
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
|
||||
match tcx.lookup_const_stability(callee) {
|
||||
None => {
|
||||
// Non-const intrinsic.
|
||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||
}
|
||||
Some(ConstStability { feature: None, .. }) => {
|
||||
// Intrinsic does not need a separate feature gate (we rely on the
|
||||
// regular stability checker). However, we have to worry about recursive
|
||||
// const stability.
|
||||
// This doesn't need a separate const-stability check -- const-stability equals
|
||||
// regular stability, and regular stability is checked separately.
|
||||
// However, we *do* have to worry about *recursive* const stability.
|
||||
if !is_const_stable && self.enforce_recursive_const_stability() {
|
||||
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
||||
span: self.span,
|
||||
|
@ -735,8 +737,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
feature: Some(feature),
|
||||
level: StabilityLevel::Unstable { .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
self.check_op(ops::IntrinsicUnstable {
|
||||
|
@ -773,7 +775,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||
// All good.
|
||||
}
|
||||
None | Some(ConstStability { feature: None, .. }) => {
|
||||
None => {
|
||||
// This doesn't need a separate const-stability check -- const-stability equals
|
||||
// regular stability, and regular stability is checked separately.
|
||||
// However, we *do* have to worry about *recursive* const stability.
|
||||
|
@ -787,8 +789,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
feature: Some(feature),
|
||||
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
// An unstable const fn with a feature gate.
|
||||
|
|
|
@ -110,14 +110,15 @@ pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> b
|
|||
|
||||
match tcx.lookup_const_stability(def_id) {
|
||||
None => {
|
||||
// Only marked functions can be trusted. Note that this may be a function in a
|
||||
// non-staged-API crate where no recursive checks were done!
|
||||
false
|
||||
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
|
||||
// functions, so we can trust local functions. But in another crate we don't know which
|
||||
// rules were applied, so we can't trust that.
|
||||
def_id.is_local() && tcx.features().staged_api()
|
||||
}
|
||||
Some(stab) => {
|
||||
// We consider things safe-to-expose if they are stable, if they don't have any explicit
|
||||
// const stability attribute, or if they are marked as `const_stable_indirect`.
|
||||
stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect
|
||||
// We consider things safe-to-expose if they are stable or if they are marked as
|
||||
// `const_stable_indirect`.
|
||||
stab.is_const_stable() || stab.const_stable_indirect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue