X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir_ty%2Fsrc%2Fconsteval.rs;h=24296c6b7b354d568e508905ff0e20c1e323fa77;hb=b301b040f5781a9083348936369a01c37138756f;hp=68e6e0582e3700344d2c8f91805aa3584dd60618;hpb=8887d2016f2e87332e4de216aaf0b5d125e0fe11;p=rust.git diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs index 68e6e0582e3..24296c6b7b3 100644 --- a/crates/hir_ty/src/consteval.rs +++ b/crates/hir_ty/src/consteval.rs @@ -2,15 +2,25 @@ use std::{collections::HashMap, convert::TryInto, fmt::Display}; -use chalk_ir::{IntTy, Scalar}; +use chalk_ir::{BoundVar, DebruijnIndex, GenericArgData, IntTy, Scalar}; use hir_def::{ expr::{ArithOp, BinaryOp, Expr, Literal, Pat}, + path::ModPath, + resolver::{Resolver, ValueNs}, type_ref::ConstScalar, }; use hir_expand::name::Name; use la_arena::{Arena, Idx}; +use stdx::never; -use crate::{Const, ConstData, ConstValue, Interner, Ty, TyKind}; +use crate::{ + db::HirDatabase, + infer::{Expectation, InferenceContext}, + lower::ParamLoweringMode, + to_placeholder_idx, + utils::Generics, + Const, ConstData, ConstValue, GenericArg, Interner, Ty, TyKind, +}; /// Extension trait for [`Const`] pub trait ConstExt { @@ -235,14 +245,14 @@ pub fn eval_const(expr: &Expr, ctx: &mut ConstEvalCtx<'_>) -> Result Err(ConstEvalError::TypeError), - _ => return Err(ConstEvalError::NotSupported("bin op on this operators")), + _ => Err(ConstEvalError::NotSupported("bin op on this operators")), } } Expr::Block { statements, tail, .. } => { let mut prev_values = HashMap::>::default(); for statement in &**statements { - match statement { - &hir_def::expr::Statement::Let { pat, initializer, .. } => { + match *statement { + hir_def::expr::Statement::Let { pat, initializer, .. } => { let pat = &ctx.pats[pat]; let name = match pat { Pat::Bind { name, subpat, .. } if subpat.is_none() => name.clone(), @@ -261,7 +271,7 @@ pub fn eval_const(expr: &Expr, ctx: &mut ConstEvalCtx<'_>) -> Result { + hir_def::expr::Statement::Expr { .. } => { return Err(ConstEvalError::NotSupported("this kind of statement")) } } @@ -293,7 +303,7 @@ pub fn eval_const(expr: &Expr, ctx: &mut ConstEvalCtx<'_>) -> Result, mut ctx: ConstEvalCtx<'_>) -> Option { let expr = &ctx.exprs[expr]; - if let Ok(ce) = eval_const(&expr, &mut ctx) { + if let Ok(ce) = eval_const(expr, &mut ctx) { match ce { ComputedExpr::Literal(Literal::Int(x, _)) => return x.try_into().ok(), ComputedExpr::Literal(Literal::Uint(x, _)) => return x.try_into().ok(), @@ -303,6 +313,57 @@ pub fn eval_usize(expr: Idx, mut ctx: ConstEvalCtx<'_>) -> Option { None } +pub(crate) fn path_to_const( + db: &dyn HirDatabase, + resolver: &Resolver, + path: &ModPath, + mode: ParamLoweringMode, + args_lazy: impl FnOnce() -> Generics, + debruijn: DebruijnIndex, +) -> Option { + match resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { + Some(ValueNs::GenericParam(p)) => { + let ty = db.const_param_ty(p); + let args = args_lazy(); + let value = match mode { + ParamLoweringMode::Placeholder => { + ConstValue::Placeholder(to_placeholder_idx(db, p.into())) + } + ParamLoweringMode::Variable => match args.param_idx(p.into()) { + Some(x) => ConstValue::BoundVar(BoundVar::new(debruijn, x)), + None => { + never!( + "Generic list doesn't contain this param: {:?}, {}, {:?}", + args, + path, + p + ); + return None; + } + }, + }; + Some(ConstData { ty, value }.intern(Interner)) + } + _ => None, + } +} + +pub fn unknown_const(ty: Ty) -> Const { + ConstData { + ty, + value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }), + } + .intern(Interner) +} + +pub fn unknown_const_usize() -> Const { + unknown_const(TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(Interner)) +} + +pub fn unknown_const_as_generic(ty: Ty) -> GenericArg { + GenericArgData::Const(unknown_const(ty)).intern(Interner) +} + /// Interns a possibly-unknown target usize pub fn usize_const(value: Option) -> Const { ConstData { @@ -313,3 +374,27 @@ pub fn usize_const(value: Option) -> Const { } .intern(Interner) } + +pub(crate) fn eval_to_const( + expr: Idx, + mode: ParamLoweringMode, + ctx: &mut InferenceContext, + args: impl FnOnce() -> Generics, + debruijn: DebruijnIndex, +) -> Const { + if let Expr::Path(p) = &ctx.body.exprs[expr] { + let db = ctx.db; + let resolver = &ctx.resolver; + if let Some(c) = path_to_const(db, resolver, p.mod_path(), mode, args, debruijn) { + return c; + } + } + let body = ctx.body.clone(); + let ctx = ConstEvalCtx { + exprs: &body.exprs, + pats: &body.pats, + local_data: HashMap::default(), + infer: &mut |x| ctx.infer_expr(x, &Expectation::None), + }; + usize_const(eval_usize(expr, ctx)) +}