diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 686e6464459e0e..20eff3b01d7bf0 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1595,10 +1595,10 @@ fn (mut c Checker) resolve_comptime_args(func ast.Fn, node_ ast.CallExpr, concre } else { func.params[offset + i] } - k++ if !param.typ.has_flag(.generic) { continue } + k++ param_typ := param.typ if call_arg.expr is ast.Ident { if call_arg.expr.obj is ast.Var { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 4032110be47f15..7f7f675e5aa649 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1186,10 +1186,10 @@ fn (mut g Gen) resolve_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concre } else { func.params[offset + i] } - k++ if !param.typ.has_flag(.generic) { continue } + k++ param_typ := param.typ if mut call_arg.expr is ast.Ident { if mut call_arg.expr.obj is ast.Var { diff --git a/vlib/v/tests/generic_comptime_arg_test.v b/vlib/v/tests/generic_comptime_arg_test.v new file mode 100644 index 00000000000000..ecdf015d7a11b8 --- /dev/null +++ b/vlib/v/tests/generic_comptime_arg_test.v @@ -0,0 +1,53 @@ +import toml + +struct Parent { + name string + child1 Child1 + child2 Child2 +} + +struct Child1 { + name string +} + +struct Child2 { + age int +} + +fn decode[T](toml_str string) !T { + doc := toml.parse_text(toml_str)! + + return decode_struct(doc.to_any(), &T{}) +} + +// `T` param serves here as a workaround to allow to infer types of nested struct fields. +fn decode_struct[T](doc toml.Any, typ &T) T { + mut res := T{} + $for field in T.fields { + val := doc.value(field.name) + $if field.typ is string { + res.$(field.name) = val.string() + } $else $if field.typ is int { + res.$(field.name) = val.int() + } $else $if field.is_struct { + typ_ := typ.$(field.name) + res.$(field.name) = decode_struct(val, &typ_) + } + } + return res +} + +fn test_main() { + toml_str := 'name = "John" + child1 = { name = "abc" } + child2 = { age = 5 }' + + a := dump(decode[Parent](toml_str)!) + assert a.name == 'John' + assert a.child1 == Child1{ + name: 'abc' + } + assert a.child2 == Child2{ + age: 5 + } +}