mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generated code for returning generic result/option to comptime var (#18834)
This commit is contained in:
parent
6a8a22891d
commit
6b29d628c3
@ -127,9 +127,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
is_decl := node.op == .decl_assign
|
is_decl := node.op == .decl_assign
|
||||||
g.assign_op = node.op
|
g.assign_op = node.op
|
||||||
g.inside_assign = true
|
g.inside_assign = true
|
||||||
|
g.assign_ct_type = 0
|
||||||
defer {
|
defer {
|
||||||
g.assign_op = .unknown
|
g.assign_op = .unknown
|
||||||
g.inside_assign = false
|
g.inside_assign = false
|
||||||
|
g.assign_ct_type = 0
|
||||||
}
|
}
|
||||||
op := if is_decl { token.Kind.assign } else { node.op }
|
op := if is_decl { token.Kind.assign } else { node.op }
|
||||||
right_expr := node.right[0]
|
right_expr := node.right[0]
|
||||||
@ -241,6 +243,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
var_type = val_type.clear_flag(.option)
|
var_type = val_type.clear_flag(.option)
|
||||||
}
|
}
|
||||||
left.obj.typ = var_type
|
left.obj.typ = var_type
|
||||||
|
g.assign_ct_type = var_type
|
||||||
}
|
}
|
||||||
} else if val is ast.ComptimeSelector {
|
} else if val is ast.ComptimeSelector {
|
||||||
key_str := g.get_comptime_selector_key_type(val)
|
key_str := g.get_comptime_selector_key_type(val)
|
||||||
@ -252,11 +255,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
} else {
|
} else {
|
||||||
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||||
}
|
}
|
||||||
|
g.assign_ct_type = var_type
|
||||||
}
|
}
|
||||||
} else if val is ast.ComptimeCall {
|
} else if val is ast.ComptimeCall {
|
||||||
key_str := '${val.method_name}.return_type'
|
key_str := '${val.method_name}.return_type'
|
||||||
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||||
left.obj.typ = var_type
|
left.obj.typ = var_type
|
||||||
|
g.assign_ct_type = var_type
|
||||||
} else if is_decl && val is ast.Ident && val.info is ast.IdentVar {
|
} else if is_decl && val is ast.Ident && val.info is ast.IdentVar {
|
||||||
val_info := (val as ast.Ident).info
|
val_info := (val as ast.Ident).info
|
||||||
gen_or = val.or_expr.kind != .absent
|
gen_or = val.or_expr.kind != .absent
|
||||||
@ -271,6 +276,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
val_type = var_type
|
val_type = var_type
|
||||||
left.obj.typ = var_type
|
left.obj.typ = var_type
|
||||||
}
|
}
|
||||||
|
g.assign_ct_type = var_type
|
||||||
} else if val is ast.IndexExpr {
|
} else if val is ast.IndexExpr {
|
||||||
if val.left is ast.Ident && g.is_generic_param_var(val.left) {
|
if val.left is ast.Ident && g.is_generic_param_var(val.left) {
|
||||||
ctyp := g.unwrap_generic(g.get_gn_var_type(val.left as ast.Ident))
|
ctyp := g.unwrap_generic(g.get_gn_var_type(val.left as ast.Ident))
|
||||||
@ -278,6 +284,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
var_type = ctyp
|
var_type = ctyp
|
||||||
val_type = var_type
|
val_type = var_type
|
||||||
left.obj.typ = var_type
|
left.obj.typ = var_type
|
||||||
|
g.assign_ct_type = var_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,11 +301,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
val_type = g.comptime_var_type_map[key_str_right] or { var_type }
|
val_type = g.comptime_var_type_map[key_str_right] or { var_type }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g.assign_ct_type = var_type
|
||||||
} else if mut left is ast.IndexExpr && val is ast.ComptimeSelector {
|
} else if mut left is ast.IndexExpr && val is ast.ComptimeSelector {
|
||||||
key_str := g.get_comptime_selector_key_type(val)
|
key_str := g.get_comptime_selector_key_type(val)
|
||||||
if key_str != '' {
|
if key_str != '' {
|
||||||
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||||
}
|
}
|
||||||
|
g.assign_ct_type = val_type
|
||||||
}
|
}
|
||||||
mut styp := g.typ(var_type)
|
mut styp := g.typ(var_type)
|
||||||
mut is_fixed_array_init := false
|
mut is_fixed_array_init := false
|
||||||
|
@ -155,6 +155,7 @@ mut:
|
|||||||
skip_stmt_pos bool // for handling if expressions + autofree (since both prepend C statements)
|
skip_stmt_pos bool // for handling if expressions + autofree (since both prepend C statements)
|
||||||
left_is_opt bool // left hand side on assignment is an option
|
left_is_opt bool // left hand side on assignment is an option
|
||||||
right_is_opt bool // right hand side on assignment is an option
|
right_is_opt bool // right hand side on assignment is an option
|
||||||
|
assign_ct_type ast.Type // left hand side resolved comptime type
|
||||||
indent int
|
indent int
|
||||||
empty_line bool
|
empty_line bool
|
||||||
assign_op token.Kind // *=, =, etc (for array_set)
|
assign_op token.Kind // *=, =, etc (for array_set)
|
||||||
|
@ -757,7 +757,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||||||
ret_typ = unaliased_type
|
ret_typ = unaliased_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
styp := g.typ(ret_typ)
|
mut styp := g.typ(ret_typ)
|
||||||
if gen_or && !is_gen_or_and_assign_rhs {
|
if gen_or && !is_gen_or_and_assign_rhs {
|
||||||
cur_line = g.go_before_stmt(0)
|
cur_line = g.go_before_stmt(0)
|
||||||
}
|
}
|
||||||
@ -767,6 +767,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||||||
g.indent++
|
g.indent++
|
||||||
g.write('${tmp_opt} = ')
|
g.write('${tmp_opt} = ')
|
||||||
} else if !g.inside_curry_call {
|
} else if !g.inside_curry_call {
|
||||||
|
if g.assign_ct_type != 0 && node.or_block.kind in [.propagate_option, .propagate_result] {
|
||||||
|
styp = g.typ(g.assign_ct_type.derive(ret_typ))
|
||||||
|
}
|
||||||
g.write('${styp} ${tmp_opt} = ')
|
g.write('${styp} ${tmp_opt} = ')
|
||||||
if node.left is ast.AnonFn {
|
if node.left is ast.AnonFn {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
|
55
vlib/v/tests/option_generic_return_test.v
Normal file
55
vlib/v/tests/option_generic_return_test.v
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
fn opt_parse[T]() ?T {
|
||||||
|
mut cfg := T{}
|
||||||
|
opt_set_val(mut cfg)?
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opt_set_val[T](mut cfg T) ? {
|
||||||
|
$for field in T.fields {
|
||||||
|
$if field.is_array {
|
||||||
|
mut arr := cfg.$(field.name)
|
||||||
|
cfg.$(field.name) = opt_add_val(mut arr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opt_add_val[T](mut arr []T) ?[]T {
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn res_parse[T]() !T {
|
||||||
|
mut cfg := T{}
|
||||||
|
res_set_val(mut cfg)!
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn res_set_val[T](mut cfg T) ! {
|
||||||
|
$for field in T.fields {
|
||||||
|
$if field.is_array {
|
||||||
|
mut arr := cfg.$(field.name)
|
||||||
|
cfg.$(field.name) = res_add_val(mut arr)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn res_add_val[T](mut arr []T) ![]T {
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Strings {
|
||||||
|
val []string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ints {
|
||||||
|
val []int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_option() {
|
||||||
|
assert dump(opt_parse[Strings]()?) == Strings{}
|
||||||
|
assert dump(opt_parse[Ints]()?) == Ints{}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_result() {
|
||||||
|
assert dump(res_parse[Strings]()!) == Strings{}
|
||||||
|
assert dump(res_parse[Ints]()!) == Ints{}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user