From eb6cbeb28b808e833cf03da9061b086918cb18d7 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 21 Jul 2024 07:45:57 -0300 Subject: [PATCH] checker,cgen: fix typeof(var.typ) with comptime $for variables (#21901) --- vlib/v/checker/tests/typeof_comptime_test.out | 14 +++++++++ vlib/v/checker/tests/typeof_comptime_test.vv | 30 +++++++++++++++++++ vlib/v/comptime/comptimeinfo.v | 26 +++++++++------- vlib/v/gen/c/cgen.v | 1 + vlib/v/gen/c/comptime.v | 3 ++ 5 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 vlib/v/checker/tests/typeof_comptime_test.out create mode 100644 vlib/v/checker/tests/typeof_comptime_test.vv diff --git a/vlib/v/checker/tests/typeof_comptime_test.out b/vlib/v/checker/tests/typeof_comptime_test.out new file mode 100644 index 000000000..dade3d333 --- /dev/null +++ b/vlib/v/checker/tests/typeof_comptime_test.out @@ -0,0 +1,14 @@ +field> 8 int +variant> 8 int +SumType(123) +field> 8 int +field> 21 string +variant> 8 int +variant> 21 string +SumType('foo') +field> 8 int +variant> 8 int +field> 8 int +field> 21 string +variant> 8 int +variant> 21 string diff --git a/vlib/v/checker/tests/typeof_comptime_test.vv b/vlib/v/checker/tests/typeof_comptime_test.vv new file mode 100644 index 000000000..082f08a3d --- /dev/null +++ b/vlib/v/checker/tests/typeof_comptime_test.vv @@ -0,0 +1,30 @@ +type SumType = int | string + +struct Test { + a int + b string +} + +fn get_as_sumtype[T, R](struct_ T, name string, typname string) R { + $for f2 in T.fields { + println('field> ${f2.typ} ${typeof(f2.typ).name}') + if f2.name == name { + val := struct_.$(f2.name) + $for f in R.variants { + println('variant> ${f.typ} ${typeof(f.typ).name}') + if typeof(f.typ).name == typname { + return R(val) + } + } + } + } + return R{} +} + +fn test_main() { + println(get_as_sumtype[Test, SumType](Test{ a: 123 }, 'a', 'int')) + println(get_as_sumtype[Test, SumType](Test{ b: 'foo' }, 'b', 'string')) + + assert get_as_sumtype[Test, SumType](Test{ a: 123 }, 'a', 'int') == SumType(123) + assert get_as_sumtype[Test, SumType](Test{ b: 'foo' }, 'b', 'string') == SumType('foo') +} diff --git a/vlib/v/comptime/comptimeinfo.v b/vlib/v/comptime/comptimeinfo.v index 86388a513..bc1edf3e6 100644 --- a/vlib/v/comptime/comptimeinfo.v +++ b/vlib/v/comptime/comptimeinfo.v @@ -93,17 +93,7 @@ pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type { // val.$(field.name) return ct.get_comptime_selector_type(node, ast.void_type) } else if node is ast.SelectorExpr && ct.is_comptime_selector_type(node) { - if node.expr is ast.Ident { - match node.expr.name { - ct.comptime_for_variant_var { - return ct.type_map['${ct.comptime_for_variant_var}.typ'] - } - else { - // field_var.typ from $for field - return ct.comptime_for_field_type - } - } - } + return ct.get_type_from_comptime_var(node.expr as ast.Ident) } else if node is ast.ComptimeCall { method_name := ct.comptime_for_method left_sym := ct.table.sym(ct.resolver.unwrap_generic(node.left_type)) @@ -117,6 +107,20 @@ pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type { return ast.void_type } +// get_type_from_comptime_var retrives the comptime type related to $for variable +@[inline] +pub fn (mut ct ComptimeInfo) get_type_from_comptime_var(var ast.Ident) ast.Type { + return match var.name { + ct.comptime_for_variant_var { + ct.type_map['${ct.comptime_for_variant_var}.typ'] + } + else { + // field_var.typ from $for field + ct.comptime_for_field_type + } + } +} + pub fn (mut ct ComptimeInfo) get_comptime_selector_var_type(node ast.ComptimeSelector) (ast.StructField, string) { field_name := ct.comptime_for_field_value.name left_sym := ct.table.sym(ct.resolver.unwrap_generic(node.left_type)) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 2ed076824..b4255d23e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -324,6 +324,7 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) (str inner_loop: unsafe { &ast.empty_stmt } field_data_type: ast.Type(table.find_type_idx('FieldData')) enum_data_type: ast.Type(table.find_type_idx('EnumData')) + variant_data_type: ast.Type(table.find_type_idx('VariantData')) is_cc_msvc: pref_.ccompiler == 'msvc' use_segfault_handler: !('no_segfault_handler' in pref_.compile_defines || pref_.os in [.wasm32, .wasm32_emscripten]) diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index ed222ecaf..23b4a1a91 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -767,6 +767,9 @@ fn (mut g Gen) resolve_comptime_type(node ast.Expr, default_type ast.Type) ast.T if (node is ast.Ident && g.comptime.is_comptime_var(node)) || node is ast.ComptimeSelector { return g.comptime.get_comptime_var_type(node) } else if node is ast.SelectorExpr && node.expr_type != 0 { + if node.expr is ast.Ident && g.comptime.is_comptime_selector_type(node) { + return g.comptime.get_type_from_comptime_var(node.expr) + } sym := g.table.sym(g.unwrap_generic(node.expr_type)) if f := g.table.find_field_with_embeds(sym, node.field_name) { return f.typ -- 2.39.5