diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 839cfd8d85a..4a00b9a5999 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -40,6 +40,13 @@ pub fn provide(providers: &mut Providers) { const_eval::provide(providers); providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider; providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; + providers.eval_static_initializer_raw = |tcx, def_id| { + assert!(tcx.is_static(def_id)); + let instance = ty::Instance::mono(tcx, def_id); + let gid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None }; + let param_env = ty::ParamEnv::reveal_all(); + Ok(tcx.eval_to_allocation_raw(param_env.and(gid))?.alloc_id) + }; providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider; providers.eval_to_valtree = |tcx, param_env_and_value| { let (param_env, raw) = param_env_and_value.into_parts(); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index a1cdc794749..6e06527100c 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -83,6 +83,7 @@ impl Into for ReportedErrorInfo { TrivialTypeTraversalImpls! { ErrorHandled } pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; +pub type EvalStaticInitializerRawResult = Result; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; /// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed. /// This is needed in `thir::pattern::lower_inline_const`. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 0da3524e055..ec2af393639 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -142,11 +142,12 @@ use crate::ty::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ - BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, - EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, - InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, Misalignment, PointerKind, - ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, - UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind, + BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult, + EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, + InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo, + MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, + ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, + ValidationErrorKind, }; pub use self::value::Scalar; diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index e8aca5f2e7d..6256de390af 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -194,22 +194,8 @@ impl<'tcx> TyCtxtAt<'tcx> { ) -> Result, ErrorHandled> { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.is_static(def_id)); - let instance = ty::Instance::mono(*self, def_id); - let gid = GlobalId { instance, promoted: None }; - self.eval_to_allocation(gid, ty::ParamEnv::reveal_all()) - } - - /// Evaluate anything constant-like, returning the allocation of the final memory. - /// - /// The span is entirely ignored here, but still helpful for better query cycle errors. - fn eval_to_allocation( - self, - gid: GlobalId<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Result, ErrorHandled> { - trace!("eval_to_allocation: Need to compute {:?}", gid); - let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; - Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) + let alloc_id = self.eval_static_initializer_raw(def_id)?; + Ok(self.global_alloc(alloc_id).unwrap_memory()) } } @@ -237,10 +223,6 @@ impl<'tcx> TyCtxtEnsure<'tcx> { pub fn eval_static_initializer(self, def_id: DefId) { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.tcx.is_static(def_id)); - let instance = ty::Instance::mono(self.tcx, def_id); - let gid = GlobalId { instance, promoted: None }; - let param_env = ty::ParamEnv::reveal_all(); - trace!("eval_to_allocation: Need to compute {:?}", gid); - self.eval_to_allocation_raw(param_env.and(gid)) + self.eval_static_initializer_raw(def_id); } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5666a59e38e..cc2c921ef49 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -277,6 +277,7 @@ trivial! { rustc_middle::mir::interpret::CtfeProvenance, rustc_middle::mir::interpret::ErrorHandled, rustc_middle::mir::interpret::LitToConstError, + rustc_middle::mir::interpret::EvalStaticInitializerRawResult, rustc_middle::thir::ExprId, rustc_middle::traits::CodegenObligationError, rustc_middle::traits::EvaluationResult, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 60d195e4d3e..23d486eed52 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,7 +20,8 @@ use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; use crate::mir::interpret::GlobalId; use crate::mir::interpret::{ - EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, + EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, + EvalToValTreeResult, }; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; @@ -1061,7 +1062,7 @@ rustc_queries! { /// Evaluates a constant and returns the computed allocation. /// - /// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper. + /// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead. query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> EvalToAllocationRawResult<'tcx> { desc { |tcx| @@ -1071,6 +1072,15 @@ rustc_queries! { cache_on_disk_if { true } } + /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + query eval_static_initializer_raw(key: DefId) -> EvalStaticInitializerRawResult { + desc { |tcx| + "evaluating initializer of static `{}`", + tcx.def_path_str(key) + } + cache_on_disk_if { key.is_local() } + } + /// Evaluates const items or anonymous constants /// (such as enum variant explicit discriminants or array lengths) /// into a representation suitable for the type system and const generics. diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr index 5b4a0418b1e..b2d5d50da62 100644 --- a/tests/ui/consts/recursive-zst-static.default.stderr +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -1,10 +1,15 @@ -error[E0391]: cycle detected when const-evaluating + checking `FOO` +error[E0391]: cycle detected when evaluating initializer of static `FOO` + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - | - = note: ...which immediately requires const-evaluating + checking `FOO` again + = note: ...which again requires evaluating initializer of static `FOO`, completing the cycle note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/recursive-zst-static.rs b/tests/ui/consts/recursive-zst-static.rs index 4e61634b349..14de00bad8a 100644 --- a/tests/ui/consts/recursive-zst-static.rs +++ b/tests/ui/consts/recursive-zst-static.rs @@ -7,7 +7,7 @@ // can depend on this fact and will thus do unsound things when it is violated. // See https://github.com/rust-lang/rust/issues/71078 for more details. -static FOO: () = FOO; //~ cycle detected when const-evaluating + checking `FOO` +static FOO: () = FOO; //~ cycle detected when evaluating initializer of static `FOO` fn main() { FOO diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr index 5b4a0418b1e..b2d5d50da62 100644 --- a/tests/ui/consts/recursive-zst-static.unleash.stderr +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -1,10 +1,15 @@ -error[E0391]: cycle detected when const-evaluating + checking `FOO` +error[E0391]: cycle detected when evaluating initializer of static `FOO` + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - | - = note: ...which immediately requires const-evaluating + checking `FOO` again + = note: ...which again requires evaluating initializer of static `FOO`, completing the cycle note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/write-to-static-mut-in-static.stderr b/tests/ui/consts/write-to-static-mut-in-static.stderr index caee433a681..dd0b05d9d44 100644 --- a/tests/ui/consts/write-to-static-mut-in-static.stderr +++ b/tests/ui/consts/write-to-static-mut-in-static.stderr @@ -4,13 +4,18 @@ error[E0080]: could not evaluate static initializer LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ modifying a static's initial value from another static's initializer -error[E0391]: cycle detected when const-evaluating + checking `C` +error[E0391]: cycle detected when evaluating initializer of static `C` + --> $DIR/write-to-static-mut-in-static.rs:5:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `C`... --> $DIR/write-to-static-mut-in-static.rs:5:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ - | - = note: ...which immediately requires const-evaluating + checking `C` again + = note: ...which again requires evaluating initializer of static `C`, completing the cycle note: cycle used when linting top-level module --> $DIR/write-to-static-mut-in-static.rs:1:1 | diff --git a/tests/ui/recursion/recursive-static-definition.rs b/tests/ui/recursion/recursive-static-definition.rs index f59ef7316d8..74a094a9b01 100644 --- a/tests/ui/recursion/recursive-static-definition.rs +++ b/tests/ui/recursion/recursive-static-definition.rs @@ -1,4 +1,4 @@ pub static FOO: u32 = FOO; -//~^ ERROR cycle detected when const-evaluating + checking `FOO` +//~^ ERROR cycle detected when evaluating initializer of static `FOO` fn main() {} diff --git a/tests/ui/recursion/recursive-static-definition.stderr b/tests/ui/recursion/recursive-static-definition.stderr index 4fc3ee68ebc..83459017634 100644 --- a/tests/ui/recursion/recursive-static-definition.stderr +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -1,10 +1,15 @@ -error[E0391]: cycle detected when const-evaluating + checking `FOO` +error[E0391]: cycle detected when evaluating initializer of static `FOO` + --> $DIR/recursive-static-definition.rs:1:1 + | +LL | pub static FOO: u32 = FOO; + | ^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-static-definition.rs:1:23 | LL | pub static FOO: u32 = FOO; | ^^^ - | - = note: ...which immediately requires const-evaluating + checking `FOO` again + = note: ...which again requires evaluating initializer of static `FOO`, completing the cycle note: cycle used when linting top-level module --> $DIR/recursive-static-definition.rs:1:1 | diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index f1b61c3607b..d4ad63a4c92 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -8,5 +8,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `C` -#1 [lint_mod] linting top-level module +#1 [eval_static_initializer_raw] evaluating initializer of static `C` end of query stack