aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-07 10:35:40 +0100
committerGitHub <[email protected]>2021-04-07 10:35:40 +0100
commita8f1e41f0f15fee02a73850db559752a9124d014 (patch)
treef3325cfcd6565c87f93a9215d44106203eb20d9b /crates/hir_ty
parentad50f5007f7fe0e02b128a2643cfca2468056f9a (diff)
parent41563fd6128e94e1fe1ae4006e4e183dff1a645c (diff)
Merge #8394
8394: Infer variants through type aliased enums r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/infer.rs70
-rw-r--r--crates/hir_ty/src/tests/simple.rs33
2 files changed, 70 insertions, 33 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 7c6c3600b..6af0c59b8 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -487,36 +487,13 @@ impl<'a> InferenceContext<'a> {
487 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 487 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
488 let substs = generics.type_params_subst(self.db); 488 let substs = generics.type_params_subst(self.db);
489 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); 489 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
490 match unresolved { 490 self.resolve_variant_on_alias(ty, unresolved, path)
491 None => {
492 let variant = ty_variant(&ty);
493 (ty, variant)
494 }
495 Some(1) => {
496 let segment = path.mod_path().segments().last().unwrap();
497 // this could be an enum variant or associated type
498 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
499 let enum_data = self.db.enum_data(enum_id);
500 if let Some(local_id) = enum_data.variant(segment) {
501 let variant = EnumVariantId { parent: enum_id, local_id };
502 return (ty, Some(variant.into()));
503 }
504 }
505 // FIXME potentially resolve assoc type
506 (self.err_ty(), None)
507 }
508 Some(_) => {
509 // FIXME diagnostic
510 (self.err_ty(), None)
511 }
512 }
513 } 491 }
514 TypeNs::TypeAliasId(it) => { 492 TypeNs::TypeAliasId(it) => {
515 let ty = TyBuilder::def_ty(self.db, it.into()) 493 let ty = TyBuilder::def_ty(self.db, it.into())
516 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 494 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
517 .build(); 495 .build();
518 let variant = ty_variant(&ty); 496 self.resolve_variant_on_alias(ty, unresolved, path)
519 forbid_unresolved_segments((ty, variant), unresolved)
520 } 497 }
521 TypeNs::AdtSelfType(_) => { 498 TypeNs::AdtSelfType(_) => {
522 // FIXME this could happen in array size expressions, once we're checking them 499 // FIXME this could happen in array size expressions, once we're checking them
@@ -543,16 +520,43 @@ impl<'a> InferenceContext<'a> {
543 (TyKind::Error.intern(&Interner), None) 520 (TyKind::Error.intern(&Interner), None)
544 } 521 }
545 } 522 }
523 }
546 524
547 fn ty_variant(ty: &Ty) -> Option<VariantId> { 525 fn resolve_variant_on_alias(
548 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 526 &mut self,
549 AdtId::StructId(s) => Some(VariantId::StructId(s)), 527 ty: Ty,
550 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 528 unresolved: Option<usize>,
551 AdtId::EnumId(_) => { 529 path: &Path,
552 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` 530 ) -> (Ty, Option<VariantId>) {
553 None 531 match unresolved {
532 None => {
533 let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
534 AdtId::StructId(s) => Some(VariantId::StructId(s)),
535 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
536 AdtId::EnumId(_) => {
537 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
538 None
539 }
540 });
541 (ty, variant)
542 }
543 Some(1) => {
544 let segment = path.mod_path().segments().last().unwrap();
545 // this could be an enum variant or associated type
546 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
547 let enum_data = self.db.enum_data(enum_id);
548 if let Some(local_id) = enum_data.variant(segment) {
549 let variant = EnumVariantId { parent: enum_id, local_id };
550 return (ty, Some(variant.into()));
551 }
554 } 552 }
555 }) 553 // FIXME potentially resolve assoc type
554 (self.err_ty(), None)
555 }
556 Some(_) => {
557 // FIXME diagnostic
558 (self.err_ty(), None)
559 }
556 } 560 }
557 } 561 }
558 562
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 361cd6302..84c5c05fd 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2564,3 +2564,36 @@ fn f() {
2564 "#, 2564 "#,
2565 ) 2565 )
2566} 2566}
2567
2568#[test]
2569fn infer_type_alias_variant() {
2570 check_infer(
2571 r#"
2572type Qux = Foo;
2573enum Foo {
2574 Bar(i32),
2575 Baz { baz: f32 }
2576}
2577
2578fn f() {
2579 match Foo::Bar(3) {
2580 Qux::Bar(bar) => (),
2581 Qux::Baz { baz } => (),
2582 }
2583}
2584 "#,
2585 expect![[r#"
2586 72..166 '{ ... } }': ()
2587 78..164 'match ... }': ()
2588 84..92 'Foo::Bar': Bar(i32) -> Foo
2589 84..95 'Foo::Bar(3)': Foo
2590 93..94 '3': i32
2591 106..119 'Qux::Bar(bar)': Foo
2592 115..118 'bar': i32
2593 123..125 '()': ()
2594 135..151 'Qux::B... baz }': Foo
2595 146..149 'baz': f32
2596 155..157 '()': ()
2597 "#]],
2598 )
2599}