From 9c569246efe483b0bc46538e52d7fd57a4f777d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Thu, 12 Nov 2020 12:27:54 +0100 Subject: [PATCH] cgen: fix typeof union sum type (#6794) --- vlib/v/gen/cgen.v | 23 +++++++++++++++++++++++ vlib/v/tests/union_sum_type_test.v | 26 +++++++++++++++++++++----- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index e691ac5ad6..2c9419db26 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -381,6 +381,22 @@ pub fn (mut g Gen) write_typeof_functions() { g.writeln('}') } } + for typ in g.table.types { + if typ.kind == .union_sum_type { + sum_info := typ.info as table.UnionSumType + tidx := g.table.find_type_idx(typ.name) + g.writeln('char * v_typeof_unionsumtype_${tidx}(int sidx) { /* $typ.name */ ') + g.writeln(' switch(sidx) {') + g.writeln(' case $tidx: return "${util.strip_main_name(typ.name)}";') + for v in sum_info.variants { + subtype := g.table.get_type_symbol(v) + g.writeln(' case $v: return "${util.strip_main_name(subtype.name)}";') + } + g.writeln(' default: return "unknown ${util.strip_main_name(typ.name)}";') + g.writeln(' }') + g.writeln('}') + } + } g.writeln('// << typeof() support for sum types') g.writeln('') } @@ -2566,6 +2582,13 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) { g.write('tos3( /* $sym.name */ v_typeof_sumtype_${sum_type_idx}( (') g.expr(node.expr) g.write(').typ ))') + } else if sym.kind == .union_sum_type { + // When encountering a .sum_type, typeof() should be done at runtime, + // because the subtype of the expression may change: + sum_type_idx := node.expr_type.idx() + g.write('tos3( /* $sym.name */ v_typeof_unionsumtype_${sum_type_idx}( (') + g.expr(node.expr) + g.write(').typ ))') } else if sym.kind == .array_fixed { fixed_info := sym.info as table.ArrayFixed typ_name := g.table.get_type_name(fixed_info.elem_type) diff --git a/vlib/v/tests/union_sum_type_test.v b/vlib/v/tests/union_sum_type_test.v index bf41a08bc6..eb231a3c6b 100644 --- a/vlib/v/tests/union_sum_type_test.v +++ b/vlib/v/tests/union_sum_type_test.v @@ -24,7 +24,7 @@ fn handle(e Expr) string { assert is_literal assert !(e !is IntegerLiteral) if e is IntegerLiteral { - println('int') + assert typeof(e.val) == 'string' } match union e { IntegerLiteral { @@ -294,7 +294,7 @@ fn test_nested_if_is() { mut b := Outer(InnerStruct{Inner(0)}) if b is InnerStruct { if b.x is int { - println(b.x) + assert b.x == 0 } } } @@ -303,20 +303,30 @@ fn test_casted_sum_type_selector_reassign() { mut b := InnerStruct{Inner(0)} if b.x is int { assert typeof(b.x) == 'int' + // this check works only if x is castet + assert b.x == 0 b.x = 'test' + // this check works only if x is castet + assert b.x[0] == `t` assert typeof(b.x) == 'string' } - assert typeof(b.x) == 'Inner' + // this check works only if x is not castet + assert b.x is string } fn test_casted_sum_type_ident_reassign() { mut x := Inner(0) if x is int { + // this check works only if x is castet + assert x == 0 assert typeof(x) == 'int' x = 'test' + // this check works only if x is castet + assert x[0] == `t` assert typeof(x) == 'string' } - assert typeof(x) == 'Inner' + // this check works only if x is not castet + assert x is string } __type Expr2 = int | string @@ -427,11 +437,17 @@ fn test_match_multi_branch() { mut y := '' match union f { CallExpr2, CTempVarExpr { - assert typeof(f) == 'Expr4' + // this check works only if f is not castet + assert f is CTempVarExpr } } } +fn test_typeof() { + x := Expr4(CTempVarExpr{}) + assert typeof(x) == 'CTempVarExpr' +} + struct Outer2 { e Expr4 }