use GlobalId in eval_to_valtree query and introduce query for valtree_to_const_val
This commit is contained in:
parent
56d540e057
commit
96b36d6eb2
27 changed files with 541 additions and 245 deletions
|
@ -1,7 +1,7 @@
|
|||
use super::{AllocId, ConstAlloc, Pointer, Scalar};
|
||||
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty};
|
||||
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty, ValTree};
|
||||
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
|
||||
|
@ -35,6 +35,7 @@ TrivialTypeFoldableAndLiftImpls! {
|
|||
|
||||
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
||||
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
||||
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
|
||||
|
||||
pub fn struct_error<'tcx>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
|
|
|
@ -119,9 +119,9 @@ use crate::ty::{self, Instance, Ty, TyCtxt};
|
|||
|
||||
pub use self::error::{
|
||||
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
|
||||
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
|
||||
ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess,
|
||||
UnsupportedOpInfo,
|
||||
EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
|
||||
MachineStopType, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
|
||||
UninitBytesAccess, UnsupportedOpInfo,
|
||||
};
|
||||
|
||||
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
|
||||
|
|
|
@ -110,11 +110,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
|
||||
}
|
||||
|
||||
/// Destructure a constant ADT or array into its variant index and its field values.
|
||||
/// Destructure a type-level constant ADT or array into its variant index and its field values.
|
||||
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
|
||||
pub fn destructure_const(
|
||||
self,
|
||||
param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
|
||||
) -> mir::DestructuredConst<'tcx> {
|
||||
self.try_destructure_const(param_env_and_val).unwrap()
|
||||
}
|
||||
|
||||
/// Destructure a mir constant ADT or array into its variant index and its field values.
|
||||
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
|
||||
pub fn destructure_mir_constant(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
constant: mir::ConstantKind<'tcx>,
|
||||
) -> mir::DestructuredMirConstant<'tcx> {
|
||||
self.try_destructure_mir_constant(param_env.and(constant)).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
|
||||
|
||||
use crate::mir::coverage::{CodeRegion, CoverageKind};
|
||||
use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, Scalar};
|
||||
use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use crate::ty::adjustment::PointerCast;
|
||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
|
@ -3078,6 +3078,58 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env)
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let body_id = match tcx.hir().get(hir_id) {
|
||||
hir::Node::AnonConst(ac) => ac.body,
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id.to_def_id()),
|
||||
"from_inline_const can only process anonymous constants"
|
||||
),
|
||||
};
|
||||
let expr = &tcx.hir().body(body_id).value;
|
||||
let ty = tcx.typeck(def_id).node_type(hir_id);
|
||||
|
||||
let lit_input = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => {
|
||||
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
if let Some(lit_input) = lit_input {
|
||||
// If an error occurred, ignore that it's a literal and leave reporting the error up to
|
||||
// mir.
|
||||
match tcx.at(expr.span).lit_to_mir_constant(lit_input) {
|
||||
Ok(c) => return c,
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
|
||||
let parent_substs =
|
||||
tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
|
||||
let substs =
|
||||
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
|
||||
.substs;
|
||||
let uneval_const = tcx.mk_const(ty::ConstS {
|
||||
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
||||
substs,
|
||||
promoted: None,
|
||||
}),
|
||||
ty,
|
||||
});
|
||||
debug!(?uneval_const);
|
||||
debug_assert!(!uneval_const.has_free_regions());
|
||||
|
||||
Self::Ty(uneval_const)
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn from_opt_const_arg_anon_const(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Values computed by queries that use MIR.
|
||||
|
||||
use crate::mir::{Body, Promoted};
|
||||
use crate::mir::{self, Body, Promoted};
|
||||
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
|
||||
use rustc_data_structures::stable_map::FxHashMap;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
|
@ -413,13 +413,20 @@ pub enum ClosureOutlivesSubject<'tcx> {
|
|||
Region(ty::RegionVid),
|
||||
}
|
||||
|
||||
/// The constituent parts of an ADT or array.
|
||||
/// The constituent parts of a type level constant of kind ADT or array.
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct DestructuredConst<'tcx> {
|
||||
pub variant: Option<VariantIdx>,
|
||||
pub fields: &'tcx [ty::Const<'tcx>],
|
||||
}
|
||||
|
||||
/// The constituent parts of a mir constant of kind ADT or array.
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct DestructuredMirConstant<'tcx> {
|
||||
pub variant: Option<VariantIdx>,
|
||||
pub fields: &'tcx [mir::ConstantKind<'tcx>],
|
||||
}
|
||||
|
||||
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
|
||||
/// compiler option `-Cinstrument-coverage`). This information is generated by the
|
||||
/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
|
||||
|
|
|
@ -946,12 +946,12 @@ rustc_queries! {
|
|||
cache_on_disk_if { true }
|
||||
}
|
||||
|
||||
/// Convert an evaluated constant to a type level constant or
|
||||
/// Evaluate a constant and convert it to a type level constant or
|
||||
/// return `None` if that is not possible.
|
||||
query const_to_valtree(
|
||||
key: ty::ParamEnvAnd<'tcx, ConstAlloc<'tcx>>
|
||||
) -> Option<ty::ValTree<'tcx>> {
|
||||
desc { "destructure constant" }
|
||||
query eval_to_valtree(
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
|
||||
) -> EvalToValTreeResult<'tcx> {
|
||||
desc { "evaluate type-level constant" }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
|
@ -964,10 +964,14 @@ rustc_queries! {
|
|||
/// field values or return `None` if constant is invalid.
|
||||
///
|
||||
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
|
||||
query try_destructure_const(
|
||||
key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
|
||||
) -> Option<mir::DestructuredConst<'tcx>> {
|
||||
desc { "destructure constant" }
|
||||
query try_destructure_const(key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>) -> Option<mir::DestructuredConst<'tcx>> {
|
||||
desc { "destructure type level constant"}
|
||||
}
|
||||
|
||||
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
|
||||
/// and its field values.
|
||||
query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option<mir::DestructuredMirConstant<'tcx>> {
|
||||
desc { "destructure mir constant"}
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
|
@ -980,6 +984,15 @@ rustc_queries! {
|
|||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
||||
/// again.
|
||||
query deref_mir_constant(
|
||||
key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
|
||||
) -> mir::ConstantKind<'tcx> {
|
||||
desc { "deref constant" }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||
desc { "get a &core::panic::Location referring to a span" }
|
||||
}
|
||||
|
@ -991,6 +1004,10 @@ rustc_queries! {
|
|||
desc { "converting literal to const" }
|
||||
}
|
||||
|
||||
query lit_to_mir_constant(key: LitToConstInput<'tcx>) -> Result<mir::ConstantKind<'tcx>, LitToConstError> {
|
||||
desc { "converting literal to mir constant" }
|
||||
}
|
||||
|
||||
query check_match(key: DefId) {
|
||||
desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
|
|
|
@ -662,7 +662,7 @@ pub enum PatKind<'tcx> {
|
|||
/// * Opaque constants, that must not be matched structurally. So anything that does not derive
|
||||
/// `PartialEq` and `Eq`.
|
||||
Constant {
|
||||
value: ty::Const<'tcx>,
|
||||
value: mir::ConstantKind<'tcx>,
|
||||
},
|
||||
|
||||
Range(PatRange<'tcx>),
|
||||
|
@ -692,8 +692,8 @@ pub enum PatKind<'tcx> {
|
|||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
|
||||
pub struct PatRange<'tcx> {
|
||||
pub lo: ty::Const<'tcx>,
|
||||
pub hi: ty::Const<'tcx>,
|
||||
pub lo: mir::ConstantKind<'tcx>,
|
||||
pub hi: mir::ConstantKind<'tcx>,
|
||||
pub end: RangeEnd,
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,10 @@ use crate::middle::resolve_lifetime::{
|
|||
use crate::middle::stability::{self, DeprecationEntry};
|
||||
use crate::mir;
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
|
||||
use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
|
||||
use crate::mir::interpret::{
|
||||
ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
|
||||
};
|
||||
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use crate::mir::mono::CodegenUnit;
|
||||
use crate::thir;
|
||||
use crate::traits::query::{
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::ty::layout::IntegerExt;
|
|||
use crate::ty::query::TyCtxtAt;
|
||||
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||
use crate::ty::{
|
||||
self, Const, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
|
||||
self, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
|
||||
TypeFoldable,
|
||||
};
|
||||
use rustc_apfloat::Float as _;
|
||||
|
@ -689,7 +689,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
|
|||
impl<'tcx> Ty<'tcx> {
|
||||
/// Returns the maximum value for the given numeric type (including `char`s)
|
||||
/// or returns `None` if the type is not numeric.
|
||||
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<Const<'tcx>> {
|
||||
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
|
||||
let val = match self.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let (size, signed) = int_size_and_signed(tcx, self);
|
||||
|
@ -704,12 +704,13 @@ impl<'tcx> Ty<'tcx> {
|
|||
}),
|
||||
_ => None,
|
||||
};
|
||||
val.map(|v| Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
|
||||
|
||||
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
|
||||
}
|
||||
|
||||
/// Returns the minimum value for the given numeric type (including `char`s)
|
||||
/// or returns `None` if the type is not numeric.
|
||||
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<Const<'tcx>> {
|
||||
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
|
||||
let val = match self.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let (size, signed) = int_size_and_signed(tcx, self);
|
||||
|
@ -723,7 +724,8 @@ impl<'tcx> Ty<'tcx> {
|
|||
}),
|
||||
_ => None,
|
||||
};
|
||||
val.map(|v| Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
|
||||
|
||||
val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` are *moved* or *copied*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue