From 34f233c93fa36d618bf73f1b41c9e43986aade79 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 11 Oct 2022 20:00:02 +0800 Subject: [PATCH] cgen: fix generic struct init with generic cast (#16035) --- vlib/v/gen/c/cgen.v | 12 ++++++--- vlib/v/gen/c/utils.v | 25 +++++++++++++------ ...neric_struct_init_with_generic_cast_test.v | 21 ++++++++++++++++ 3 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 vlib/v/tests/generic_struct_init_with_generic_cast_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 3b7fe610e7..2e2c5b8bb5 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -211,6 +211,7 @@ mut: cur_concrete_types []ast.Type // do not use table.cur_concrete_types because table is global, so should not be accessed by different threads cur_fn &ast.FnDecl = unsafe { nil } // same here cur_lock ast.LockExpr + cur_struct_init_typ ast.Type autofree_methods map[int]bool generated_free_methods map[int]bool autofree_scope_stmts []string @@ -3300,7 +3301,9 @@ fn (mut g Gen) expr(node_ ast.Expr) { } else { // `user := User{name: 'Bob'}` g.inside_struct_init = true + g.cur_struct_init_typ = node.typ g.struct_init(node) + g.cur_struct_init_typ = 0 g.inside_struct_init = false } } @@ -4102,9 +4105,10 @@ fn (mut g Gen) ident(node ast.Ident) { } fn (mut g Gen) cast_expr(node ast.CastExpr) { - sym := g.table.sym(node.typ) + node_typ := g.unwrap_generic(node.typ) + sym := g.table.sym(node_typ) if sym.kind in [.sum_type, .interface_] { - g.expr_with_cast(node.expr, node.expr_type, node.typ) + g.expr_with_cast(node.expr, node.expr_type, node_typ) } else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as ast.Struct).is_typedef { // deprecated, replaced by Struct{...exr} styp := g.typ(node.typ) @@ -4117,7 +4121,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } g.expr(node.expr) } else if node.expr_type == ast.bool_type && node.typ.is_int() { - styp := g.typ(node.typ) + styp := g.typ(node_typ) g.write('($styp[]){(') g.expr(node.expr) g.write(')?1:0}[0]') @@ -4150,7 +4154,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } g.expr(node.expr) if node.expr is ast.IntegerLiteral { - if node.typ in [ast.u64_type, ast.u32_type, ast.u16_type] { + if node_typ in [ast.u64_type, ast.u32_type, ast.u16_type] { if !node.expr.val.starts_with('-') { g.write('U') } diff --git a/vlib/v/gen/c/utils.v b/vlib/v/gen/c/utils.v index aaef3ea208..d61d2e213d 100644 --- a/vlib/v/gen/c/utils.v +++ b/vlib/v/gen/c/utils.v @@ -15,16 +15,27 @@ fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type { // This should have already happened in the checker, since it also calls // `resolve_generic_to_concrete`. `g.table` is made non-mut to make sure // no one else can accidentally mutates the table. - unsafe { - mut mut_table := &ast.Table(g.table) - if t_typ := mut_table.resolve_generic_to_concrete(typ, if g.cur_fn != nil { - g.cur_fn.generic_names - } else { - []string{} - }, g.cur_concrete_types) + mut mut_table := unsafe { &ast.Table(g.table) } + if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { + if t_typ := mut_table.resolve_generic_to_concrete(typ, g.cur_fn.generic_names, + g.cur_concrete_types) { return t_typ } + } else if g.inside_struct_init { + if g.cur_struct_init_typ != 0 { + sym := g.table.sym(g.cur_struct_init_typ) + if sym.info is ast.Struct { + if sym.info.generic_types.len > 0 { + generic_names := sym.info.generic_types.map(g.table.sym(it).name) + if t_typ := mut_table.resolve_generic_to_concrete(typ, generic_names, + sym.info.concrete_types) + { + return t_typ + } + } + } + } } } return typ diff --git a/vlib/v/tests/generic_struct_init_with_generic_cast_test.v b/vlib/v/tests/generic_struct_init_with_generic_cast_test.v new file mode 100644 index 0000000000..14b6036943 --- /dev/null +++ b/vlib/v/tests/generic_struct_init_with_generic_cast_test.v @@ -0,0 +1,21 @@ +pub struct Range { + start T + end T [required] + step T = T(1) +mut: + now T +} + +fn test_generic_struct_init_with_generic_cast() { + r1 := Range{ + end: 10 + } + println(r1) + + r2 := Range{ + end: 2.2 + } + println(r2) + + assert true +}