vlang

/

v Public
0 commits 39 issues 0 pull requests 0 contributors Discussions Projects CI

committed 56 years ago · View patch
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)