Skip to content

Commit

Permalink
cgen: fix comptime generic arg resolution (allow several different st…
Browse files Browse the repository at this point in the history
…ruct fields in generic functions using comptime) (fix #18110) (#21682)
  • Loading branch information
felipensp authored Jun 15, 2024
1 parent 8f7741d commit 3ad77b2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
2 changes: 1 addition & 1 deletion vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
53 changes: 53 additions & 0 deletions vlib/v/tests/generic_comptime_arg_test.v
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 3ad77b2

Please sign in to comment.