From e2386270df9d619bb6d3d62664e89c632baeb6cb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 10 Oct 2023 08:52:21 +0000 Subject: [PATCH] Return ConstAllocation from eval_static_initializer query directly --- .../src/const_eval/eval_queries.rs | 26 +++++++++++++++ compiler/rustc_const_eval/src/lib.rs | 8 +---- .../src/rmeta/decoder/cstore_impl.rs | 6 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +-- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- .../rustc_middle/src/mir/interpret/error.rs | 4 +-- .../rustc_middle/src/mir/interpret/queries.rs | 33 +------------------ compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 ++ compiler/rustc_middle/src/query/erase.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- .../recursive-zst-static.default.stderr | 9 ++--- .../recursive-zst-static.unleash.stderr | 9 ++--- .../write-to-static-mut-in-static.stderr | 9 ++--- .../recursive-static-definition.stderr | 9 ++--- tests/ui/treat-err-as-bug/err.rs | 2 +- tests/ui/treat-err-as-bug/err.stderr | 4 +-- 18 files changed, 53 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index c55d899e4d5..05baf102d88 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -8,6 +8,7 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::LocalDefId; use rustc_span::Span; use rustc_target::abi::{self, Abi}; @@ -249,11 +250,36 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key)) } +#[instrument(skip(tcx), level = "debug")] +pub fn eval_static_initializer_provider<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> { + assert!(tcx.is_static(def_id.to_def_id())); + + let instance = ty::Instance::mono(tcx, def_id.to_def_id()); + let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None }; + let ecx = InterpCx::new( + tcx, + tcx.def_span(def_id), + ty::ParamEnv::reveal_all(), + // Statics (and promoteds inside statics) may access other statics, because unlike consts + // they do not have to behave "as if" they were evaluated at runtime. + CompileTimeInterpreter::new(CanAccessMutGlobal::Yes, CheckAlignment::Error), + ); + let alloc_id = eval_in_interpreter(ecx, cid, true)?.alloc_id; + let alloc = tcx.global_alloc(alloc_id).unwrap_memory(); + Ok(alloc) +} + #[instrument(skip(tcx), level = "debug")] pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { + // This shouldn't be used for statics, since statics are conceptually places, + // not values -- so what we do here could break pointer identity. + assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())); // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of // opaque types. This is needed for trivial things like `size_of`, but also for using associated // types that are not specified in the opaque type. diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 42c86942a43..e33f374c359 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -40,13 +40,7 @@ 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.to_def_id())); - let instance = ty::Instance::mono(tcx, def_id.to_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.eval_static_initializer = const_eval::eval_static_initializer_provider; 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_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index e27a21490d3..178bfc3a380 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -250,14 +250,14 @@ provide! { tcx, def_id, other, cdata, fn_arg_names => { table } coroutine_kind => { table_direct } coroutine_for_closure => { table } - eval_static_initializer_raw => { + eval_static_initializer => { Ok(cdata .root .tables - .eval_static_initializer_raw + .eval_static_initializer .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) - .unwrap_or_else(|| panic!("{def_id:?} does not have eval_static_initializer_raw"))) + .unwrap_or_else(|| panic!("{def_id:?} does not have eval_static_initializer"))) } trait_def => { table } deduced_param_attrs => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index eee8127b055..6f908f7752a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1454,8 +1454,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Static(_) = def_kind { if !self.tcx.is_foreign_item(def_id) { - let data = self.tcx.eval_static_initializer_raw(def_id).unwrap(); - record!(self.tables.eval_static_initializer_raw[def_id] <- data); + let data = self.tcx.eval_static_initializer(def_id).unwrap(); + record!(self.tables.eval_static_initializer[def_id] <- data); } } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 14e48ea0a40..eac78a3cd7c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -443,7 +443,7 @@ define_tables! { fn_arg_names: Table>, coroutine_kind: Table, coroutine_for_closure: Table, - eval_static_initializer_raw: Table>, + eval_static_initializer: Table>>, trait_def: Table>, trait_item_def_id: Table, expn_that_defined: Table>, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 6e06527100c..9d4ec7d25bb 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -1,4 +1,4 @@ -use super::{AllocId, AllocRange, Pointer, Scalar}; +use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; use crate::error; use crate::mir::{ConstAlloc, ConstValue}; @@ -83,7 +83,7 @@ impl Into for ReportedErrorInfo { TrivialTypeTraversalImpls! { ErrorHandled } pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; -pub type EvalStaticInitializerRawResult = Result; +pub type EvalStaticInitializerRawResult<'tcx> = Result, ErrorHandled>; 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/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 6256de390af..643b61c1de3 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,7 +1,7 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}; use crate::mir; -use crate::query::{TyCtxtAt, TyCtxtEnsure}; +use crate::query::TyCtxtEnsure; use crate::ty::visit::TypeVisitableExt; use crate::ty::GenericArgs; use crate::ty::{self, TyCtxt}; @@ -173,30 +173,6 @@ impl<'tcx> TyCtxt<'tcx> { self.eval_to_valtree(inputs) } } - - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - #[inline(always)] - pub fn eval_static_initializer( - self, - def_id: DefId, - ) -> Result, ErrorHandled> { - self.at(DUMMY_SP).eval_static_initializer(def_id) - } -} - -impl<'tcx> TyCtxtAt<'tcx> { - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - /// - /// The span is entirely ignored here, but still helpful for better query cycle errors. - pub fn eval_static_initializer( - self, - def_id: DefId, - ) -> Result, ErrorHandled> { - trace!("eval_static_initializer: Need to compute {:?}", def_id); - assert!(self.is_static(def_id)); - let alloc_id = self.eval_static_initializer_raw(def_id)?; - Ok(self.global_alloc(alloc_id).unwrap_memory()) - } } impl<'tcx> TyCtxtEnsure<'tcx> { @@ -218,11 +194,4 @@ impl<'tcx> TyCtxtEnsure<'tcx> { let inputs = self.tcx.erase_regions(param_env.and(cid)); self.eval_to_const_value_raw(inputs) } - - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - 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)); - self.eval_static_initializer_raw(def_id); - } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e22d5228628..3017f912ef0 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2,7 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html -use crate::mir::interpret::{AllocRange, ConstAllocation, Scalar}; +use crate::mir::interpret::{AllocRange, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a011f6114de..5638b575b31 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -4,6 +4,8 @@ use std::fs; use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; +use crate::mir::interpret::ConstAllocation; + use super::graphviz::write_mir_fn_graphviz; use rustc_ast::InlineAsmTemplatePiece; use rustc_middle::mir::interpret::{ diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index cc2c921ef49..7ac7fa0ac33 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -277,7 +277,6 @@ 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, @@ -338,6 +337,7 @@ tcx_lifetime! { rustc_middle::mir::ConstValue, rustc_middle::mir::interpret::GlobalId, rustc_middle::mir::interpret::LitToConstInput, + rustc_middle::mir::interpret::EvalStaticInitializerRawResult, rustc_middle::traits::query::MethodAutoderefStepsResult, rustc_middle::traits::query::type_op::AscribeUserType, rustc_middle::traits::query::type_op::Eq, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d0983546499..a7f4e75e214 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1073,7 +1073,7 @@ rustc_queries! { } /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - query eval_static_initializer_raw(key: DefId) -> EvalStaticInitializerRawResult { + query eval_static_initializer(key: DefId) -> EvalStaticInitializerRawResult<'tcx> { desc { |tcx| "evaluating initializer of static `{}`", tcx.def_path_str(key) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 2f6121d0e62..22f0574d614 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -63,7 +63,6 @@ trivially_parameterized_over_tcx! { crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, - crate::mir::interpret::AllocId, ty::AssocItemContainer, ty::Asyncness, ty::DeducedParamAttrs, @@ -127,6 +126,7 @@ parameterized_over_tcx! { crate::middle::exported_symbols::ExportedSymbol, crate::mir::Body, crate::mir::CoroutineLayout, + crate::mir::interpret::ConstAllocation, ty::Ty, ty::FnSig, ty::GenericPredicates, diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr index b2d5d50da62..9e31209204b 100644 --- a/tests/ui/consts/recursive-zst-static.default.stderr +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -1,15 +1,10 @@ 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 again requires evaluating initializer of static `FOO`, completing the cycle + | + = note: ...which immediately requires evaluating initializer of static `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr index b2d5d50da62..9e31209204b 100644 --- a/tests/ui/consts/recursive-zst-static.unleash.stderr +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -1,15 +1,10 @@ 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 again requires evaluating initializer of static `FOO`, completing the cycle + | + = note: ...which immediately requires evaluating initializer of static `FOO` again 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 dd0b05d9d44..23dd1346ad9 100644 --- a/tests/ui/consts/write-to-static-mut-in-static.stderr +++ b/tests/ui/consts/write-to-static-mut-in-static.stderr @@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ modifying a static's initial value from another static's initializer 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 again requires evaluating initializer of static `C`, completing the cycle + | + = note: ...which immediately requires evaluating initializer of static `C` again 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.stderr b/tests/ui/recursion/recursive-static-definition.stderr index 83459017634..f071e501e38 100644 --- a/tests/ui/recursion/recursive-static-definition.stderr +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -1,15 +1,10 @@ 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 again requires evaluating initializer of static `FOO`, completing the cycle + | + = note: ...which immediately requires evaluating initializer of static `FOO` again 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.rs b/tests/ui/treat-err-as-bug/err.rs index 4090a706f99..74992497dab 100644 --- a/tests/ui/treat-err-as-bug/err.rs +++ b/tests/ui/treat-err-as-bug/err.rs @@ -1,7 +1,7 @@ // compile-flags: -Ztreat-err-as-bug // failure-status: 101 // error-pattern: aborting due to `-Z treat-err-as-bug=1` -// error-pattern: [eval_to_allocation_raw] const-evaluating + checking `C` +// error-pattern: [eval_static_initializer] evaluating initializer of static `C` // normalize-stderr-test "note: .*\n\n" -> "" // normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> "" // rustc-env:RUST_BACKTRACE=0 diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index d4ad63a4c92..ca04ee9e0cf 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -7,6 +7,6 @@ LL | pub static C: u32 = 0 - 1; error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [eval_to_allocation_raw] const-evaluating + checking `C` -#1 [eval_static_initializer_raw] evaluating initializer of static `C` +#0 [eval_static_initializer] evaluating initializer of static `C` +#1 [lint_mod] linting top-level module end of query stack