Skip to content

Commit e2710df

Browse files
committed
try to implement feature(more_qualified_paths)
This handles ```rust let <T as Trait>::Assoc { a } = <T as Trait>::Assoc { a: 0 }; ```
1 parent bf6d445 commit e2710df

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

crates/hir-ty/src/infer.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,82 @@ impl<'db> InferenceContext<'db> {
17311731

17321732
self.resolve_variant_on_alias(ty, unresolved, mod_path)
17331733
}
1734+
TypeNs::TraitId(_trait_id) => {
1735+
let Some(remaining_idx) = unresolved else {
1736+
drop(ctx);
1737+
return (self.err_ty(), None);
1738+
};
1739+
1740+
let mut remaining_segments = path.segments().skip(remaining_idx);
1741+
1742+
if remaining_segments.len() >= 2 {
1743+
path_ctx.ignore_last_segment();
1744+
}
1745+
1746+
let mut ty;
1747+
1748+
// We need to try resolving unresolved segments one by one because each may resolve
1749+
// to a projection, which `TyLoweringContext` cannot handle on its own.
1750+
let mut tried_resolving_once;
1751+
loop {
1752+
let current_segment = remaining_segments.first().unwrap();
1753+
1754+
// `lower_partly_resolved_path()` returns `None` as type namespace unless
1755+
// `remaining_segments` is empty, which is never the case here. We don't know
1756+
// which namespace the new `ty` is in until normalized anyway.
1757+
(ty, _) = path_ctx.lower_partly_resolved_path(resolution, true);
1758+
tried_resolving_once = true;
1759+
1760+
ty = self.table.insert_type_vars(ty);
1761+
ty = self.table.normalize_associated_types_in(ty);
1762+
ty = self.table.resolve_ty_shallow(&ty);
1763+
if ty.is_unknown() {
1764+
return (self.err_ty(), None);
1765+
}
1766+
1767+
remaining_segments = remaining_segments.skip(1);
1768+
1769+
// If we can resolve to an enum variant, it takes priority over associated type
1770+
// of the same name.
1771+
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
1772+
let enum_data = self.db.enum_variants(id);
1773+
if let Some(variant) = enum_data.variant(current_segment.name) {
1774+
return if remaining_segments.len() == 1 {
1775+
(ty, Some(variant.into()))
1776+
} else {
1777+
// We still have unresolved paths, but enum variants never have
1778+
// associated types!
1779+
// FIXME: Report an error.
1780+
(self.err_ty(), None)
1781+
};
1782+
}
1783+
}
1784+
1785+
if tried_resolving_once {
1786+
// FIXME: with `inherent_associated_types` this is allowed, but our `lower_partly_resolved_path()`
1787+
// will need to be updated to err at the correct segment.
1788+
//
1789+
// We need to stop here because otherwise the segment index passed to `lower_partly_resolved_path()`
1790+
// will be incorrect, and that can mess up error reporting.
1791+
break;
1792+
}
1793+
1794+
if remaining_segments.is_empty() {
1795+
break;
1796+
}
1797+
}
1798+
drop(ctx);
1799+
1800+
let variant = ty.as_adt().and_then(|(id, _)| match id {
1801+
AdtId::StructId(s) => Some(VariantId::StructId(s)),
1802+
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
1803+
AdtId::EnumId(_) => {
1804+
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
1805+
None
1806+
}
1807+
});
1808+
(ty, variant)
1809+
}
17341810
TypeNs::AdtSelfType(_) => {
17351811
// FIXME this could happen in array size expressions, once we're checking them
17361812
(self.err_ty(), None)
@@ -1741,7 +1817,6 @@ impl<'db> InferenceContext<'db> {
17411817
}
17421818
TypeNs::AdtId(AdtId::EnumId(_))
17431819
| TypeNs::BuiltinType(_)
1744-
| TypeNs::TraitId(_)
17451820
| TypeNs::TraitAliasId(_)
17461821
| TypeNs::ModuleId(_) => {
17471822
// FIXME diagnostic

0 commit comments

Comments
 (0)