diff options
| author | Michael Goulet <michael@errs.io> | 2024-10-30 18:47:54 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-11-01 16:13:30 +0000 |
| commit | 57f2e12f4aafb2c37f45090be97c68c5020c938f (patch) | |
| tree | 87ff58d0bd558cd2d82a867e52da9ba010674e92 /compiler/rustc_const_eval/src | |
| parent | e319838e8d160f965f4329580bf3049d075fea03 (diff) | |
| download | rust-57f2e12f4aafb2c37f45090be97c68c5020c938f.tar.gz rust-57f2e12f4aafb2c37f45090be97c68c5020c938f.zip | |
Completely deny calling functions with const conditions in MIR const check unless const_trait_impl is enabled
This will help us make sure that we never leak any conditionally const functions into stable.
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/check_consts/check.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/check_consts/ops.rs | 11 |
2 files changed, 22 insertions, 18 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 779de61edc3..303c490d827 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -363,7 +363,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } fn revalidate_conditional_constness( - &self, + &mut self, callee: DefId, callee_args: ty::GenericArgsRef<'tcx>, call_source: CallSource, @@ -374,11 +374,24 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return; } + let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args); + // If there are any const conditions on this fn and `const_trait_impl` + // is not enabled, simply bail. We shouldn't be able to call conditionally + // const functions on stable. + if !const_conditions.is_empty() && !tcx.features().const_trait_impl() { + self.check_op(ops::FnCallNonConst { + callee, + args: callee_args, + span: call_span, + call_source, + feature: Some(sym::const_trait_impl), + }); + return; + } + let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args); - let body_id = self.body.source.def_id().expect_local(); let host_polarity = match self.const_kind() { hir::ConstContext::ConstFn => ty::BoundConstness::Maybe, @@ -621,7 +634,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }; let ConstCx { tcx, body, param_env, .. } = *self.ccx; - let caller = self.def_id(); let fn_ty = func.ty(body, tcx); @@ -639,12 +651,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } }; - self.revalidate_conditional_constness( - callee, - fn_args, - call_source, - terminator.source_info.span, - ); + self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span); let mut is_trait = false; // Attempting to call a trait method? @@ -684,7 +691,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { None }; self.check_op(ops::FnCallNonConst { - caller, callee, args: fn_args, span: *fn_span, @@ -774,7 +780,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Trait functions are not `const fn` so we have to skip them here. if !tcx.is_const_fn(callee) && !is_trait { self.check_op(ops::FnCallNonConst { - caller, callee, args: fn_args, span: *fn_span, diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 961a27ae9ba..ce36701a942 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,6 +1,5 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use hir::def_id::LocalDefId; use hir::{ConstContext, LangItem}; use rustc_errors::Diag; use rustc_errors::codes::*; @@ -74,7 +73,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { /// A function call where the callee is not marked as `const`. #[derive(Debug, Clone, Copy)] pub(crate) struct FnCallNonConst<'tcx> { - pub caller: LocalDefId, pub callee: DefId, pub args: GenericArgsRef<'tcx>, pub span: Span, @@ -87,8 +85,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { - let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self; - let ConstCx { tcx, param_env, body, .. } = *ccx; + let FnCallNonConst { callee, args, span, call_source, feature } = *self; + let ConstCx { tcx, param_env, .. } = *ccx; + let caller = ccx.def_id(); let diag_trait = |err, self_ty: Ty<'_>, trait_id| { let trait_ref = TraitRef::from_method(tcx, trait_id, args); @@ -116,7 +115,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx)); + let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let implsrc = selcx.select(&obligation); @@ -289,7 +288,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { if let Some(feature) = feature { ccx.tcx.disabled_nightly_features( &mut err, - body.source.def_id().as_local().map(|local| ccx.tcx.local_def_id_to_hir_id(local)), + Some(ccx.tcx.local_def_id_to_hir_id(caller)), [(String::new(), feature)], ); } |
