Infer variants through type aliased enums
This commit is contained in:
parent
e6a1c9ca60
commit
41563fd612
@ -484,36 +484,13 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
|
|||||||
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
|
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
|
||||||
let substs = generics.type_params_subst(self.db);
|
let substs = generics.type_params_subst(self.db);
|
||||||
let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
|
let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
|
||||||
match unresolved {
|
self.resolve_variant_on_alias(ty, unresolved, path)
|
||||||
None => {
|
|
||||||
let variant = ty_variant(&ty);
|
|
||||||
(ty, variant)
|
|
||||||
}
|
|
||||||
Some(1) => {
|
|
||||||
let segment = path.mod_path().segments().last().unwrap();
|
|
||||||
// this could be an enum variant or associated type
|
|
||||||
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
|
||||||
let enum_data = self.db.enum_data(enum_id);
|
|
||||||
if let Some(local_id) = enum_data.variant(segment) {
|
|
||||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
|
||||||
return (ty, Some(variant.into()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// FIXME potentially resolve assoc type
|
|
||||||
(self.err_ty(), None)
|
|
||||||
}
|
|
||||||
Some(_) => {
|
|
||||||
// FIXME diagnostic
|
|
||||||
(self.err_ty(), None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TypeNs::TypeAliasId(it) => {
|
TypeNs::TypeAliasId(it) => {
|
||||||
let ty = TyBuilder::def_ty(self.db, it.into())
|
let ty = TyBuilder::def_ty(self.db, it.into())
|
||||||
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
|
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
|
||||||
.build();
|
.build();
|
||||||
let variant = ty_variant(&ty);
|
self.resolve_variant_on_alias(ty, unresolved, path)
|
||||||
forbid_unresolved_segments((ty, variant), unresolved)
|
|
||||||
}
|
}
|
||||||
TypeNs::AdtSelfType(_) => {
|
TypeNs::AdtSelfType(_) => {
|
||||||
// FIXME this could happen in array size expressions, once we're checking them
|
// FIXME this could happen in array size expressions, once we're checking them
|
||||||
@ -540,16 +517,43 @@ fn forbid_unresolved_segments(
|
|||||||
(TyKind::Error.intern(&Interner), None)
|
(TyKind::Error.intern(&Interner), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ty_variant(ty: &Ty) -> Option<VariantId> {
|
fn resolve_variant_on_alias(
|
||||||
ty.as_adt().and_then(|(adt_id, _)| match adt_id {
|
&mut self,
|
||||||
|
ty: Ty,
|
||||||
|
unresolved: Option<usize>,
|
||||||
|
path: &Path,
|
||||||
|
) -> (Ty, Option<VariantId>) {
|
||||||
|
match unresolved {
|
||||||
|
None => {
|
||||||
|
let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
|
||||||
AdtId::StructId(s) => Some(VariantId::StructId(s)),
|
AdtId::StructId(s) => Some(VariantId::StructId(s)),
|
||||||
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
|
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
|
||||||
AdtId::EnumId(_) => {
|
AdtId::EnumId(_) => {
|
||||||
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
|
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
(ty, variant)
|
||||||
|
}
|
||||||
|
Some(1) => {
|
||||||
|
let segment = path.mod_path().segments().last().unwrap();
|
||||||
|
// this could be an enum variant or associated type
|
||||||
|
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
||||||
|
let enum_data = self.db.enum_data(enum_id);
|
||||||
|
if let Some(local_id) = enum_data.variant(segment) {
|
||||||
|
let variant = EnumVariantId { parent: enum_id, local_id };
|
||||||
|
return (ty, Some(variant.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME potentially resolve assoc type
|
||||||
|
(self.err_ty(), None)
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
// FIXME diagnostic
|
||||||
|
(self.err_ty(), None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2564,3 +2564,36 @@ fn f() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_type_alias_variant() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
type Qux = Foo;
|
||||||
|
enum Foo {
|
||||||
|
Bar(i32),
|
||||||
|
Baz { baz: f32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
match Foo::Bar(3) {
|
||||||
|
Qux::Bar(bar) => (),
|
||||||
|
Qux::Baz { baz } => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
72..166 '{ ... } }': ()
|
||||||
|
78..164 'match ... }': ()
|
||||||
|
84..92 'Foo::Bar': Bar(i32) -> Foo
|
||||||
|
84..95 'Foo::Bar(3)': Foo
|
||||||
|
93..94 '3': i32
|
||||||
|
106..119 'Qux::Bar(bar)': Foo
|
||||||
|
115..118 'bar': i32
|
||||||
|
123..125 '()': ()
|
||||||
|
135..151 'Qux::B... baz }': Foo
|
||||||
|
146..149 'baz': f32
|
||||||
|
155..157 '()': ()
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user