Skip to content

Commit 00e0eae

Browse files
authored
cgen: fix codegen for generic interface with multi return generic type (fix #24838) (#24858)
1 parent e62ed47 commit 00e0eae

2 files changed

Lines changed: 72 additions & 7 deletions

File tree

‎vlib/v/gen/c/cgen.v‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) GenO
502502
global_g.gen_array_index_methods()
503503
global_g.gen_equality_fns()
504504
global_g.gen_free_methods()
505+
global_g.register_iface_return_types()
505506
global_g.write_results()
506507
global_g.write_options()
507508
global_g.sort_globals_consts()
@@ -5807,7 +5808,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
58075808

58085809
exprs_len := node.exprs.len
58095810
expr0 := if exprs_len > 0 { node.exprs[0] } else { ast.empty_expr }
5810-
type0 := if exprs_len > 0 { node.types[0] } else { ast.void_type }
5811+
type0 := if exprs_len > 0 { g.unwrap_generic(node.types[0]) } else { ast.void_type }
58115812

58125813
if exprs_len > 0 {
58135814
// skip `return $vweb.html()`
@@ -5819,15 +5820,15 @@ fn (mut g Gen) return_stmt(node ast.Return) {
58195820
return
58205821
}
58215822
}
5822-
ret_type := g.fn_decl.return_type
5823+
ret_type := g.unwrap_generic(g.fn_decl.return_type)
58235824

58245825
// got to do a correct check for multireturn
5825-
sym := g.table.sym(g.unwrap_generic(ret_type))
5826+
sym := g.table.sym(ret_type)
58265827
mut fn_ret_type := ret_type
58275828
if sym.kind == .alias {
58285829
unaliased_type := g.table.unaliased_type(fn_ret_type)
58295830
if unaliased_type.has_option_or_result() {
5830-
fn_ret_type = unaliased_type
5831+
fn_ret_type = g.unwrap_generic(unaliased_type)
58315832
}
58325833
}
58335834
fn_return_is_multi := sym.kind == .multi_return
@@ -5857,7 +5858,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
58575858
}
58585859
tmpvar := g.new_tmp_var()
58595860
g.defer_return_tmp_var = tmpvar
5860-
ret_typ := g.ret_styp(g.unwrap_generic(fn_ret_type))
5861+
ret_typ := g.ret_styp(fn_ret_type)
58615862

58625863
// `return fn_call_opt()`
58635864
if exprs_len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr
@@ -6077,7 +6078,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
60776078
node.pos)
60786079
}
60796080
// normal return
6080-
return_sym := g.table.final_sym(g.unwrap_generic(type0))
6081+
return_sym := g.table.final_sym(type0)
60816082
// `return opt_ok(expr)` for functions that expect an option
60826083
expr_type_is_opt := match expr0 {
60836084
ast.CallExpr {
@@ -6114,7 +6115,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
61146115
g.writeln('${ret_typ} ${tmpvar};')
61156116
styp := g.base_type(fn_ret_type)
61166117
g.write('_option_ok(&(${styp}[]) { ')
6117-
if !g.unwrap_generic(fn_ret_type).is_ptr() && type0.is_ptr() {
6118+
if !fn_ret_type.is_ptr() && type0.is_ptr() {
61186119
if !(expr0 is ast.Ident && !g.is_amp) {
61196120
g.write('*')
61206121
}
@@ -7717,6 +7718,22 @@ fn (g &Gen) has_been_referenced(fn_name string) bool {
77177718
return referenced
77187719
}
77197720

7721+
fn (mut g Gen) register_iface_return_types() {
7722+
interfaces := g.table.type_symbols.filter(it.kind == .interface && it.info is ast.Interface)
7723+
for isym in interfaces {
7724+
inter_info := isym.info as ast.Interface
7725+
if inter_info.is_generic {
7726+
continue
7727+
}
7728+
for _, method_name in inter_info.get_methods() {
7729+
method := isym.find_method_with_generic_parent(method_name) or { continue }
7730+
if method.return_type.has_flag(.result) {
7731+
g.register_result(method.return_type)
7732+
}
7733+
}
7734+
}
7735+
}
7736+
77207737
// Generates interface table and interface indexes
77217738
fn (mut g Gen) interface_table() string {
77227739
util.timing_start(@METHOD)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pool
2+
3+
pub struct DB {}
4+
5+
fn (mut d DB) validate() !bool {
6+
return false
7+
}
8+
9+
fn (mut d DB) close() ! {}
10+
11+
fn (mut d DB) reset() ! {}
12+
13+
pub interface DatabaseMysqlPool[T] {
14+
mut:
15+
acquire() !(T, &pool.ConnectionPoolable)
16+
release(conn &pool.ConnectionPoolable) !
17+
}
18+
19+
@[heap]
20+
struct DatabasePoolImpl[T] {
21+
mut:
22+
inner &pool.ConnectionPool
23+
}
24+
25+
pub fn new_mysql_pool[T]() !&DatabaseMysqlPool[T] {
26+
create_conn := fn () !&pool.ConnectionPoolable {
27+
return DB{}
28+
}
29+
pool_conf := pool.ConnectionPoolConfig{}
30+
inner_pool := pool.new_connection_pool(create_conn, pool_conf)!
31+
pool_instance := &DatabasePoolImpl[T]{
32+
inner: inner_pool
33+
}
34+
return pool_instance
35+
}
36+
37+
pub fn (mut p DatabasePoolImpl[T]) acquire() !(T, &pool.ConnectionPoolable) {
38+
conn := p.inner.get()!
39+
return conn as DB, conn
40+
}
41+
42+
pub fn (mut p DatabasePoolImpl[T]) release(conn &pool.ConnectionPoolable) ! {
43+
p.inner.put(conn)!
44+
}
45+
46+
fn test_main() {
47+
new_mysql_pool[DB]() or { assert err.str().contains('failed') }
48+
}

0 commit comments

Comments
 (0)