1 files changed
+39
-3
vlib/v/gen/c/match.v
+39
-3
@@ -194,6 +194,14 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str |
|||
| 194 | 194 | dot_or_ptr := g.dot_or_ptr(node.cond_type) |
|
| 195 | 195 | use_ternary := is_expr && tmp_var == '' |
|
| 196 | 196 | cond_sym := g.table.final_sym(node.cond_type) |
|
| 197 | + | // Tracks the runtime type tags already handled by earlier arms of this match. |
|
| 198 | + | // With alias/runtime-tag matching, a variant and an alias of it (e.g. `u8` and |
|
| 199 | + | // `type EmptyExpr = u8`, both variants of the same sumtype) expand to the same |
|
| 200 | + | // set of tags, so distinct arms can produce identical `_typ == ...` conditions. |
|
| 201 | + | // Emitting both yields a duplicated `else if` condition (a -Wduplicated-cond |
|
| 202 | + | // error under -cstrict) and the later arm is unreachable anyway, so drop the |
|
| 203 | + | // already-covered tags and skip an arm once nothing fresh remains. |
|
| 204 | + | mut seen_tag_idxs := map[string]bool{} |
|
| 197 | 205 | for j, branch in node.branches { |
|
| 198 | 206 | mut sumtype_index := 0 |
|
| 199 | 207 | // iterates through all types in sumtype branches |
|
@@ -210,6 +218,36 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str |
|||
| 210 | 218 | branch_type = branch_expr.typ |
|
| 211 | 219 | } |
|
| 212 | 220 | } |
|
| 221 | + | mut sumtype_fresh_idx_exprs := []string{} |
|
| 222 | + | if !branch.is_else && cond_sym.kind == .sum_type && sumtype_index < branch.exprs.len { |
|
| 223 | + | ce := unsafe { &branch.exprs[sumtype_index] } |
|
| 224 | + | if ce is ast.TypeNode { |
|
| 225 | + | variant_type := g.unwrap_generic(g.recheck_concrete_type(ce.typ)) |
|
| 226 | + | all_idx_exprs := g.matching_sumtype_variant_type_idx_exprs(node.cond_type, |
|
| 227 | + | variant_type) |
|
| 228 | + | if use_ternary { |
|
| 229 | + | // Ternary `?:` chains cannot drop an arm, so keep every tag. |
|
| 230 | + | sumtype_fresh_idx_exprs = all_idx_exprs.clone() |
|
| 231 | + | } else { |
|
| 232 | + | for idx_expr in all_idx_exprs { |
|
| 233 | + | if idx_expr !in seen_tag_idxs { |
|
| 234 | + | sumtype_fresh_idx_exprs << idx_expr |
|
| 235 | + | } |
|
| 236 | + | } |
|
| 237 | + | if sumtype_fresh_idx_exprs.len == 0 { |
|
| 238 | + | // every tag of this arm is already handled above: unreachable, skip it |
|
| 239 | + | sumtype_index++ |
|
| 240 | + | if branch.exprs.len == 0 || sumtype_index == branch.exprs.len { |
|
| 241 | + | break |
|
| 242 | + | } |
|
| 243 | + | continue |
|
| 244 | + | } |
|
| 245 | + | for idx_expr in sumtype_fresh_idx_exprs { |
|
| 246 | + | seen_tag_idxs[idx_expr] = true |
|
| 247 | + | } |
|
| 248 | + | } |
|
| 249 | + | } |
|
| 250 | + | } |
|
| 213 | 251 | if branch.is_else || (use_ternary && is_last) { |
|
| 214 | 252 | if use_ternary { |
|
| 215 | 253 | // TODO: too many branches. maybe separate ?: matches |
|
@@ -248,9 +286,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str |
|||
| 248 | 286 | if cur_expr is ast.None { |
|
| 249 | 287 | g.write('${tag_expr} == ${ast.none_type.idx()} /* none */') |
|
| 250 | 288 | } else if cur_expr is ast.TypeNode { |
|
| 251 | - | variant_type := g.unwrap_generic(g.recheck_concrete_type(cur_expr.typ)) |
|
| 252 | - | g.write_type_tag_condition(tag_expr, '==', g.matching_sumtype_variant_type_idx_exprs(node.cond_type, |
|
| 253 | - | variant_type)) |
|
| 289 | + | g.write_type_tag_condition(tag_expr, '==', sumtype_fresh_idx_exprs) |
|
| 254 | 290 | } else { |
|
| 255 | 291 | g.write('${tag_expr} == ') |
|
| 256 | 292 | g.expr(cur_expr) |
|