1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen,checker: fix method call with comptime var (#16844)

This commit is contained in:
Felipe Pena 2023-01-03 05:14:23 -03:00 committed by GitHub
parent 395ee2b464
commit bd2b216ac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 5 deletions

View File

@ -1578,9 +1578,17 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
mut got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
node.args[i].typ = got_arg_typ
if c.inside_comptime_for_field && method.params[param_idx].typ.has_flag(.generic) {
c.table.register_fn_concrete_types(method.fkey(), [
c.comptime_fields_default_type,
])
arg_sym := c.table.sym(c.comptime_fields_default_type)
if arg_sym.kind == .array
&& c.table.sym(method.params[param_idx].typ).kind == .array {
c.table.register_fn_concrete_types(method.fkey(), [
(arg_sym.info as ast.Array).elem_type,
])
} else {
c.table.register_fn_concrete_types(method.fkey(), [
c.comptime_fields_default_type,
])
}
} else if c.inside_for_in_any_cond && method.params[param_idx].typ.has_flag(.generic) {
c.table.register_fn_concrete_types(method.fkey(), [
c.for_in_any_val_type,

View File

@ -769,6 +769,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
mut unwrapped_rec_type := node.receiver_type
mut has_comptime_field := false
mut for_in_any_var_type := ast.void_type
mut comptime_args := []int{}
if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { // in generic fn
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
} else { // in non-generic fn
@ -795,10 +796,12 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
node_.args[i].typ = call_arg.expr.obj.typ
if call_arg.expr.obj.is_comptime_field {
has_comptime_field = true
comptime_args << i
}
}
} else if mut call_arg.expr is ast.ComptimeSelector {
has_comptime_field = true
comptime_args << i
}
}
}
@ -1130,7 +1133,20 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
}
if g.comptime_for_field_type != 0 && g.inside_comptime_for_field && has_comptime_field {
name = g.generic_fn_name([g.comptime_for_field_type], name)
mut concrete_types := node.concrete_types.map(g.unwrap_generic(it))
arg_sym := g.table.sym(g.comptime_for_field_type)
if m := g.table.find_method(g.table.sym(node.left_type), node.name) {
for k in comptime_args {
if m.generic_names.len > 0 && arg_sym.kind == .array
&& m.params[k + 1].typ.has_flag(.generic)
&& g.table.final_sym(m.params[k + 1].typ).kind == .array {
concrete_types[k] = (arg_sym.info as ast.Array).elem_type
} else {
concrete_types[k] = g.comptime_for_field_type
}
}
}
name = g.generic_fn_name(concrete_types, name)
} else if g.inside_for_in_any_cond && for_in_any_var_type != ast.void_type {
name = g.generic_fn_name([for_in_any_var_type], name)
} else {
@ -1391,7 +1407,8 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
mut concrete_types := node.concrete_types.map(g.unwrap_generic(it))
arg_sym := g.table.sym(g.comptime_for_field_type)
for k in comptime_args {
if arg_sym.kind == .array {
if arg_sym.kind == .array && func.params[k].typ.has_flag(.generic)
&& g.table.sym(func.params[k].typ).kind == .array {
concrete_types[k] = (arg_sym.info as ast.Array).elem_type
} else {
concrete_types[k] = g.comptime_for_field_type

View File

@ -0,0 +1,39 @@
struct EmptyStruct {
a int
b []int
}
struct Encoder {
}
fn (e &Encoder) encode_array[T](val []T) []T {
return val
}
fn encode_struct[T](val T) []string {
e := Encoder{}
mut out := []string{}
$if T is $Struct {
$for field in T.fields {
out << field.name
out << field.is_array.str()
$if field.is_array {
value := val.$(field.name)
out << e.encode_array(value).str()
out << e.encode_array([1, 2]).str()
}
}
}
return out
}
fn test_main() {
out := encode_struct(EmptyStruct{3, [2, 1]})
assert out[0] == 'a'
assert out[1] == 'false'
assert out[2] == 'b'
assert out[3] == 'true'
assert out[4] == '[2, 1]'
assert out[5] == '[1, 2]'
}