Skip to content

Commit 64f9379

Browse files
committed
implement feature(more_qualified_paths)
Specifically, this allows the following patterns and expressions which were not allowed before: ```rust let <T as Trait>::Assoc { a } = <T as Trait>::Assoc { a: 0 }; let (<E as Trait>::Assoc::ES { a } | <E as Trait>::Assoc::ET(a)) = <E as Trait>::Assoc::ES { a: 0 }; let (<E>::ES { a } | <E>::ET(a)) = <E>::ES { a: 0 }; ```
1 parent bf6d445 commit 64f9379

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

crates/hir-ty/src/infer.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,25 @@ impl<'db> InferenceContext<'db> {
15891589
self.generic_def,
15901590
LifetimeElisionKind::Infer,
15911591
);
1592+
1593+
if let Some(type_anchor) = path.type_anchor() {
1594+
let segments = path.segments();
1595+
if segments.len() != 1 {
1596+
return (self.err_ty(), None);
1597+
}
1598+
let ty = ctx.lower_ty(type_anchor);
1599+
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
1600+
let enum_data = self.db.enum_variants(id);
1601+
if let Some(variant) = enum_data.variant(segments.first().unwrap().name) {
1602+
// FIXME: Report error if there are generics on the variant.
1603+
return (ty, Some(variant.into()));
1604+
}
1605+
} else {
1606+
// FIXME: Report an error.
1607+
return (self.err_ty(), None);
1608+
}
1609+
}
1610+
15921611
let mut path_ctx = ctx.at_path(path, node);
15931612
let (resolution, unresolved) = if value_ns {
15941613
let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else {
@@ -1719,6 +1738,48 @@ impl<'db> InferenceContext<'db> {
17191738
});
17201739
(ty, variant)
17211740
}
1741+
TypeNs::TraitId(_) => {
1742+
let Some(remaining_idx) = unresolved else {
1743+
return (self.err_ty(), None);
1744+
};
1745+
1746+
let remaining_segments = path.segments().skip(remaining_idx);
1747+
1748+
if remaining_segments.len() >= 2 {
1749+
path_ctx.ignore_last_segment();
1750+
}
1751+
1752+
let (mut ty, _) = path_ctx.lower_partly_resolved_path(resolution, true);
1753+
ty = self.table.insert_type_vars(ty);
1754+
ty = self.table.normalize_associated_types_in(ty);
1755+
ty = self.table.resolve_ty_shallow(&ty);
1756+
1757+
if let Some(segment) = remaining_segments.get(1) {
1758+
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
1759+
let enum_data = self.db.enum_variants(id);
1760+
if let Some(variant) = enum_data.variant(segment.name) {
1761+
return if remaining_segments.len() == 2 {
1762+
(ty, Some(variant.into()))
1763+
} else {
1764+
// We still have unresolved paths, but enum variants never have
1765+
// associated types!
1766+
// FIXME: Report an error.
1767+
(self.err_ty(), None)
1768+
};
1769+
}
1770+
}
1771+
}
1772+
1773+
let variant = ty.as_adt().and_then(|(id, _)| match id {
1774+
AdtId::StructId(s) => Some(VariantId::StructId(s)),
1775+
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
1776+
AdtId::EnumId(_) => {
1777+
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
1778+
None
1779+
}
1780+
});
1781+
(ty, variant)
1782+
}
17221783
TypeNs::TypeAliasId(it) => {
17231784
let Some(mod_path) = path.mod_path() else {
17241785
never!("resolver should always resolve lang item paths");
@@ -1741,7 +1802,6 @@ impl<'db> InferenceContext<'db> {
17411802
}
17421803
TypeNs::AdtId(AdtId::EnumId(_))
17431804
| TypeNs::BuiltinType(_)
1744-
| TypeNs::TraitId(_)
17451805
| TypeNs::TraitAliasId(_)
17461806
| TypeNs::ModuleId(_) => {
17471807
// FIXME diagnostic

0 commit comments

Comments
 (0)