Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/path.rs')
-rw-r--r--crates/hir-ty/src/infer/path.rs129
1 files changed, 64 insertions, 65 deletions
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 3cadc8e933..704f15cc86 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -11,14 +11,14 @@ use rustc_type_ir::inherent::{SliceLike, Ty as _};
use stdx::never;
use crate::{
- InferenceDiagnostic, ValueTyDefId,
- generics::generics,
- infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
+ InferenceDiagnostic, Span, ValueTyDefId,
+ infer::{
+ InferenceTyLoweringVarsCtx, diagnostics::InferenceTyLoweringContext as TyLoweringContext,
+ },
lower::{GenericPredicates, LifetimeElisionKind},
method_resolution::{self, CandidateId, MethodError},
next_solver::{
- GenericArg, GenericArgs, TraitRef, Ty,
- infer::traits::{Obligation, ObligationCause},
+ GenericArg, GenericArgs, TraitRef, Ty, Unnormalized, infer::traits::ObligationCause,
util::clauses_as_obligations,
},
};
@@ -26,29 +26,36 @@ use crate::{
use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource};
impl<'db> InferenceContext<'_, 'db> {
- pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty<'db>> {
- let (value_def, generic_def, substs) = match self.resolve_value_path(path, id)? {
- ValuePathResolution::GenericDef(value_def, generic_def, substs) => {
- (value_def, generic_def, substs)
- }
- ValuePathResolution::NonGeneric(ty) => return Some(ty),
- };
+ pub(super) fn infer_path(
+ &mut self,
+ path: &Path,
+ id: ExprOrPatId,
+ ) -> Option<(ValueNs, Ty<'db>)> {
+ let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?;
+
+ let (value_def, generic_def, substs) =
+ match self.resolve_value_path(path, id, value, self_subst)? {
+ ValuePathResolution::GenericDef(value_def, generic_def, substs) => {
+ (value_def, generic_def, substs)
+ }
+ ValuePathResolution::NonGeneric(ty) => return Some((value, ty)),
+ };
let args = self.insert_type_vars(substs);
- self.add_required_obligations_for_value_path(generic_def, args);
+ self.add_required_obligations_for_value_path(id, generic_def, args);
- let ty = self.db.value_ty(value_def)?.instantiate(self.interner(), args);
+ let ty = self.db.value_ty(value_def)?.instantiate(self.interner(), args).skip_norm_wip();
let ty = self.process_remote_user_written_ty(ty);
- Some(ty)
+ Some((value, ty))
}
fn resolve_value_path(
&mut self,
path: &Path,
id: ExprOrPatId,
+ value: ValueNs,
+ self_subst: Option<GenericArgs<'db>>,
) -> Option<ValuePathResolution<'db>> {
- let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?;
-
let value_def: ValueTyDefId = match value {
ValueNs::FunctionId(it) => it.into(),
ValueNs::ConstId(it) => it.into(),
@@ -73,7 +80,7 @@ impl<'db> InferenceContext<'_, 'db> {
};
}
ValueNs::ImplSelf(impl_id) => {
- let ty = self.db.impl_self_ty(impl_id).instantiate_identity();
+ let ty = self.db.impl_self_ty(impl_id).instantiate_identity().skip_norm_wip();
return if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
Some(ValuePathResolution::GenericDef(
struct_id.into(),
@@ -86,7 +93,7 @@ impl<'db> InferenceContext<'_, 'db> {
};
}
ValueNs::GenericParam(it) => {
- return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty_ns(it)));
+ return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it)));
}
};
@@ -112,7 +119,7 @@ impl<'db> InferenceContext<'_, 'db> {
if let Some(last_segment) = last_segment {
path_ctx.set_current_segment(last_segment)
}
- path_ctx.substs_from_path(value_def, true, false)
+ path_ctx.substs_from_path(value_def, true, false, id.into())
})
};
@@ -134,14 +141,23 @@ impl<'db> InferenceContext<'_, 'db> {
no_diagnostics: bool,
) -> Option<(ValueNs, Option<GenericArgs<'db>>)> {
// Don't use `self.make_ty()` here as we need `orig_ns`.
+ let mut vars_ctx = InferenceTyLoweringVarsCtx {
+ table: &mut self.table,
+ type_of_type_placeholder: &mut self.result.type_of_type_placeholder,
+ };
let mut ctx = TyLoweringContext::new(
self.db,
&self.resolver,
self.store,
&self.diagnostics,
InferenceTyDiagnosticSource::Body,
+ self.store_owner,
self.generic_def,
+ &self.generics,
LifetimeElisionKind::Infer,
+ self.allow_using_generic_params,
+ Some(&mut vars_ctx),
+ &self.defined_anon_consts,
);
let mut path_ctx = if no_diagnostics {
ctx.at_path_forget_diagnostics(path)
@@ -152,10 +168,10 @@ impl<'db> InferenceContext<'_, 'db> {
let last = path.segments().last()?;
let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref);
- let ty = self.table.process_user_written_ty(ty);
+ let ty = path_ctx.expect_table().process_user_written_ty(ty);
path_ctx.ignore_last_segment();
- let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true);
+ let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true, id.into());
drop_ctx(ctx, no_diagnostics);
let ty = self.table.process_user_written_ty(ty);
self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
@@ -182,9 +198,13 @@ impl<'db> InferenceContext<'_, 'db> {
let (resolution, substs) = match (def, is_before_last) {
(TypeNs::TraitId(trait_), true) => {
- let self_ty = self.table.next_ty_var();
- let trait_ref =
- path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true);
+ let self_ty = path_ctx.expect_table().next_ty_var(id.into());
+ let trait_ref = path_ctx.lower_trait_ref_from_resolved_path(
+ trait_,
+ self_ty,
+ true,
+ id.into(),
+ );
drop_ctx(ctx, no_diagnostics);
self.resolve_trait_assoc_item(trait_ref, last_segment, id)
}
@@ -194,7 +214,7 @@ impl<'db> InferenceContext<'_, 'db> {
// should resolve to an associated type of that trait (e.g. `<T
// as Iterator>::Item::default`)
path_ctx.ignore_last_segment();
- let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
+ let (ty, _) = path_ctx.lower_partly_resolved_path(def, true, id.into());
drop_ctx(ctx, no_diagnostics);
if ty.is_ty_error() {
return None;
@@ -219,8 +239,9 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
- fn add_required_obligations_for_value_path(
+ pub(super) fn add_required_obligations_for_value_path(
&mut self,
+ node: ExprOrPatId,
def: GenericDefId,
subst: GenericArgs<'db>,
) {
@@ -228,29 +249,12 @@ impl<'db> InferenceContext<'_, 'db> {
let predicates = GenericPredicates::query_all(self.db, def);
let param_env = self.table.param_env;
self.table.register_predicates(clauses_as_obligations(
- predicates.iter_instantiated(interner, subst.as_slice()),
- ObligationCause::new(),
+ predicates
+ .iter_instantiated(interner, subst.as_slice())
+ .map(Unnormalized::skip_norm_wip),
+ ObligationCause::new(node),
param_env,
));
-
- // We need to add `Self: Trait` obligation when `def` is a trait assoc item.
- let container = match def {
- GenericDefId::FunctionId(id) => id.lookup(self.db).container,
- GenericDefId::ConstId(id) => id.lookup(self.db).container,
- _ => return,
- };
-
- if let ItemContainerId::TraitId(trait_) = container {
- let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self());
- let parent_subst = GenericArgs::new_from_slice(&subst.as_slice()[..parent_len]);
- let trait_ref = TraitRef::new_from_args(interner, trait_.into(), parent_subst);
- self.table.register_predicate(Obligation::new(
- interner,
- ObligationCause::new(),
- param_env,
- trait_ref,
- ));
- }
}
fn resolve_trait_assoc_item(
@@ -304,7 +308,7 @@ impl<'db> InferenceContext<'_, 'db> {
return Some(result);
}
- let res = self.with_method_resolution(|ctx| {
+ let res = self.with_method_resolution(Span::Dummy, Span::Dummy, |ctx| {
ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty)
});
let (item, visible) = match res {
@@ -324,28 +328,23 @@ impl<'db> InferenceContext<'_, 'db> {
};
let substs = match container {
ItemContainerId::ImplId(impl_id) => {
- let impl_substs = self.table.fresh_args_for_item(impl_id.into());
- let impl_self_ty =
- self.db.impl_self_ty(impl_id).instantiate(self.interner(), impl_substs);
- self.unify(impl_self_ty, ty);
+ let impl_substs = self.table.fresh_args_for_item(id.into(), impl_id.into());
+ let impl_self_ty = self
+ .db
+ .impl_self_ty(impl_id)
+ .instantiate(self.interner(), impl_substs)
+ .skip_norm_wip();
+ _ = self.demand_eqtype(id, impl_self_ty, ty);
impl_substs
}
ItemContainerId::TraitId(trait_) => {
// we're picking this method
- let args = GenericArgs::fill_rest(
+ GenericArgs::fill_rest(
self.interner(),
trait_.into(),
[ty.into()],
- |_, id, _| self.table.next_var_for_param(id),
- );
- let trait_ref = TraitRef::new_from_args(self.interner(), trait_.into(), args);
- self.table.register_predicate(Obligation::new(
- self.interner(),
- ObligationCause::new(),
- self.table.param_env,
- trait_ref,
- ));
- args
+ |_, param, _| self.table.var_for_def(param, id.into()),
+ )
}
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
never!("assoc item contained in module/extern block");
@@ -370,7 +369,7 @@ impl<'db> InferenceContext<'_, 'db> {
name: &Name,
id: ExprOrPatId,
) -> Option<(ValueNs, GenericArgs<'db>)> {
- let ty = self.table.try_structurally_resolve_type(ty);
+ let ty = self.table.try_structurally_resolve_type(id.into(), ty);
let (enum_id, subst) = match ty.as_adt() {
Some((AdtId::EnumId(e), subst)) => (e, subst),
_ => return None,