From 6447d485e3765c20295368ac3503ed18b041298f Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Wed, 29 Mar 2023 21:46:46 +0900 Subject: [PATCH] Normalize type anchor type before resolving the rest of value paths --- crates/hir-ty/src/infer/path.rs | 19 +++++++++++++------ crates/hir-ty/src/lower.rs | 2 +- crates/hir-ty/src/tests/traits.rs | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 266e410187..368c3f6524 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -30,11 +30,18 @@ impl<'a> InferenceContext<'a> { fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option { let (value, self_subst) = if let Some(type_ref) = path.type_anchor() { - let Some(last) = path.segments().last() else { return None }; - let ty = self.make_ty(type_ref); - let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); + let last = path.segments().last()?; + + // Don't use `self.make_ty()` here as we need `orig_ns`. let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); - let (ty, _) = ctx.lower_ty_relative_path(ty, None, remaining_segments_for_ty); + let (ty, orig_ns) = ctx.lower_ty_ext(type_ref); + let ty = self.table.insert_type_vars(ty); + let ty = self.table.normalize_associated_types_in(ty); + + let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); + let (ty, _) = ctx.lower_ty_relative_path(ty, orig_ns, remaining_segments_for_ty); + let ty = self.table.insert_type_vars(ty); + let ty = self.table.normalize_associated_types_in(ty); self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))? } else { // FIXME: report error, unresolved first path segment @@ -169,7 +176,7 @@ impl<'a> InferenceContext<'a> { ) -> Option<(ValueNs, Substitution)> { let trait_ = trait_ref.hir_trait_id(); let item = - self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id)).find_map(|item| { + self.db.trait_data(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| { match item { AssocItemId::FunctionId(func) => { if segment.name == &self.db.function_data(func).name { @@ -288,7 +295,7 @@ impl<'a> InferenceContext<'a> { name: &Name, id: ExprOrPatId, ) -> Option<(ValueNs, Substitution)> { - let ty = self.resolve_ty_shallow(ty); + let ty = self.resolve_ty_shallow(&ty); let (enum_id, subst) = match ty.as_adt() { Some((AdtId::EnumId(e), subst)) => (e, subst), _ => return None, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 797e9ad0e9..adadbb888b 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -103,7 +103,7 @@ impl ImplTraitLoweringState { #[derive(Debug)] pub struct TyLoweringContext<'a> { pub db: &'a dyn HirDatabase, - pub resolver: &'a Resolver, + resolver: &'a Resolver, in_binders: DebruijnIndex, /// Note: Conceptually, it's thinkable that we could be in a location where /// some type params should be represented as placeholders, and others diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 7e6092f5b6..1201165cfa 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -4239,6 +4239,26 @@ impl Trait for () { type Assoc = E; fn f() { + let a = Self::Assoc::Unit; + // ^ E + let a = ::Assoc::Unit; + // ^ E + let a = ::Unit; + // ^ E + let a = <::Assoc>::Unit; + // ^ E + + // should be `Copy` but we don't track ownership anyway. + let value = E::Unit; + if let Self::Assoc::Unit = value {} + // ^^^^^^^^^^^^^^^^^ E + if let ::Assoc::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^ E + if let ::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^ E + if let <::Assoc>::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^^^ E + let x = 42; let a = Self::Assoc::Struct { x }; // ^ E