Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_ty/src/infer/expr.rs')
| -rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index c093f0e4b2..e78a6377e5 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -7,13 +7,15 @@ use std::{ sync::Arc, }; -use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; +use chalk_ir::{ + cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind, +}; use hir_def::{ expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, Literal, Ordering, Statement, UnaryOp}, generics::TypeOrConstParamData, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, - FieldId, FunctionId, ItemContainerId, Lookup, + ConstParamId, FieldId, FunctionId, ItemContainerId, Lookup, }; use hir_expand::name::{name, Name}; use stdx::always; @@ -23,7 +25,9 @@ use crate::{ autoderef::{self, Autoderef}, consteval, infer::coerce::CoerceMany, - lower::lower_to_chalk_mutability, + lower::{ + const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode, + }, mapping::from_chalk, method_resolution, primitive::{self, UintTy}, @@ -39,7 +43,7 @@ use super::{ }; impl<'a> InferenceContext<'a> { - pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { + pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { let ty = self.infer_expr_inner(tgt_expr, expected); if self.resolve_ty_shallow(&ty).is_never() { // Any expression that produces a value of type `!` must have diverged @@ -662,7 +666,7 @@ impl<'a> InferenceContext<'a> { self.resolve_associated_type_with_params( self_ty, self.resolve_ops_index_output(), - &[index_ty], + &[GenericArgData::Ty(index_ty).intern(Interner)], ) } else { self.err_ty() @@ -704,7 +708,7 @@ impl<'a> InferenceContext<'a> { let cur_elem_ty = self.infer_expr_inner(expr, &expected); coerce.coerce(self, Some(expr), &cur_elem_ty); } - Some(items.len() as u64) + consteval::usize_const(Some(items.len() as u64)) } &Array::Repeat { initializer, repeat } => { self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty)); @@ -715,19 +719,22 @@ impl<'a> InferenceContext<'a> { ), ); - consteval::eval_usize( - repeat, - consteval::ConstEvalCtx { - exprs: &body.exprs, - pats: &body.pats, - local_data: Default::default(), - infer: &mut |x| self.infer_expr(x, &expected), - }, - ) + if let Some(g_def) = self.owner.as_generic_def_id() { + let generics = generics(self.db.upcast(), g_def); + consteval::eval_to_const( + repeat, + ParamLoweringMode::Placeholder, + self, + || generics, + DebruijnIndex::INNERMOST, + ) + } else { + consteval::usize_const(None) + } } }; - TyKind::Array(coerce.complete(), consteval::usize_const(len)).intern(Interner) + TyKind::Array(coerce.complete(), len).intern(Interner) } Expr::Literal(lit) => match lit { Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner), @@ -1038,38 +1045,52 @@ impl<'a> InferenceContext<'a> { let total_len = parent_params + type_params + const_params + impl_trait_params; let mut substs = Vec::with_capacity(total_len); // Parent arguments are unknown - for (_id, param) in def_generics.iter_parent() { + for (id, param) in def_generics.iter_parent() { match param { TypeOrConstParamData::TypeParamData(_) => { - substs.push(self.table.new_type_var()); + substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner)); } TypeOrConstParamData::ConstParamData(_) => { - // FIXME: here we should do something else - substs.push(self.table.new_type_var()); + let ty = self.db.const_param_ty(ConstParamId::from_unchecked(id)); + substs + .push(GenericArgData::Const(self.table.new_const_var(ty)).intern(Interner)); } } } - // handle provided type arguments + // handle provided arguments if let Some(generic_args) = generic_args { // if args are provided, it should be all of them, but we can't rely on that - for arg in generic_args + for (arg, kind_id) in generic_args .args .iter() - .filter(|arg| matches!(arg, GenericArg::Type(_))) - .take(type_params) + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .take(type_params + const_params) + .zip(def_generics.iter_id().skip(parent_params)) { - match arg { - GenericArg::Type(type_ref) => { - let ty = self.make_ty(type_ref); - substs.push(ty); - } - GenericArg::Lifetime(_) => {} + if let Some(g) = generic_arg_to_chalk( + self.db, + kind_id, + arg, + self, + |this, type_ref| this.make_ty(type_ref), + |this, c| { + const_or_path_to_chalk( + this.db, + &this.resolver, + c, + ParamLoweringMode::Placeholder, + || generics(this.db.upcast(), (&this.resolver).generic_def().unwrap()), + DebruijnIndex::INNERMOST, + ) + }, + ) { + substs.push(g); } } }; let supplied_params = substs.len(); for _ in supplied_params..total_len { - substs.push(self.table.new_type_var()); + substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner)); } assert_eq!(substs.len(), total_len); Substitution::from_iter(Interner, substs) |