make it possible for outside crates to inspect a mir::ConstValue with the interpreter
This commit is contained in:
parent
5af2130440
commit
9eabdc2a4c
@ -3,10 +3,11 @@ use either::{Left, Right};
|
|||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
|
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
|
||||||
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
|
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
|
||||||
|
use rustc_middle::query::TyCtxtAt;
|
||||||
use rustc_middle::traits::Reveal;
|
use rustc_middle::traits::Reveal;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::abi::{self, Abi};
|
use rustc_target::abi::{self, Abi};
|
||||||
@ -87,13 +88,16 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
|
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
|
||||||
/// `simd_shuffle` and const patterns in match arms. It never performs alignment checks.
|
/// `simd_shuffle` and const patterns in match arms.
|
||||||
|
///
|
||||||
|
/// This should *not* be used to do any actual interpretation. In particular, alignment checks are
|
||||||
|
/// turned off!
|
||||||
///
|
///
|
||||||
/// The function containing the `match` that is currently being analyzed may have generic bounds
|
/// The function containing the `match` that is currently being analyzed may have generic bounds
|
||||||
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
|
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
|
||||||
/// of a function's generic parameter will require knowledge about the bounds on the generic
|
/// of a function's generic parameter will require knowledge about the bounds on the generic
|
||||||
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
|
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
|
||||||
pub(crate) fn mk_eval_cx<'mir, 'tcx>(
|
pub(crate) fn mk_eval_cx_to_read_const_val<'mir, 'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
root_span: Span,
|
root_span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -108,6 +112,19 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create an interpreter context to inspect the given `ConstValue`.
|
||||||
|
/// Returns both the context and an `OpTy` that represents the constant.
|
||||||
|
pub fn mk_eval_cx_for_const_val<'mir, 'tcx>(
|
||||||
|
tcx: TyCtxtAt<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
val: mir::ConstValue<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> Option<(CompileTimeEvalContext<'mir, 'tcx>, OpTy<'tcx>)> {
|
||||||
|
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
|
||||||
|
let op = ecx.const_val_to_op(val, ty, None).ok()?;
|
||||||
|
Some((ecx, op))
|
||||||
|
}
|
||||||
|
|
||||||
/// This function converts an interpreter value into a MIR constant.
|
/// This function converts an interpreter value into a MIR constant.
|
||||||
///
|
///
|
||||||
/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
|
/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
|
||||||
@ -203,7 +220,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
|
|||||||
let def_id = cid.instance.def.def_id();
|
let def_id = cid.instance.def.def_id();
|
||||||
let is_static = tcx.is_static(def_id);
|
let is_static = tcx.is_static(def_id);
|
||||||
// This is just accessing an already computed constant, so no need to check alignment here.
|
// This is just accessing an already computed constant, so no need to check alignment here.
|
||||||
let ecx = mk_eval_cx(
|
let ecx = mk_eval_cx_to_read_const_val(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.def_span(key.value.instance.def_id()),
|
tcx.def_span(key.value.instance.def_id()),
|
||||||
key.param_env,
|
key.param_env,
|
||||||
|
@ -47,8 +47,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
|
|||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Option<mir::DestructuredConstant<'tcx>> {
|
) -> Option<mir::DestructuredConstant<'tcx>> {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let ecx = mk_eval_cx(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
|
let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?;
|
||||||
let op = ecx.const_val_to_op(val, ty, None).ok()?;
|
|
||||||
|
|
||||||
// We go to `usize` as we cannot allocate anything bigger anyway.
|
// We go to `usize` as we cannot allocate anything bigger anyway.
|
||||||
let (field_count, variant, down) = match ty.kind() {
|
let (field_count, variant, down) = match ty.kind() {
|
||||||
|
@ -5,7 +5,7 @@ use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
|
|||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_target::abi::{Abi, VariantIdx};
|
use rustc_target::abi::{Abi, VariantIdx};
|
||||||
|
|
||||||
use super::eval_queries::{mk_eval_cx, op_to_const};
|
use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
|
||||||
use super::machine::CompileTimeEvalContext;
|
use super::machine::CompileTimeEvalContext;
|
||||||
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
||||||
use crate::const_eval::CanAccessMutGlobal;
|
use crate::const_eval::CanAccessMutGlobal;
|
||||||
@ -223,7 +223,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
|||||||
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
|
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
|
||||||
|
|
||||||
// FIXME Need to provide a span to `eval_to_valtree`
|
// FIXME Need to provide a span to `eval_to_valtree`
|
||||||
let ecx = mk_eval_cx(
|
let ecx = mk_eval_cx_to_read_const_val(
|
||||||
tcx,
|
tcx,
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
param_env,
|
param_env,
|
||||||
@ -287,7 +287,8 @@ pub fn valtree_to_const_value<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Ref(_, inner_ty, _) => {
|
ty::Ref(_, inner_ty, _) => {
|
||||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
|
let mut ecx =
|
||||||
|
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
|
||||||
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
|
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
|
||||||
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
|
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
|
||||||
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
|
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
|
||||||
@ -314,7 +315,8 @@ pub fn valtree_to_const_value<'tcx>(
|
|||||||
bug!("could not find non-ZST field during in {layout:#?}");
|
bug!("could not find non-ZST field during in {layout:#?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
|
let mut ecx =
|
||||||
|
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
|
||||||
|
|
||||||
// Need to create a place for this valtree.
|
// Need to create a place for this valtree.
|
||||||
let place = create_valtree_place(&mut ecx, layout, valtree);
|
let place = create_valtree_place(&mut ecx, layout, valtree);
|
||||||
|
@ -6,7 +6,7 @@ use rustc_middle::ty::layout::LayoutOf;
|
|||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_type_ir::Mutability;
|
use rustc_type_ir::Mutability;
|
||||||
|
|
||||||
use crate::const_eval::{mk_eval_cx, CanAccessMutGlobal, CompileTimeEvalContext};
|
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext};
|
||||||
use crate::interpret::*;
|
use crate::interpret::*;
|
||||||
|
|
||||||
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
||||||
@ -57,7 +57,12 @@ pub(crate) fn const_caller_location_provider(
|
|||||||
col: u32,
|
col: u32,
|
||||||
) -> mir::ConstValue<'_> {
|
) -> mir::ConstValue<'_> {
|
||||||
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
||||||
let mut ecx = mk_eval_cx(tcx.tcx, tcx.span, ty::ParamEnv::reveal_all(), CanAccessMutGlobal::No);
|
let mut ecx = mk_eval_cx_to_read_const_val(
|
||||||
|
tcx.tcx,
|
||||||
|
tcx.span,
|
||||||
|
ty::ParamEnv::reveal_all(),
|
||||||
|
CanAccessMutGlobal::No,
|
||||||
|
);
|
||||||
|
|
||||||
let loc_place = alloc_caller_location(&mut ecx, file, line, col);
|
let loc_place = alloc_caller_location(&mut ecx, file, line, col);
|
||||||
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
|
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user