Skip to content

Commit 38a3d65

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 38a3d65

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

crates/hir-ty/src/infer.rs

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

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

0 commit comments

Comments
 (0)