Normalize type anchor type before resolving the rest of value paths

This commit is contained in:
Ryo Yoshida 2023-03-29 21:46:46 +09:00
parent 8aef04f1a7
commit 6447d485e3
No known key found for this signature in database
GPG Key ID: E25698A930586171
3 changed files with 34 additions and 7 deletions

View File

@ -30,11 +30,18 @@ pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty>
fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> {
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 @@ fn resolve_trait_assoc_item(
) -> 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 @@ fn resolve_enum_variant_on_ty(
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,

View File

@ -103,7 +103,7 @@ fn swap(&self, impl_trait_mode: &Self) {
#[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

View File

@ -4239,6 +4239,26 @@ impl Trait for () {
type Assoc = E;
fn f() {
let a = Self::Assoc::Unit;
// ^ E
let a = <Self>::Assoc::Unit;
// ^ E
let a = <Self::Assoc>::Unit;
// ^ E
let a = <<Self>::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 <Self>::Assoc::Unit = value {}
// ^^^^^^^^^^^^^^^^^^^ E
if let <Self::Assoc>::Unit = value {}
// ^^^^^^^^^^^^^^^^^^^ E
if let <<Self>::Assoc>::Unit = value {}
// ^^^^^^^^^^^^^^^^^^^^^ E
let x = 42;
let a = Self::Assoc::Struct { x };
// ^ E