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.rs464
1 files changed, 197 insertions, 267 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 80e3ca1fa2..5468254ab9 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -5,17 +5,17 @@ use std::{
mem,
};
-use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
+use chalk_ir::{DebruijnIndex, Mutability, TyVariableKind, cast::Cast};
use either::Either;
use hir_def::{
+ BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+ expr_store::path::{GenericArg, GenericArgs, Path},
hir::{
- ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, ClosureKind, Expr, ExprId, ExprOrPatId,
- LabelId, Literal, Pat, PatId, Statement, UnaryOp,
+ ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, Expr, ExprId, ExprOrPatId, LabelId,
+ Literal, Pat, PatId, Statement, UnaryOp, generics::GenericParamDataRef,
},
lang_item::{LangItem, LangItemTarget},
- path::{GenericArg, GenericArgs, Path},
resolver::ValueNs,
- BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
};
use hir_expand::name::Name;
use intern::sym;
@@ -23,34 +23,33 @@ use stdx::always;
use syntax::ast::RangeOp;
use crate::{
- autoderef::{builtin_deref, deref_by_trait, Autoderef},
+ Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext,
+ DeclOrigin, IncorrectGenericsLenKind, Interner, Rawness, Scalar, Substitution,
+ TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
+ autoderef::{Autoderef, builtin_deref, deref_by_trait},
consteval,
- db::{InternedClosure, InternedCoroutine},
- error_lifetime,
- generics::{generics, Generics},
+ generics::generics,
infer::{
+ BreakableKind,
coerce::{CoerceMany, CoerceNever, CoercionCause},
find_continuable,
pat::contains_explicit_ref_binding,
- BreakableKind,
},
lang_items::lang_items_for_bin_op,
lower::{
- const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
+ LifetimeElisionKind, ParamLoweringMode, lower_to_chalk_mutability,
+ path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings},
},
- mapping::{from_chalk, ToChalk},
+ mapping::{ToChalk, from_chalk},
method_resolution::{self, VisibleFromModule},
primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id,
traits::FnTrait,
- Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext,
- DeclOrigin, FnAbi, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar, Substitution,
- TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
};
use super::{
- cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges,
- Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
+ BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
+ cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable,
};
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -198,14 +197,10 @@ impl InferenceContext<'_> {
match &self.body[expr] {
// Lang item paths cannot currently be local variables or statics.
Expr::Path(Path::LangItem(_, _)) => false,
- Expr::Path(Path::Normal(path)) => path.type_anchor().is_none(),
+ Expr::Path(Path::Normal(path)) => path.type_anchor.is_none(),
Expr::Path(path) => self
.resolver
- .resolve_path_in_value_ns_fully(
- self.db.upcast(),
- path,
- self.body.expr_path_hygiene(expr),
- )
+ .resolve_path_in_value_ns_fully(self.db, path, self.body.expr_path_hygiene(expr))
.is_none_or(|res| matches!(res, ValueNs::LocalBinding(_) | ValueNs::StaticId(_))),
Expr::Underscore => true,
Expr::UnaryOp { op: UnaryOp::Deref, .. } => true,
@@ -289,7 +284,7 @@ impl InferenceContext<'_> {
expected: &Expectation,
is_read: ExprIsRead,
) -> Ty {
- self.db.unwind_if_cancelled();
+ self.db.unwind_if_revision_cancelled();
let ty = match &self.body[tgt_expr] {
Expr::Missing => self.err_ty(),
@@ -349,8 +344,7 @@ impl InferenceContext<'_> {
}
Expr::Const(id) => {
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
- let loc = this.db.lookup_intern_anonymous_const(*id);
- this.infer_expr(loc.root, expected, ExprIsRead::Yes)
+ this.infer_expr(*id, expected, ExprIsRead::Yes)
})
.1
}
@@ -378,117 +372,8 @@ impl InferenceContext<'_> {
None => self.result.standard_types.never.clone(),
}
}
- Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => {
- assert_eq!(args.len(), arg_types.len());
-
- let mut sig_tys = Vec::with_capacity(arg_types.len() + 1);
-
- // collect explicitly written argument types
- for arg_type in arg_types.iter() {
- let arg_ty = match arg_type {
- Some(type_ref) => self.make_body_ty(*type_ref),
- None => self.table.new_type_var(),
- };
- sig_tys.push(arg_ty);
- }
-
- // add return type
- let ret_ty = match ret_type {
- Some(type_ref) => self.make_body_ty(*type_ref),
- None => self.table.new_type_var(),
- };
- if let ClosureKind::Async = closure_kind {
- sig_tys.push(self.lower_async_block_type_impl_trait(ret_ty.clone(), *body));
- } else {
- sig_tys.push(ret_ty.clone());
- }
-
- let sig_ty = TyKind::Function(FnPointer {
- num_binders: 0,
- sig: FnSig {
- abi: FnAbi::RustCall,
- safety: chalk_ir::Safety::Safe,
- variadic: false,
- },
- substitution: FnSubst(
- Substitution::from_iter(Interner, sig_tys.iter().cloned())
- .shifted_in(Interner),
- ),
- })
- .intern(Interner);
-
- let (id, ty, resume_yield_tys) = match closure_kind {
- ClosureKind::Coroutine(_) => {
- // FIXME: report error when there are more than 1 parameter.
- let resume_ty = match sig_tys.first() {
- // When `sig_tys.len() == 1` the first type is the return type, not the
- // first parameter type.
- Some(ty) if sig_tys.len() > 1 => ty.clone(),
- _ => self.result.standard_types.unit.clone(),
- };
- let yield_ty = self.table.new_type_var();
-
- let subst = TyBuilder::subst_for_coroutine(self.db, self.owner)
- .push(resume_ty.clone())
- .push(yield_ty.clone())
- .push(ret_ty.clone())
- .build();
-
- let coroutine_id = self
- .db
- .intern_coroutine(InternedCoroutine(self.owner, tgt_expr))
- .into();
- let coroutine_ty = TyKind::Coroutine(coroutine_id, subst).intern(Interner);
-
- (None, coroutine_ty, Some((resume_ty, yield_ty)))
- }
- ClosureKind::Closure | ClosureKind::Async => {
- let closure_id =
- self.db.intern_closure(InternedClosure(self.owner, tgt_expr)).into();
- let closure_ty = TyKind::Closure(
- closure_id,
- TyBuilder::subst_for_closure(self.db, self.owner, sig_ty.clone()),
- )
- .intern(Interner);
- self.deferred_closures.entry(closure_id).or_default();
- if let Some(c) = self.current_closure {
- self.closure_dependencies.entry(c).or_default().push(closure_id);
- }
- (Some(closure_id), closure_ty, None)
- }
- };
-
- // Eagerly try to relate the closure type with the expected
- // type, otherwise we often won't have enough information to
- // infer the body.
- self.deduce_closure_type_from_expectations(tgt_expr, &ty, &sig_ty, expected);
-
- // Now go through the argument patterns
- for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) {
- self.infer_top_pat(*arg_pat, arg_ty, None);
- }
-
- // FIXME: lift these out into a struct
- let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
- let prev_closure = mem::replace(&mut self.current_closure, id);
- let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
- let prev_ret_coercion =
- mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty)));
- let prev_resume_yield_tys =
- mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
-
- self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
- this.infer_return(*body);
- });
-
- self.diverges = prev_diverges;
- self.return_ty = prev_ret_ty;
- self.return_coercion = prev_ret_coercion;
- self.current_closure = prev_closure;
- self.resume_yield_tys = prev_resume_yield_tys;
-
- ty
- }
+ Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => self
+ .infer_closure(body, args, ret_type, arg_types, *closure_kind, tgt_expr, expected),
Expr::Call { callee, args, .. } => self.infer_call(tgt_expr, *callee, args, expected),
Expr::MethodCall { receiver, args, method_name, generic_args } => self
.infer_method_call(
@@ -657,16 +542,15 @@ impl InferenceContext<'_> {
_ if fields.is_empty() => {}
Some(def) => {
let field_types = self.db.field_types(def);
- let variant_data = def.variant_data(self.db.upcast());
+ let variant_data = def.variant_data(self.db);
let visibilities = self.db.field_visibilities(def);
for field in fields.iter() {
let field_def = {
match variant_data.field(&field.name) {
Some(local_id) => {
- if !visibilities[local_id].is_visible_from(
- self.db.upcast(),
- self.resolver.module(),
- ) {
+ if !visibilities[local_id]
+ .is_visible_from(self.db, self.resolver.module())
+ {
self.push_diagnostic(
InferenceDiagnostic::NoSuchField {
field: field.expr.into(),
@@ -772,8 +656,8 @@ impl InferenceContext<'_> {
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
if let Some(deref_fn) = self
.db
- .trait_data(deref_trait)
- .method_by_name(&Name::new_symbol_root(sym::deref.clone()))
+ .trait_items(deref_trait)
+ .method_by_name(&Name::new_symbol_root(sym::deref))
{
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
// the mutability is not wrong, and will be fixed in `self.infer_mut`).
@@ -858,7 +742,7 @@ impl InferenceContext<'_> {
} else {
let rhs_ty = self.infer_expr(value, &Expectation::none(), ExprIsRead::Yes);
let resolver_guard =
- self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, tgt_expr);
+ self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr);
self.inside_assignment = true;
self.infer_top_pat(target, &rhs_ty, None);
self.inside_assignment = false;
@@ -921,17 +805,18 @@ impl InferenceContext<'_> {
.map_or((self.err_ty(), Vec::new()), |adj| {
adj.apply(&mut self.table, base_ty)
});
+
// mutability will be fixed up in `InferenceContext::infer_mut`;
adj.push(Adjustment::borrow(
Mutability::Not,
self_ty.clone(),
self.table.new_lifetime_var(),
));
- self.write_expr_adj(*base, adj);
+ self.write_expr_adj(*base, adj.into_boxed_slice());
if let Some(func) = self
.db
- .trait_data(index_trait)
- .method_by_name(&Name::new_symbol_root(sym::index.clone()))
+ .trait_items(index_trait)
+ .method_by_name(&Name::new_symbol_root(sym::index))
{
let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
if subst.remaining() != 2 {
@@ -1143,7 +1028,7 @@ impl InferenceContext<'_> {
}
fn infer_expr_path(&mut self, path: &Path, id: ExprOrPatId, scope_id: ExprId) -> Ty {
- let g = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, scope_id);
+ let g = self.resolver.update_to_inner_scope(self.db, self.owner, scope_id);
let ty = match self.infer_path(path, id) {
Some(ty) => ty,
None => {
@@ -1168,8 +1053,7 @@ impl InferenceContext<'_> {
let ret_ty = self.table.new_type_var();
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
- let prev_ret_coercion =
- mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone())));
+ let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(ret_ty.clone()));
// FIXME: We should handle async blocks like we handle closures
let expected = &Expectation::has_type(ret_ty);
@@ -1258,7 +1142,7 @@ impl InferenceContext<'_> {
let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
return;
};
- let trait_data = self.db.trait_data(trait_);
+ let trait_data = self.db.trait_items(trait_);
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
.push(callee_ty.clone())
@@ -1426,7 +1310,7 @@ impl InferenceContext<'_> {
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
- let func = self.db.trait_data(trait_id).method_by_name(&name)?;
+ let func = self.db.trait_items(trait_id).method_by_name(&name)?;
Some((trait_id, func))
});
let (trait_, func) = match trait_func {
@@ -1472,10 +1356,10 @@ impl InferenceContext<'_> {
if let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner) {
self.write_expr_adj(
lhs,
- vec![Adjustment {
+ Box::new([Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
target: p_left.clone(),
- }],
+ }]),
);
}
}
@@ -1484,10 +1368,10 @@ impl InferenceContext<'_> {
if let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner) {
self.write_expr_adj(
rhs,
- vec![Adjustment {
+ Box::new([Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
target: p_right.clone(),
- }],
+ }]),
);
}
}
@@ -1517,7 +1401,7 @@ impl InferenceContext<'_> {
expected: &Expectation,
) -> Ty {
let coerce_ty = expected.coercion_target_type(&mut self.table);
- let g = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr);
+ let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
let prev_env = block_id.map(|block_id| {
let prev_env = self.table.trait_env.clone();
TraitEnvironment::with_block(&mut self.table.trait_env, block_id);
@@ -1556,11 +1440,7 @@ impl InferenceContext<'_> {
target_is_read,
)
};
- if type_ref.is_some() {
- decl_ty
- } else {
- ty
- }
+ if type_ref.is_some() { decl_ty } else { ty }
} else {
decl_ty
};
@@ -1681,20 +1561,20 @@ impl InferenceContext<'_> {
})
});
}
- TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
- let local_id = self.db.struct_data(*s).variant_data.field(name)?;
- let field = FieldId { parent: (*s).into(), local_id };
+ &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => {
+ let local_id = self.db.variant_fields(s.into()).field(name)?;
+ let field = FieldId { parent: s.into(), local_id };
(field, parameters.clone())
}
- TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => {
- let local_id = self.db.union_data(*u).variant_data.field(name)?;
- let field = FieldId { parent: (*u).into(), local_id };
+ &TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => {
+ let local_id = self.db.variant_fields(u.into()).field(name)?;
+ let field = FieldId { parent: u.into(), local_id };
(field, parameters.clone())
}
_ => return None,
};
let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
- .is_visible_from(self.db.upcast(), self.resolver.module());
+ .is_visible_from(self.db, self.resolver.module());
if !is_visible {
if private_field.is_none() {
private_field = Some((field_id, parameters));
@@ -1747,7 +1627,7 @@ impl InferenceContext<'_> {
match self.lookup_field(&receiver_ty, name) {
Some((ty, field_id, adjustments, is_public)) => {
- self.write_expr_adj(receiver, adjustments);
+ self.write_expr_adj(receiver, adjustments.into_boxed_slice());
self.result.field_resolutions.insert(tgt_expr, field_id);
if !is_public {
if let Either::Left(field) = field_id {
@@ -1781,9 +1661,8 @@ impl InferenceContext<'_> {
match resolved {
Some((adjust, func, _)) => {
let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty);
- let generics = generics(self.db.upcast(), func.into());
- let substs = self.substs_for_method_call(generics, None);
- self.write_expr_adj(receiver, adjustments);
+ let substs = self.substs_for_method_call(tgt_expr, func.into(), None);
+ self.write_expr_adj(receiver, adjustments.into_boxed_slice());
self.write_method_resolution(tgt_expr, func, substs.clone());
self.check_method_call(
@@ -1828,9 +1707,7 @@ impl InferenceContext<'_> {
if let TyKind::Closure(c, _) =
self.table.resolve_completely(callee_ty.clone()).kind(Interner)
{
- if let Some(par) = self.current_closure {
- self.closure_dependencies.entry(par).or_default().push(*c);
- }
+ self.add_current_closure_dependency(*c);
self.deferred_closures.entry(*c).or_default().push((
derefed_callee.clone(),
callee_ty.clone(),
@@ -1848,7 +1725,7 @@ impl InferenceContext<'_> {
tgt_expr,
);
}
- self.write_expr_adj(callee, adjustments);
+ self.write_expr_adj(callee, adjustments.into_boxed_slice());
(params, ret_ty)
}
None => {
@@ -1932,10 +1809,9 @@ impl InferenceContext<'_> {
}
let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty);
- self.write_expr_adj(receiver, adjustments);
+ self.write_expr_adj(receiver, adjustments.into_boxed_slice());
- let generics = generics(self.db.upcast(), func.into());
- let substs = self.substs_for_method_call(generics, generic_args);
+ let substs = self.substs_for_method_call(tgt_expr, func.into(), generic_args);
self.write_method_resolution(tgt_expr, func, substs.clone());
self.check_method_call(
tgt_expr,
@@ -1952,7 +1828,7 @@ impl InferenceContext<'_> {
let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name)
{
Some((ty, field_id, adjustments, _public)) => {
- self.write_expr_adj(receiver, adjustments);
+ self.write_expr_adj(receiver, adjustments.into_boxed_slice());
self.result.field_resolutions.insert(tgt_expr, field_id);
Some(ty)
}
@@ -1985,8 +1861,7 @@ impl InferenceContext<'_> {
let recovered = match assoc_func_with_same_name {
Some(f) => {
- let generics = generics(self.db.upcast(), f.into());
- let substs = self.substs_for_method_call(generics, generic_args);
+ let substs = self.substs_for_method_call(tgt_expr, f.into(), generic_args);
let f = self
.db
.value_ty(f.into())
@@ -2176,87 +2051,147 @@ impl InferenceContext<'_> {
fn substs_for_method_call(
&mut self,
- def_generics: Generics,
+ expr: ExprId,
+ def: GenericDefId,
generic_args: Option<&GenericArgs>,
) -> Substitution {
- let (
- parent_params,
- has_self_param,
- type_params,
- const_params,
- impl_trait_params,
- lifetime_params,
- ) = def_generics.provenance_split();
- assert!(!has_self_param); // method shouldn't have another Self param
- let total_len =
- parent_params + type_params + const_params + impl_trait_params + lifetime_params;
- let mut substs = Vec::with_capacity(total_len);
-
- // 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
- let self_params = type_params + const_params + lifetime_params;
-
- let mut args = generic_args.args.iter().peekable();
- for kind_id in def_generics.iter_self_id().take(self_params) {
- let arg = args.peek();
- let arg = match (kind_id, arg) {
- // Lifetimes can be inferred.
- // Once we have implemented lifetime inference correctly,
- // this should be handled in a proper way.
- (
- GenericParamId::LifetimeParamId(_),
- None | Some(GenericArg::Type(_) | GenericArg::Const(_)),
- ) => error_lifetime().cast(Interner),
-
- // If we run out of `generic_args`, stop pushing substs
- (_, None) => break,
-
- // Normal cases
- (_, Some(_)) => generic_arg_to_chalk(
- self.db,
- kind_id,
- args.next().unwrap(), // `peek()` is `Some(_)`, so guaranteed no panic
- self,
- &self.body.types,
- |this, type_ref| this.make_body_ty(type_ref),
- |this, c, ty| {
- const_or_path_to_chalk(
- this.db,
- &this.resolver,
- this.owner.into(),
- ty,
- c,
- ParamLoweringMode::Placeholder,
- || this.generics(),
- DebruijnIndex::INNERMOST,
- )
- },
- |this, lt_ref| this.make_body_lifetime(lt_ref),
- ),
- };
+ struct LowererCtx<'a, 'b> {
+ ctx: &'a mut InferenceContext<'b>,
+ expr: ExprId,
+ }
- substs.push(arg);
+ impl GenericArgsLowerer for LowererCtx<'_, '_> {
+ fn report_len_mismatch(
+ &mut self,
+ def: GenericDefId,
+ provided_count: u32,
+ expected_count: u32,
+ kind: IncorrectGenericsLenKind,
+ ) {
+ self.ctx.push_diagnostic(InferenceDiagnostic::MethodCallIncorrectGenericsLen {
+ expr: self.expr,
+ provided_count,
+ expected_count,
+ kind,
+ def,
+ });
+ }
+
+ fn report_arg_mismatch(
+ &mut self,
+ param_id: GenericParamId,
+ arg_idx: u32,
+ has_self_arg: bool,
+ ) {
+ self.ctx.push_diagnostic(InferenceDiagnostic::MethodCallIncorrectGenericsOrder {
+ expr: self.expr,
+ param_id,
+ arg_idx,
+ has_self_arg,
+ });
}
- };
- // Handle everything else as unknown. This also handles generic arguments for the method's
- // parent (impl or trait), which should come after those for the method.
- for (id, _data) in def_generics.iter().skip(substs.len()) {
- match id {
- GenericParamId::TypeParamId(_) => {
- substs.push(self.table.new_type_var().cast(Interner))
+ fn provided_kind(
+ &mut self,
+ param_id: GenericParamId,
+ param: GenericParamDataRef<'_>,
+ arg: &GenericArg,
+ ) -> crate::GenericArg {
+ match (param, arg) {
+ (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
+ self.ctx.make_body_lifetime(*lifetime).cast(Interner)
+ }
+ (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
+ self.ctx.make_body_ty(*type_ref).cast(Interner)
+ }
+ (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
+ let GenericParamId::ConstParamId(const_id) = param_id else {
+ unreachable!("non-const param ID for const param");
+ };
+ let const_ty = self.ctx.db.const_param_ty(const_id);
+ self.ctx.make_body_const(*konst, const_ty).cast(Interner)
+ }
+ _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
}
- GenericParamId::ConstParamId(id) => {
- substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
+ }
+
+ fn provided_type_like_const(
+ &mut self,
+ const_ty: Ty,
+ arg: TypeLikeConst<'_>,
+ ) -> crate::Const {
+ match arg {
+ TypeLikeConst::Path(path) => self.ctx.make_path_as_body_const(path, const_ty),
+ TypeLikeConst::Infer => self.ctx.table.new_const_var(const_ty),
+ }
+ }
+
+ fn inferred_kind(
+ &mut self,
+ _def: GenericDefId,
+ param_id: GenericParamId,
+ _param: GenericParamDataRef<'_>,
+ _infer_args: bool,
+ _preceding_args: &[crate::GenericArg],
+ ) -> crate::GenericArg {
+ // Always create an inference var, even when `infer_args == false`. This helps with diagnostics,
+ // and I think it's also required in the presence of `impl Trait` (that must be inferred).
+ match param_id {
+ GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner),
+ GenericParamId::ConstParamId(const_id) => self
+ .ctx
+ .table
+ .new_const_var(self.ctx.db.const_param_ty(const_id))
+ .cast(Interner),
+ GenericParamId::LifetimeParamId(_) => {
+ self.ctx.table.new_lifetime_var().cast(Interner)
+ }
}
- GenericParamId::LifetimeParamId(_) => {
- substs.push(self.table.new_lifetime_var().cast(Interner))
+ }
+
+ fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg {
+ match param_id {
+ GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner),
+ GenericParamId::ConstParamId(const_id) => self
+ .ctx
+ .table
+ .new_const_var(self.ctx.db.const_param_ty(const_id))
+ .cast(Interner),
+ GenericParamId::LifetimeParamId(_) => {
+ self.ctx.table.new_lifetime_var().cast(Interner)
+ }
}
}
+
+ fn report_elided_lifetimes_in_path(
+ &mut self,
+ _def: GenericDefId,
+ _expected_count: u32,
+ _hard_error: bool,
+ ) {
+ unreachable!("we set `LifetimeElisionKind::Infer`")
+ }
+
+ fn report_elision_failure(&mut self, _def: GenericDefId, _expected_count: u32) {
+ unreachable!("we set `LifetimeElisionKind::Infer`")
+ }
+
+ fn report_missing_lifetime(&mut self, _def: GenericDefId, _expected_count: u32) {
+ unreachable!("we set `LifetimeElisionKind::Infer`")
+ }
}
- assert_eq!(substs.len(), total_len);
- Substitution::from_iter(Interner, substs)
+
+ substs_from_args_and_bindings(
+ self.db,
+ self.body,
+ generic_args,
+ def,
+ true,
+ LifetimeElisionKind::Infer,
+ false,
+ None,
+ &mut LowererCtx { ctx: self, expr },
+ )
}
fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
@@ -2264,7 +2199,7 @@ impl InferenceContext<'_> {
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates =
- self.db.generic_predicates(GenericDefId::from_callable(self.db.upcast(), def));
+ self.db.generic_predicates(GenericDefId::from_callable(self.db, def));
for predicate in generic_predicates.iter() {
let (predicate, binders) = predicate
.clone()
@@ -2276,15 +2211,14 @@ impl InferenceContext<'_> {
// add obligation for trait implementation, if this is a trait method
match def {
CallableDefId::FunctionId(f) => {
- if let ItemContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container {
+ if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container {
// construct a TraitRef
- let params_len = parameters.len(Interner);
- let trait_params_len = generics(self.db.upcast(), trait_.into()).len();
+ let trait_params_len = generics(self.db, trait_.into()).len();
let substs = Substitution::from_iter(
Interner,
// The generic parameters for the trait come after those for the
// function.
- &parameters.as_slice(Interner)[params_len - trait_params_len..],
+ &parameters.as_slice(Interner)[..trait_params_len],
);
self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
@@ -2311,7 +2245,7 @@ impl InferenceContext<'_> {
_ => return Default::default(),
};
- let data = self.db.function_data(func);
+ let data = self.db.function_signature(func);
let Some(legacy_const_generics_indices) = &data.legacy_const_generics_indices else {
return Default::default();
};
@@ -2402,11 +2336,7 @@ impl InferenceContext<'_> {
BinaryOp::Assignment { .. } => unreachable!("handled above"),
};
- if is_assign {
- self.result.standard_types.unit.clone()
- } else {
- output_ty
- }
+ if is_assign { self.result.standard_types.unit.clone() } else { output_ty }
}
fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool {
@@ -2468,7 +2398,7 @@ impl InferenceContext<'_> {
}
}
- fn with_breakable_ctx<T>(
+ pub(super) fn with_breakable_ctx<T>(
&mut self,
kind: BreakableKind,
ty: Option<Ty>,