Add new query just for static initializers
This commit is contained in:
parent
fc9d1a8133
commit
95004e5ae2
13 changed files with 65 additions and 43 deletions
|
@ -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();
|
||||
|
|
|
@ -83,6 +83,7 @@ impl Into<ErrorGuaranteed> for ReportedErrorInfo {
|
|||
TrivialTypeTraversalImpls! { ErrorHandled }
|
||||
|
||||
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
||||
pub type EvalStaticInitializerRawResult = Result<AllocId, ErrorHandled>;
|
||||
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
||||
/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
|
||||
/// This is needed in `thir::pattern::lower_inline_const`.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -194,22 +194,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
|||
) -> Result<mir::ConstAllocation<'tcx>, 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<mir::ConstAllocation<'tcx>, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue