diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 56 | ||||
-rw-r--r-- | compiler/rustc_middle/src/ty/consts/kind.rs | 56 | ||||
-rw-r--r-- | compiler/rustc_middle/src/ty/consts/valtree.rs | 5 |
3 files changed, 44 insertions, 73 deletions
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index f8792edc0..f998e6083 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,9 +1,6 @@ use crate::mir::interpret::LitToConstInput; use crate::mir::ConstantKind; -use crate::ty::{ - self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, - TyCtxt, TypeVisitable, -}; +use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -41,7 +38,7 @@ pub struct ConstS<'tcx> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstS<'_>, 48); +static_assert_size!(ConstS<'_>, 40); impl<'tcx> Const<'tcx> { #[inline] @@ -65,8 +62,6 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, ) -> Self { - debug!("Const::from_anon_const(def={:?})", def); - let body_id = match tcx.hir().get_by_def_id(def.did) { hir::Node::AnonConst(ac) => ac.body, _ => span_bug!( @@ -83,10 +78,9 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, None => tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - promoted: None, }), ty, }), @@ -153,46 +147,6 @@ impl<'tcx> Const<'tcx> { } } - pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { - debug!("Const::from_inline_const(def_id={:?})", def_id); - - 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 ret = match Self::try_eval_lit_or_param(tcx, ty, expr) { - Some(v) => v, - None => { - 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 = - InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty }) - .substs; - tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: ty::WithOptConstParam::unknown(def_id).to_global(), - substs, - promoted: None, - }), - ty, - }) - } - }; - debug_assert!(!ret.has_free_regions()); - ret - } - /// Interns the given value as a constant. #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self { @@ -309,6 +263,10 @@ impl<'tcx> Const<'tcx> { self.try_eval_usize(tcx, param_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } + + pub fn is_ct_infer(self) -> bool { + matches!(self.kind(), ty::ConstKind::Infer(_)) + } } pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index cb0137d2e..4ab761e07 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,50 +1,52 @@ use std::convert::TryInto; +use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; -use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; use crate::ty::{self, TyCtxt, TypeVisitable}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_target::abi::Size; use super::ScalarInt; -/// An unevaluated, potentially generic, constant. + +/// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] -#[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx, P = Option<Promoted>> { +#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct UnevaluatedConst<'tcx> { pub def: ty::WithOptConstParam<DefId>, pub substs: SubstsRef<'tcx>, - pub promoted: P, } -impl<'tcx> Unevaluated<'tcx> { - #[inline] - pub fn shrink(self) -> Unevaluated<'tcx, ()> { - debug_assert_eq!(self.promoted, None); - Unevaluated { def: self.def, substs: self.substs, promoted: () } +impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + format!("{:?}", self).into_diagnostic_arg() } } -impl<'tcx> Unevaluated<'tcx, ()> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn expand(self) -> Unevaluated<'tcx> { - Unevaluated { def: self.def, substs: self.substs, promoted: None } + pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { + mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None } } } -impl<'tcx, P: Default> Unevaluated<'tcx, P> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { - Unevaluated { def, substs, promoted: Default::default() } + pub fn new( + def: ty::WithOptConstParam<DefId>, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs } } } /// Represents a constant in Rust. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(Hash, HashStable)] +#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ty::ParamConst), @@ -60,7 +62,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(Unevaluated<'tcx>), + Unevaluated(UnevaluatedConst<'tcx>), /// Used to hold computed value. Value(ty::ValTree<'tcx>), @@ -71,7 +73,7 @@ pub enum ConstKind<'tcx> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstKind<'_>, 40); +static_assert_size!(ConstKind<'_>, 32); impl<'tcx> ConstKind<'tcx> { #[inline] @@ -107,7 +109,6 @@ impl<'tcx> ConstKind<'tcx> { /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -#[derive(HashStable)] pub enum InferConst<'tcx> { /// Infer the value of the const. Var(ty::ConstVid<'tcx>), @@ -115,6 +116,15 @@ pub enum InferConst<'tcx> { Fresh(u32), } +impl<CTX> HashStable<CTX> for InferConst<'_> { + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + match self { + InferConst::Var(_) => panic!("const variables should not be hashed: {self:?}"), + InferConst::Fresh(i) => i.hash_stable(hcx, hasher), + } + } +} + enum EvalMode { Typeck, Mir, @@ -174,6 +184,7 @@ impl<'tcx> ConstKind<'tcx> { param_env: ParamEnv<'tcx>, eval_mode: EvalMode, ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> { + assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; @@ -194,10 +205,9 @@ impl<'tcx> ConstKind<'tcx> { // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. let param_env_and = if param_env_and.needs_infer() { - tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { + tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst { def: unevaluated.def, substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), - promoted: unevaluated.promoted, }) } else { param_env_and @@ -221,7 +231,7 @@ impl<'tcx> ConstKind<'tcx> { } } EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated, None) { + match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 93707bb18..a803fca0d 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -18,7 +18,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; /// `ValTree` does not have this problem with representation, as it only contains integers or /// lists of (nested) `ValTree`. pub enum ValTree<'tcx> { - /// ZSTs, integers, `bool`, `char` are represented as scalars. + /// integers, `bool`, `char` are represented as scalars. /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values /// of these types have the same representation. Leaf(ScalarInt), @@ -27,8 +27,11 @@ pub enum ValTree<'tcx> { // dont use SliceOrStr for now /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by /// listing their fields' values in order. + /// /// Enums are represented by storing their discriminant as a field, followed by all /// the fields of the variant. + /// + /// ZST types are represented as an empty slice. Branch(&'tcx [ValTree<'tcx>]), } |