Skip to content

Commit f407d6d

Browse files
authored
ast, checker, cgen: fix generics multiple type comptime call (fix #12777) (#12806)
1 parent ab6e933 commit f407d6d

File tree

5 files changed

+50
-10
lines changed

5 files changed

+50
-10
lines changed

cmd/tools/vast/vast.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,11 +966,11 @@ fn (t Tree) comptime_call(node ast.ComptimeCall) &Node {
966966
obj.add_terse('is_vweb', t.bool_node(node.is_vweb))
967967
obj.add_terse('vweb_tmpl', t.string_node(node.vweb_tmpl.path))
968968
obj.add_terse('args_var', t.string_node(node.args_var))
969-
obj.add_terse('sym', t.string_node(node.sym.name))
970969
obj.add_terse('has_parens', t.bool_node(node.has_parens))
971970
obj.add_terse('is_embed', t.bool_node(node.is_embed))
972971
obj.add_terse('embed_file', t.embed_file(node.embed_file))
973972
obj.add('method_pos', t.position(node.method_pos))
973+
obj.add_terse('left_type', t.type_node(node.left_type))
974974
obj.add_terse('result_type', t.type_node(node.result_type))
975975
obj.add('scope', t.scope(node.scope))
976976
obj.add_terse('env_value', t.string_node(node.env_value))

vlib/v/ast/ast.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,7 @@ pub:
15591559
//
15601560
is_pkgconfig bool
15611561
pub mut:
1562-
sym TypeSymbol
1562+
left_type Type
15631563
result_type Type
15641564
env_value string
15651565
args []CallArg

vlib/v/checker/comptime.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import v.pkgconfig
1010

1111
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
1212
sym := c.table.get_type_symbol(c.unwrap_generic(c.expr(node.left)))
13-
node.sym = *sym
13+
node.left_type = c.expr(node.left)
1414
if node.is_env {
1515
env_value := util.resolve_env_value("\$env('$node.args_var')", false) or {
1616
c.error(err.msg, node.env_pos)
@@ -91,7 +91,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
9191
} else {
9292
c.error('todo: not a string literal', node.method_pos)
9393
}
94-
f := node.sym.find_method(method_name) or {
94+
f := sym.find_method(method_name) or {
9595
c.error('could not find method `$method_name`', node.method_pos)
9696
return ast.void_type
9797
}

vlib/v/gen/c/comptime.v

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
7676
}
7777
return
7878
}
79-
g.trace_autofree('// \$method call. sym="$node.sym.name"')
79+
sym := g.table.get_type_symbol(g.unwrap_generic(node.left_type))
80+
g.trace_autofree('// \$method call. sym="$sym.name"')
8081
if node.method_name == 'method' {
8182
// `app.$method()`
82-
m := node.sym.find_method(g.comptime_for_method) or { return }
83+
m := sym.find_method(g.comptime_for_method) or { return }
8384
/*
8485
vals := m.attrs[0].split('/')
8586
args := vals.filter(it.starts_with(':')).map(it[1..])
@@ -99,15 +100,15 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
99100
// check argument length and types
100101
if m.params.len - 1 != node.args.len && !expand_strs {
101102
// do not generate anything if the argument lengths don't match
102-
g.writeln('/* skipping ${node.sym.name}.$m.name due to mismatched arguments list */')
103+
g.writeln('/* skipping ${sym.name}.$m.name due to mismatched arguments list */')
103104
// g.writeln('println(_SLIT("skipping ${node.sym.name}.$m.name due to mismatched arguments list"));')
104105
// eprintln('info: skipping ${node.sym.name}.$m.name due to mismatched arguments list\n' +
105106
//'method.params: $m.params, args: $node.args\n\n')
106107
// verror('expected ${m.params.len-1} arguments to method ${node.sym.name}.$m.name, but got $node.args.len')
107108
return
108109
}
109110
// TODO: check argument types
110-
g.write('${util.no_dots(node.sym.name)}_${g.comptime_for_method}(')
111+
g.write('${util.no_dots(sym.name)}_${g.comptime_for_method}(')
111112

112113
// try to see if we need to pass a pointer
113114
if node.left is ast.Ident {
@@ -153,7 +154,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
153154
return
154155
}
155156
mut j := 0
156-
for method in node.sym.methods {
157+
for method in sym.methods {
157158
// if method.return_type != ast.void_type {
158159
if method.return_type != node.result_type {
159160
continue
@@ -172,7 +173,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
172173
}
173174
g.write('if (string__eq($node.method_name, _SLIT("$method.name"))) ')
174175
}
175-
g.write('${util.no_dots(node.sym.name)}_${method.name}($amp ')
176+
g.write('${util.no_dots(sym.name)}_${method.name}($amp ')
176177
g.expr(node.left)
177178
g.writeln(');')
178179
j++
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
struct Foo {}
2+
3+
['/'; 'GET']
4+
fn (mut f Foo) hello() string {
5+
return @FN
6+
}
7+
8+
struct Bar {}
9+
10+
['/'; 'GET']
11+
fn (b &Bar) world() string {
12+
return @FN
13+
}
14+
15+
fn execute_methods<T>() string {
16+
tmp := T{}
17+
$for method in T.methods {
18+
if method.attrs.len >= 2 {
19+
fun_path := method.attrs[0]
20+
fun_method := method.attrs[1]
21+
22+
if fun_path == '/' && fun_method == 'GET' {
23+
ret := tmp.$method()
24+
return ret
25+
}
26+
}
27+
}
28+
return ''
29+
}
30+
31+
fn test_generics_multi_type_comptime_call() {
32+
ret1 := execute_methods<Foo>()
33+
println(ret1)
34+
assert ret1 == 'hello'
35+
36+
ret2 := execute_methods<Bar>()
37+
println(ret2)
38+
assert ret2 == 'world'
39+
}

0 commit comments

Comments
 (0)