diff options
| author | Ralf Jung <post@ralfj.de> | 2024-11-13 11:58:27 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-11-13 12:03:16 +0100 |
| commit | 9760983353e2600058b5b39d7c97a8bcbe21c583 (patch) | |
| tree | a2fa25efec712976a5e6d2f5456dd2b020b6ddd6 /compiler/rustc_const_eval/src/check_consts/check.rs | |
| parent | 44f233f2519ce5d633c87c38014d03d8a5f0e810 (diff) | |
| download | rust-9760983353e2600058b5b39d7c97a8bcbe21c583.tar.gz rust-9760983353e2600058b5b39d7c97a8bcbe21c583.zip | |
check_consts: fix error requesting feature gate when that gate is not actually needed
Diffstat (limited to 'compiler/rustc_const_eval/src/check_consts/check.rs')
| -rw-r--r-- | compiler/rustc_const_eval/src/check_consts/check.rs | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index c3efca28c68..ffe32acb316 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -272,9 +272,18 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { /// context. pub fn check_op_spanned<O: NonConstOp<'tcx>>(&mut self, op: O, span: Span) { let gate = match op.status_in_item(self.ccx) { - Status::Unstable { gate, safe_to_expose_on_stable, is_function_call } - if self.tcx.features().enabled(gate) => - { + Status::Unstable { + gate, + safe_to_expose_on_stable, + is_function_call, + gate_already_checked, + } if gate_already_checked || self.tcx.features().enabled(gate) => { + if gate_already_checked { + assert!( + !safe_to_expose_on_stable, + "setting `gate_already_checked` without `safe_to_expose_on_stable` makes no sense" + ); + } // Generally this is allowed since the feature gate is enabled -- except // if this function wants to be safe-to-expose-on-stable. if !safe_to_expose_on_stable @@ -745,7 +754,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_op(ops::IntrinsicUnstable { name: intrinsic.name, feature, - const_stable: is_const_stable, + const_stable_indirect: is_const_stable, }); } Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { @@ -800,6 +809,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // We only honor `span.allows_unstable` aka `#[allow_internal_unstable]` if // the callee is safe to expose, to avoid bypassing recursive stability. + // This is not ideal since it means the user sees an error, not the macro + // author, but that's also the case if one forgets to set + // `#[allow_internal_unstable]` in the first place. Note that this cannot be + // integrated in the check below since we want to enforce + // `callee_safe_to_expose_on_stable` even if + // `!self.enforce_recursive_const_stability()`. if (self.span.allows_unstable(feature) || implied_feature.is_some_and(|f| self.span.allows_unstable(f))) && callee_safe_to_expose_on_stable @@ -830,15 +845,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { && issue == NonZero::new(27812) && self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked }; - // We do *not* honor this if we are in the "danger zone": we have to enforce - // recursive const-stability and the callee is not safe-to-expose. In that - // case we need `check_op` to do the check. - let danger_zone = !callee_safe_to_expose_on_stable - && self.enforce_recursive_const_stability(); - if danger_zone || !feature_enabled { + // Even if the feature is enabled, we still need check_op to double-check + // this if the callee is not safe to expose on stable. + if !feature_enabled || !callee_safe_to_expose_on_stable { self.check_op(ops::FnCallUnstable { def_id: callee, feature, + feature_enabled, safe_to_expose_on_stable: callee_safe_to_expose_on_stable, }); } |
