Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/consteval.rs')
-rw-r--r--crates/hir-ty/src/consteval.rs206
1 files changed, 120 insertions, 86 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 18ebe7d7a5..f11240e0f7 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -5,7 +5,8 @@ mod tests;
use base_db::Crate;
use hir_def::{
- EnumVariantId, GeneralConstId, HasModule, StaticId,
+ ConstId, EnumVariantId, GeneralConstId, HasModule, StaticId,
+ attrs::AttrFlags,
expr_store::Body,
hir::{Expr, ExprId},
type_ref::LiteralConstRef,
@@ -15,15 +16,16 @@ use rustc_type_ir::inherent::IntoKind;
use triomphe::Arc;
use crate::{
- LifetimeElisionKind, MemoryMap, TraitEnvironment, TyLoweringContext,
+ LifetimeElisionKind, MemoryMap, ParamEnvAndCrate, TyLoweringContext,
db::HirDatabase,
display::DisplayTarget,
infer::InferenceContext,
mir::{MirEvalError, MirLowerError},
next_solver::{
Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
- SolverDefId, Ty, ValueConst,
+ ParamEnv, StoredConst, StoredGenericArgs, Ty, ValueConst,
},
+ traits::StoredParamEnvAndCrate,
};
use super::mir::{interpret_mir, lower_to_mir, pad16};
@@ -37,12 +39,12 @@ pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> {
}
#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ConstEvalError<'db> {
- MirLowerError(MirLowerError<'db>),
- MirEvalError(MirEvalError<'db>),
+pub enum ConstEvalError {
+ MirLowerError(MirLowerError),
+ MirEvalError(MirEvalError),
}
-impl ConstEvalError<'_> {
+impl ConstEvalError {
pub fn pretty_print(
&self,
f: &mut String,
@@ -61,8 +63,8 @@ impl ConstEvalError<'_> {
}
}
-impl<'db> From<MirLowerError<'db>> for ConstEvalError<'db> {
- fn from(value: MirLowerError<'db>) -> Self {
+impl From<MirLowerError> for ConstEvalError {
+ fn from(value: MirLowerError) -> Self {
match value {
MirLowerError::ConstEvalError(_, e) => *e,
_ => ConstEvalError::MirLowerError(value),
@@ -70,8 +72,8 @@ impl<'db> From<MirLowerError<'db>> for ConstEvalError<'db> {
}
}
-impl<'db> From<MirEvalError<'db>> for ConstEvalError<'db> {
- fn from(value: MirEvalError<'db>) -> Self {
+impl From<MirEvalError> for ConstEvalError {
+ fn from(value: MirEvalError) -> Self {
ConstEvalError::MirEvalError(value)
}
}
@@ -83,8 +85,9 @@ pub fn intern_const_ref<'a>(
ty: Ty<'a>,
krate: Crate,
) -> Const<'a> {
- let interner = DbInterner::new_with(db, Some(krate), None);
- let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate));
+ let interner = DbInterner::new_no_crate(db);
+ let layout = db
+ .layout_of_ty(ty.store(), ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }.store());
let kind = match value {
LiteralConstRef::Int(i) => {
// FIXME: We should handle failure of layout better.
@@ -128,7 +131,7 @@ pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Cr
intern_const_ref(
db,
&value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),
- Ty::new_uint(DbInterner::new_with(db, Some(krate), None), rustc_type_ir::UintTy::Usize),
+ Ty::new_uint(DbInterner::new_no_crate(db), rustc_type_ir::UintTy::Usize),
krate,
)
}
@@ -139,16 +142,17 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u
ConstKind::Infer(_) => None,
ConstKind::Bound(_, _) => None,
ConstKind::Placeholder(_) => None,
- ConstKind::Unevaluated(unevaluated_const) => {
- let c = match unevaluated_const.def {
- SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
- SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
- _ => unreachable!(),
- };
- let subst = unevaluated_const.args;
- let ec = db.const_eval(c, subst, None).ok()?;
- try_const_usize(db, ec)
- }
+ ConstKind::Unevaluated(unevaluated_const) => match unevaluated_const.def.0 {
+ GeneralConstId::ConstId(id) => {
+ let subst = unevaluated_const.args;
+ let ec = db.const_eval(id, subst, None).ok()?;
+ try_const_usize(db, ec)
+ }
+ GeneralConstId::StaticId(id) => {
+ let ec = db.const_eval_static(id).ok()?;
+ try_const_usize(db, ec)
+ }
+ },
ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().memory, false))),
ConstKind::Error(_) => None,
ConstKind::Expr(_) => None,
@@ -161,27 +165,28 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<
ConstKind::Infer(_) => None,
ConstKind::Bound(_, _) => None,
ConstKind::Placeholder(_) => None,
- ConstKind::Unevaluated(unevaluated_const) => {
- let c = match unevaluated_const.def {
- SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
- SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
- _ => unreachable!(),
- };
- let subst = unevaluated_const.args;
- let ec = db.const_eval(c, subst, None).ok()?;
- try_const_isize(db, &ec)
- }
+ ConstKind::Unevaluated(unevaluated_const) => match unevaluated_const.def.0 {
+ GeneralConstId::ConstId(id) => {
+ let subst = unevaluated_const.args;
+ let ec = db.const_eval(id, subst, None).ok()?;
+ try_const_isize(db, &ec)
+ }
+ GeneralConstId::StaticId(id) => {
+ let ec = db.const_eval_static(id).ok()?;
+ try_const_isize(db, &ec)
+ }
+ },
ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().memory, true))),
ConstKind::Error(_) => None,
ConstKind::Expr(_) => None,
}
}
-pub(crate) fn const_eval_discriminant_variant<'db>(
- db: &'db dyn HirDatabase,
+pub(crate) fn const_eval_discriminant_variant(
+ db: &dyn HirDatabase,
variant_id: EnumVariantId,
-) -> Result<i128, ConstEvalError<'db>> {
- let interner = DbInterner::new_with(db, None, None);
+) -> Result<i128, ConstEvalError> {
+ let interner = DbInterner::new_no_crate(db);
let def = variant_id.into();
let body = db.body(def);
let loc = variant_id.lookup(db);
@@ -198,13 +203,14 @@ pub(crate) fn const_eval_discriminant_variant<'db>(
return Ok(value);
}
- let repr = db.enum_signature(loc.parent).repr;
+ let repr = AttrFlags::repr(db, loc.parent.into());
let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed());
let mir_body = db.monomorphized_mir_body(
def,
- GenericArgs::new_from_iter(interner, []),
- db.trait_environment_for_body(def),
+ GenericArgs::empty(interner).store(),
+ ParamEnvAndCrate { param_env: db.trait_environment_for_body(def), krate: def.krate(db) }
+ .store(),
)?;
let c = interpret_mir(db, mir_body, false, None)?.0?;
let c = if is_signed {
@@ -230,7 +236,7 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'd
}
if has_closure(ctx.body, expr) {
// Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
- return unknown_const(infer[expr]);
+ return Const::error(ctx.interner());
}
if let Expr::Path(p) = &ctx.body[expr] {
let mut ctx = TyLoweringContext::new(
@@ -249,61 +255,89 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'd
{
return result;
}
- unknown_const(infer[expr])
+ Const::error(ctx.interner())
}
-pub(crate) fn const_eval_cycle_result<'db>(
- _: &'db dyn HirDatabase,
- _: GeneralConstId,
- _: GenericArgs<'db>,
- _: Option<Arc<TraitEnvironment<'db>>>,
-) -> Result<Const<'db>, ConstEvalError<'db>> {
- Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
-}
-
-pub(crate) fn const_eval_static_cycle_result<'db>(
- _: &'db dyn HirDatabase,
- _: StaticId,
-) -> Result<Const<'db>, ConstEvalError<'db>> {
- Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
-}
-
-pub(crate) fn const_eval_discriminant_cycle_result<'db>(
- _: &'db dyn HirDatabase,
+pub(crate) fn const_eval_discriminant_cycle_result(
+ _: &dyn HirDatabase,
+ _: salsa::Id,
_: EnumVariantId,
-) -> Result<i128, ConstEvalError<'db>> {
+) -> Result<i128, ConstEvalError> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
-pub(crate) fn const_eval_query<'db>(
+pub(crate) fn const_eval<'db>(
db: &'db dyn HirDatabase,
- def: GeneralConstId,
+ def: ConstId,
subst: GenericArgs<'db>,
- trait_env: Option<Arc<TraitEnvironment<'db>>>,
-) -> Result<Const<'db>, ConstEvalError<'db>> {
- let body = match def {
- GeneralConstId::ConstId(c) => {
- db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))?
- }
- GeneralConstId::StaticId(s) => {
- let krate = s.module(db).krate();
- db.monomorphized_mir_body(s.into(), subst, TraitEnvironment::empty(krate))?
- }
+ trait_env: Option<ParamEnvAndCrate<'db>>,
+) -> Result<Const<'db>, ConstEvalError> {
+ return match const_eval_query(db, def, subst.store(), trait_env.map(|env| env.store())) {
+ Ok(konst) => Ok(konst.as_ref()),
+ Err(err) => Err(err.clone()),
};
- let c = interpret_mir(db, body, false, trait_env)?.0?;
- Ok(c)
+
+ #[salsa::tracked(returns(ref), cycle_result = const_eval_cycle_result)]
+ pub(crate) fn const_eval_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: ConstId,
+ subst: StoredGenericArgs,
+ trait_env: Option<StoredParamEnvAndCrate>,
+ ) -> Result<StoredConst, ConstEvalError> {
+ let body = db.monomorphized_mir_body(
+ def.into(),
+ subst,
+ ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) }
+ .store(),
+ )?;
+ let c = interpret_mir(db, body, false, trait_env.as_ref().map(|env| env.as_ref()))?.0?;
+ Ok(c.store())
+ }
+
+ pub(crate) fn const_eval_cycle_result(
+ _: &dyn HirDatabase,
+ _: salsa::Id,
+ _: ConstId,
+ _: StoredGenericArgs,
+ _: Option<StoredParamEnvAndCrate>,
+ ) -> Result<StoredConst, ConstEvalError> {
+ Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
+ }
}
-pub(crate) fn const_eval_static_query<'db>(
+pub(crate) fn const_eval_static<'db>(
db: &'db dyn HirDatabase,
def: StaticId,
-) -> Result<Const<'db>, ConstEvalError<'db>> {
- let interner = DbInterner::new_with(db, None, None);
- let body = db.monomorphized_mir_body(
- def.into(),
- GenericArgs::new_from_iter(interner, []),
- db.trait_environment_for_body(def.into()),
- )?;
- let c = interpret_mir(db, body, false, None)?.0?;
- Ok(c)
+) -> Result<Const<'db>, ConstEvalError> {
+ return match const_eval_static_query(db, def) {
+ Ok(konst) => Ok(konst.as_ref()),
+ Err(err) => Err(err.clone()),
+ };
+
+ #[salsa::tracked(returns(ref), cycle_result = const_eval_static_cycle_result)]
+ pub(crate) fn const_eval_static_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: StaticId,
+ ) -> Result<StoredConst, ConstEvalError> {
+ let interner = DbInterner::new_no_crate(db);
+ let body = db.monomorphized_mir_body(
+ def.into(),
+ GenericArgs::empty(interner).store(),
+ ParamEnvAndCrate {
+ param_env: db.trait_environment_for_body(def.into()),
+ krate: def.krate(db),
+ }
+ .store(),
+ )?;
+ let c = interpret_mir(db, body, false, None)?.0?;
+ Ok(c.store())
+ }
+
+ pub(crate) fn const_eval_static_cycle_result(
+ _: &dyn HirDatabase,
+ _: salsa::Id,
+ _: StaticId,
+ ) -> Result<StoredConst, ConstEvalError> {
+ Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
+ }
}