summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/consts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs55
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs4
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