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.rs | 206 |
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)) + } } |