@@ -684,6 +684,49 @@ fn (mut c Checker) get_match_case_literal_value(mut expr ast.Expr) ?i64 {
684684 return none
685685}
686686
687+ fn (mut c Checker) match_sumtype_has_variant (parent ast.Type, variant ast.Type) bool {
688+ if c.table.sumtype_has_variant_recursive (parent, variant, true ) {
689+ return true
690+ }
691+ if c.table.sym (parent).kind == .sum_type {
692+ return false
693+ }
694+ for candidate in c.concrete_sumtype_variants (parent) {
695+ if c.match_sumtype_variant_is_handled (candidate, variant) {
696+ return true
697+ }
698+ }
699+ return false
700+ }
701+
702+ fn (mut c Checker) match_sumtype_missing_variants (parent ast.Type, handled []ast.Type) []ast.Type {
703+ if c.table.sym (parent).kind == .sum_type {
704+ return c.table.sumtype_missing_variants (parent, handled)
705+ }
706+ mut missing := []ast.Type{}
707+ for variant in c.concrete_sumtype_variants (parent) {
708+ mut is_handled := false
709+ for handled_variant in handled {
710+ if c.match_sumtype_variant_is_handled (variant, handled_variant) {
711+ is_handled = true
712+ break
713+ }
714+ }
715+ if ! is_handled {
716+ missing << variant
717+ }
718+ }
719+ return missing
720+ }
721+
722+ fn (mut c Checker) match_sumtype_variant_is_handled (variant ast.Type, handled ast.Type) bool {
723+ unaliased_variant := c.table.fully_unaliased_type (variant)
724+ unaliased_handled := c.table.fully_unaliased_type (handled)
725+ return unaliased_variant.idx () == unaliased_handled.idx ()
726+ && unaliased_variant.has_flag (.option) == unaliased_handled.has_flag (.option)
727+ && unaliased_variant.nr_muls () == unaliased_handled.nr_muls ()
728+ }
729+
687730fn (mut c Checker) match_exprs (mut node ast.MatchExpr, cond_type_sym ast.TypeSymbol, cond_final_sym ast.TypeSymbol) {
688731 c.expected_type = node.expected_type
689732 if node.cond_type.idx () == 0 {
@@ -694,6 +737,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
694737 is_alias_to_matchable_type := cond_type_sym.kind == .alias
695738 && cond_final_sym.kind in [.interface , .sum_type]
696739 cond_match_sym := if is_alias_to_matchable_type { cond_final_sym } else { cond_type_sym }
740+ sumtype_match_variants := c.concrete_sumtype_variants (cond_match_type)
741+ is_cond_match_sumtype := sumtype_match_variants.len > 0
697742 mut enum_ref_checked := false
698743 mut is_comptime_value_match := false
699744 // branch_exprs is a histogram of how many times
@@ -908,12 +953,12 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
908953 }
909954 }
910955 }
911- } else if cond_match_sym.info is ast.SumType {
912- if ! c.table. sumtype_has_variant_recursive (cond_match_type, expr_type, true ) {
956+ } else if is_cond_match_sumtype {
957+ if ! c.match_sumtype_has_variant (cond_match_type, expr_type) {
913958 expr_str := c.table.type_to_str (expr_type)
914959 expect_str := c.table.type_to_str (node.cond_type)
915960 sumtype_variant_names :=
916- c.table. sumtype_matchable_variants (cond_match_type) .map (c.table.type_to_str_using_aliases (it , {}))
961+ sumtype_match_variants .map (c.table.type_to_str_using_aliases (it , {}))
917962 suggestion := util.new_suggestion (expr_str, sumtype_variant_names)
918963 c.error (suggestion.say ('`${expect_str }` has no variant `${expr_str }`' ),
919964 expr.pos ())
@@ -941,7 +986,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
941986 }
942987 // when match is type matching, then register smart cast for every branch
943988 if expr_types.len > 0 {
944- if cond_match_sym.kind in [.sum_type, . interface ] {
989+ if is_cond_match_sumtype || cond_match_sym.kind == . interface {
945990 mut expr_type := ast.no_type
946991 if expr_types.len > 1 {
947992 mut agg_name := strings.new_builder (20 )
@@ -999,34 +1044,34 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
9991044 }
10001045 }
10011046 } else {
1002- match cond_match_sym.info {
1003- ast.SumType {
1004- for v in c.table.sumtype_missing_variants (cond_match_type, branch_expr_types) {
1005- is_exhaustive = false
1006- unhandled << '`${c .table .type_to_str (v )}`'
1007- }
1047+ if is_cond_match_sumtype {
1048+ for v in c.match_sumtype_missing_variants (cond_match_type, branch_expr_types) {
1049+ is_exhaustive = false
1050+ unhandled << '`${c .table .type_to_str (v )}`'
10081051 }
1009- //
1010- ast.Enum {
1011- for v in cond_match_sym.info.vals {
1012- mut is_handled := v in branch_exprs
1013- if ! is_handled && is_multi_allowed_enum_match {
1014- if enum_val := c.table.find_enum_field_val (cond_match_sym.name, v) {
1015- is_handled = enum_val in branch_enum_values
1052+ } else {
1053+ match cond_match_sym.info {
1054+ ast.Enum {
1055+ for v in cond_match_sym.info.vals {
1056+ mut is_handled := v in branch_exprs
1057+ if ! is_handled && is_multi_allowed_enum_match {
1058+ if enum_val := c.table.find_enum_field_val (cond_match_sym.name, v) {
1059+ is_handled = enum_val in branch_enum_values
1060+ }
1061+ }
1062+ if ! is_handled {
1063+ is_exhaustive = false
1064+ unhandled << '`.${v }`'
10161065 }
10171066 }
1018- if ! is_handled {
1067+ if cond_match_sym.info.is_flag {
10191068 is_exhaustive = false
1020- unhandled << '`.${v }`'
10211069 }
10221070 }
1023- if cond_match_sym.info.is_flag {
1071+ else {
10241072 is_exhaustive = false
10251073 }
10261074 }
1027- else {
1028- is_exhaustive = false
1029- }
10301075 }
10311076 }
10321077 if node.branches.len == 0 {
0 commit comments