diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 55 | ||||
-rw-r--r-- | compiler/rustc_middle/src/ty/consts/int.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_middle/src/ty/consts/kind.rs | 16 | ||||
-rw-r--r-- | compiler/rustc_middle/src/ty/consts/valtree.rs | 4 |
4 files changed, 49 insertions, 28 deletions
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 65cbac3e8..527ec9f6e 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,7 +1,9 @@ +use crate::middle::resolve_bound_vars as rbv; use crate::mir::interpret::LitToConstInput; use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; use std::fmt; @@ -14,7 +16,7 @@ pub use int::*; pub use kind::*; pub use valtree::*; -/// Use this rather than `ConstData, whenever possible. +/// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>); @@ -71,7 +73,10 @@ impl<'tcx> Const<'tcx> { let expr = &tcx.hir().body(body_id).value; debug!(?expr); - let ty = tcx.type_of(def.def_id_for_type_of()); + let ty = tcx + .type_of(def.def_id_for_type_of()) + .no_bound_vars() + .expect("const parameter types cannot be generic"); match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, @@ -125,16 +130,30 @@ impl<'tcx> Const<'tcx> { } } - use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; match expr.kind { - ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { - // Find the name and index of the const parameter by indexing the generics of - // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) + hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }, + )) => { + match tcx.named_bound_var(expr.hir_id) { + Some(rbv::ResolvedArg::EarlyBound(_)) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let item_def_id = tcx.parent(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + let name = tcx.item_name(def_id); + Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const( + ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), + ty, + )), + Some(rbv::ResolvedArg::Error(guar)) => { + Some(tcx.const_error_with_guaranteed(ty, guar)) + } + arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), + } } _ => None, } @@ -175,7 +194,7 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned usize constant. - pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { + pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } @@ -201,8 +220,12 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> { - self.kind().eval(tcx, param_env).try_to_machine_usize(tcx) + pub fn try_eval_target_usize( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option<u64> { + self.kind().eval(tcx, param_env).try_to_target_usize(tcx) } #[inline] @@ -229,8 +252,8 @@ impl<'tcx> Const<'tcx> { #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { - self.try_eval_usize(tcx, param_env) + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, param_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 48958e0d9..eecd78ab6 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -232,7 +232,7 @@ impl ScalarInt { } #[inline] - pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> { + pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> { Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index d9721863a..560caa041 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -4,7 +4,7 @@ use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::ty::abstract_const::CastKind; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; -use crate::ty::{self, List, Ty, TyCtxt, TypeVisitable}; +use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; @@ -125,8 +125,8 @@ impl<'tcx> ConstKind<'tcx> { } #[inline] - pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_value()?.try_to_machine_usize(tcx) + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { + self.try_to_value()?.try_to_target_usize(tcx) } } @@ -217,23 +217,21 @@ impl<'tcx> ConstKind<'tcx> { // Note that we erase regions *before* calling `with_reveal_all_normalized`, // so that we don't try to invoke this query with // any region variables. - let param_env_and = tcx - .erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)); // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed // when the expression doesn't depend on any parameters. // 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() { + let param_env_and = if (param_env, unevaluated).has_non_region_infer() { tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst { def: unevaluated.def, substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), }) } else { - param_env_and + tcx.erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)) }; // FIXME(eddyb) maybe the `const_eval_*` methods should take diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index a803fca0d..5ed4af2e9 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -78,8 +78,8 @@ impl<'tcx> ValTree<'tcx> { } } - pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten() + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { + self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten() } /// Get the values inside the ValTree as a slice of bytes. This only works for |