Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/consteval_nextsolver.rs')
| -rw-r--r-- | crates/hir-ty/src/consteval_nextsolver.rs | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/crates/hir-ty/src/consteval_nextsolver.rs b/crates/hir-ty/src/consteval_nextsolver.rs deleted file mode 100644 index 155f1336e4..0000000000 --- a/crates/hir-ty/src/consteval_nextsolver.rs +++ /dev/null @@ -1,256 +0,0 @@ -//! Constant evaluation details -// FIXME(next-solver): this should get removed as things get moved to rustc_type_ir from chalk_ir -#![allow(unused)] - -use base_db::Crate; -use hir_def::{ - EnumVariantId, GeneralConstId, - expr_store::{Body, HygieneId, path::Path}, - hir::{Expr, ExprId}, - resolver::{Resolver, ValueNs}, - type_ref::LiteralConstRef, -}; -use hir_expand::Lookup; -use rustc_type_ir::{ - UnevaluatedConst, - inherent::{IntoKind, SliceLike}, -}; -use stdx::never; -use triomphe::Arc; - -use crate::{ - ConstScalar, Interner, MemoryMap, Substitution, TraitEnvironment, - consteval::ConstEvalError, - db::HirDatabase, - generics::Generics, - infer::InferenceContext, - next_solver::{ - Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, - ParamConst, SolverDefId, Ty, ValueConst, - mapping::{ChalkToNextSolver, NextSolverToChalk, convert_binder_to_early_binder}, - }, -}; - -use super::mir::{interpret_mir, lower_to_mir, pad16}; - -pub(crate) fn path_to_const<'a, 'g>( - db: &'a dyn HirDatabase, - resolver: &Resolver<'a>, - path: &Path, - args: impl FnOnce() -> &'g Generics, - expected_ty: Ty<'a>, -) -> Option<Const<'a>> { - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { - Some(ValueNs::GenericParam(p)) => { - let args = args(); - match args - .type_or_const_param(p.into()) - .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone()))) - { - Some((idx, _param)) => { - Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p })) - } - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - None - } - } - } - Some(ValueNs::ConstId(c)) => { - let args = GenericArgs::new_from_iter(interner, []); - Some(Const::new( - interner, - rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new( - SolverDefId::ConstId(c), - args, - )), - )) - } - _ => None, - } -} - -pub fn unknown_const<'db>(ty: Ty<'db>) -> Const<'db> { - Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed)) -} - -pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> { - unknown_const(ty).into() -} - -/// Interns a constant scalar with the given type -pub fn intern_const_ref<'a>( - db: &'a dyn HirDatabase, - value: &LiteralConstRef, - 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 kind = match value { - LiteralConstRef::Int(i) => { - // FIXME: We should handle failure of layout better. - let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); - rustc_type_ir::ConstKind::Value(ValueConst::new( - ty, - ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()), - )) - } - LiteralConstRef::UInt(i) => { - let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); - rustc_type_ir::ConstKind::Value(ValueConst::new( - ty, - ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()), - )) - } - LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new( - ty, - ConstBytes(Box::new([*b as u8]), MemoryMap::default()), - )), - LiteralConstRef::Char(c) => rustc_type_ir::ConstKind::Value(ValueConst::new( - ty, - ConstBytes((*c as u32).to_le_bytes().into(), MemoryMap::default()), - )), - LiteralConstRef::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed), - }; - Const::new(interner, kind) -} - -/// Interns a possibly-unknown target usize -pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const<'db> { - 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), - krate, - ) -} - -pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u128> { - let interner = DbInterner::new_with(db, None, None); - match c.kind() { - ConstKind::Param(_) => None, - 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.to_chalk(interner); - let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); - try_const_usize(db, ec) - } - ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().0, false))), - ConstKind::Error(_) => None, - ConstKind::Expr(_) => None, - } -} - -pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<i128> { - let interner = DbInterner::new_with(db, None, None); - match (*c).kind() { - ConstKind::Param(_) => None, - 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.to_chalk(interner); - let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); - try_const_isize(db, &ec) - } - ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().0, true))), - ConstKind::Error(_) => None, - ConstKind::Expr(_) => None, - } -} - -pub(crate) fn const_eval_discriminant_variant( - db: &dyn HirDatabase, - variant_id: EnumVariantId, -) -> Result<i128, ConstEvalError> { - let interner = DbInterner::new_with(db, None, None); - let def = variant_id.into(); - let body = db.body(def); - let loc = variant_id.lookup(db); - if matches!(body[body.body_expr], Expr::Missing) { - let prev_idx = loc.index.checked_sub(1); - let value = match prev_idx { - Some(prev_idx) => { - 1 + db.const_eval_discriminant( - loc.parent.enum_variants(db).variants[prev_idx as usize].0, - )? - } - _ => 0, - }; - return Ok(value); - } - - let repr = db.enum_signature(loc.parent).repr; - let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed()); - - let mir_body = db.monomorphized_mir_body( - def, - Substitution::empty(Interner), - db.trait_environment_for_body(def), - )?; - let c = interpret_mir(db, mir_body, false, None)?.0?; - let c = c.to_nextsolver(interner); - let c = if is_signed { - try_const_isize(db, &c).unwrap() - } else { - try_const_usize(db, c).unwrap() as i128 - }; - Ok(c) -} - -// FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should -// get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here -// and make this function private. See the fixme comment on `InferenceContext::resolve_all`. -pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>) -> Const<'db> { - let interner = DbInterner::new_with(ctx.db, None, None); - let infer = ctx.fixme_resolve_all_clone(); - fn has_closure(body: &Body, expr: ExprId) -> bool { - if matches!(body[expr], Expr::Closure { .. }) { - return true; - } - let mut r = false; - body.walk_child_exprs(expr, |idx| r |= has_closure(body, idx)); - r - } - 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].clone().to_nextsolver(interner)); - } - if let Expr::Path(p) = &ctx.body[expr] { - let resolver = &ctx.resolver; - if let Some(c) = path_to_const( - ctx.db, - resolver, - p, - || ctx.generics(), - infer[expr].to_nextsolver(interner), - ) { - return c; - } - } - if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) - && let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None) - { - return result.to_nextsolver(interner); - } - unknown_const(infer[expr].to_nextsolver(interner)) -} |