diff options
author | Lukas Wirth <[email protected]> | 2021-04-07 10:31:50 +0100 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-04-07 10:31:50 +0100 |
commit | 41563fd6128e94e1fe1ae4006e4e183dff1a645c (patch) | |
tree | 6de6740ca7f028b1e58ce107f414d7a4b67eb5ac /crates/hir_ty/src/infer.rs | |
parent | e6a1c9ca60c19bf3b02b302e21d9f9fd9bd8a466 (diff) |
Infer variants through type aliased enums
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index c63878e7a..796f77ab0 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -484,36 +484,13 @@ impl<'a> InferenceContext<'a> { | |||
484 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 484 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
485 | let substs = generics.type_params_subst(self.db); | 485 | let substs = generics.type_params_subst(self.db); |
486 | let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); | 486 | let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); |
487 | match unresolved { | 487 | self.resolve_variant_on_alias(ty, unresolved, path) |
488 | None => { | ||
489 | let variant = ty_variant(&ty); | ||
490 | (ty, variant) | ||
491 | } | ||
492 | Some(1) => { | ||
493 | let segment = path.mod_path().segments().last().unwrap(); | ||
494 | // this could be an enum variant or associated type | ||
495 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
496 | let enum_data = self.db.enum_data(enum_id); | ||
497 | if let Some(local_id) = enum_data.variant(segment) { | ||
498 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
499 | return (ty, Some(variant.into())); | ||
500 | } | ||
501 | } | ||
502 | // FIXME potentially resolve assoc type | ||
503 | (self.err_ty(), None) | ||
504 | } | ||
505 | Some(_) => { | ||
506 | // FIXME diagnostic | ||
507 | (self.err_ty(), None) | ||
508 | } | ||
509 | } | ||
510 | } | 488 | } |
511 | TypeNs::TypeAliasId(it) => { | 489 | TypeNs::TypeAliasId(it) => { |
512 | let ty = TyBuilder::def_ty(self.db, it.into()) | 490 | let ty = TyBuilder::def_ty(self.db, it.into()) |
513 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 491 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
514 | .build(); | 492 | .build(); |
515 | let variant = ty_variant(&ty); | 493 | self.resolve_variant_on_alias(ty, unresolved, path) |
516 | forbid_unresolved_segments((ty, variant), unresolved) | ||
517 | } | 494 | } |
518 | TypeNs::AdtSelfType(_) => { | 495 | TypeNs::AdtSelfType(_) => { |
519 | // FIXME this could happen in array size expressions, once we're checking them | 496 | // FIXME this could happen in array size expressions, once we're checking them |
@@ -540,16 +517,43 @@ impl<'a> InferenceContext<'a> { | |||
540 | (TyKind::Error.intern(&Interner), None) | 517 | (TyKind::Error.intern(&Interner), None) |
541 | } | 518 | } |
542 | } | 519 | } |
520 | } | ||
543 | 521 | ||
544 | fn ty_variant(ty: &Ty) -> Option<VariantId> { | 522 | fn resolve_variant_on_alias( |
545 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { | 523 | &mut self, |
546 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | 524 | ty: Ty, |
547 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | 525 | unresolved: Option<usize>, |
548 | AdtId::EnumId(_) => { | 526 | path: &Path, |
549 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | 527 | ) -> (Ty, Option<VariantId>) { |
550 | None | 528 | match unresolved { |
529 | None => { | ||
530 | let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id { | ||
531 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | ||
532 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | ||
533 | AdtId::EnumId(_) => { | ||
534 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | ||
535 | None | ||
536 | } | ||
537 | }); | ||
538 | (ty, variant) | ||
539 | } | ||
540 | Some(1) => { | ||
541 | let segment = path.mod_path().segments().last().unwrap(); | ||
542 | // this could be an enum variant or associated type | ||
543 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
544 | let enum_data = self.db.enum_data(enum_id); | ||
545 | if let Some(local_id) = enum_data.variant(segment) { | ||
546 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
547 | return (ty, Some(variant.into())); | ||
548 | } | ||
551 | } | 549 | } |
552 | }) | 550 | // FIXME potentially resolve assoc type |
551 | (self.err_ty(), None) | ||
552 | } | ||
553 | Some(_) => { | ||
554 | // FIXME diagnostic | ||
555 | (self.err_ty(), None) | ||
556 | } | ||
553 | } | 557 | } |
554 | } | 558 | } |
555 | 559 | ||