cgen: fix fn return array of interface (#10677)
parent
6dde9f76c6
commit
9f8c3cc159
|
@ -78,7 +78,7 @@ mut:
|
||||||
is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
|
is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
|
||||||
is_shared bool // for initialization of hidden mutex in `[rw]shared` literals
|
is_shared bool // for initialization of hidden mutex in `[rw]shared` literals
|
||||||
is_vlines_enabled bool // is it safe to generate #line directives when -g is passed
|
is_vlines_enabled bool // is it safe to generate #line directives when -g is passed
|
||||||
is_cast_in_heap bool // fn return struct_init to interface type (cannot use stack, should use heap)
|
inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls)
|
||||||
arraymap_set_pos int // map or array set value position
|
arraymap_set_pos int // map or array set value position
|
||||||
vlines_path string // set to the proper path for generating #line directives
|
vlines_path string // set to the proper path for generating #line directives
|
||||||
optionals []string // to avoid duplicates TODO perf, use map
|
optionals []string // to avoid duplicates TODO perf, use map
|
||||||
|
@ -1833,11 +1833,21 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
||||||
}
|
}
|
||||||
if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
|
if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
|
||||||
&& !expected_type.has_flag(.optional) {
|
&& !expected_type.has_flag(.optional) {
|
||||||
got_styp := g.cc_type(got_type, true)
|
if expr is ast.StructInit && !got_type.is_ptr() {
|
||||||
exp_styp := g.cc_type(expected_type, true)
|
g.inside_cast_in_heap++
|
||||||
fname := 'I_${got_styp}_to_Interface_$exp_styp'
|
got_styp := g.cc_type(got_type.to_ptr(), true)
|
||||||
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr,
|
exp_styp := g.cc_type(expected_type, true)
|
||||||
got_styp)
|
fname := 'I_${got_styp}_to_Interface_$exp_styp'
|
||||||
|
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, true,
|
||||||
|
got_styp)
|
||||||
|
g.inside_cast_in_heap--
|
||||||
|
} else {
|
||||||
|
got_styp := g.cc_type(got_type, true)
|
||||||
|
exp_styp := g.cc_type(expected_type, true)
|
||||||
|
fname := 'I_${got_styp}_to_Interface_$exp_styp'
|
||||||
|
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr,
|
||||||
|
got_styp)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// cast to sum type
|
// cast to sum type
|
||||||
|
@ -4733,14 +4743,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
g.expr(expr0)
|
g.expr(expr0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rs := g.table.get_type_symbol(g.fn_decl.return_type)
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
if node.exprs[0] is ast.StructInit && rs.kind == .interface_ && !node.types[0].is_ptr() {
|
|
||||||
g.is_cast_in_heap = true
|
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0].to_ptr(), g.fn_decl.return_type)
|
|
||||||
g.is_cast_in_heap = false
|
|
||||||
} else {
|
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if use_tmp_var {
|
if use_tmp_var {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
|
@ -4928,7 +4931,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
mut shared_typ := struct_init.typ.set_flag(.shared_f)
|
mut shared_typ := struct_init.typ.set_flag(.shared_f)
|
||||||
shared_styp = g.typ(shared_typ)
|
shared_styp = g.typ(shared_typ)
|
||||||
g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
|
g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
|
||||||
} else if is_amp || g.is_cast_in_heap {
|
} else if is_amp || g.inside_cast_in_heap > 0 {
|
||||||
g.write('($styp*)memdup(&($styp){')
|
g.write('($styp*)memdup(&($styp){')
|
||||||
} else if struct_init.typ.is_ptr() {
|
} else if struct_init.typ.is_ptr() {
|
||||||
basetyp := g.typ(struct_init.typ.set_nr_muls(0))
|
basetyp := g.typ(struct_init.typ.set_nr_muls(0))
|
||||||
|
@ -5118,7 +5121,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
|
if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
|
||||||
g.write('}, sizeof($shared_styp))')
|
g.write('}, sizeof($shared_styp))')
|
||||||
} else if is_amp || g.is_cast_in_heap {
|
} else if is_amp || g.inside_cast_in_heap > 0 {
|
||||||
g.write(', sizeof($styp))')
|
g.write(', sizeof($styp))')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
interface Node {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NodeEmpty {
|
||||||
|
name string = 'abc'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pusher(lines []string) []Node {
|
||||||
|
mut nodes := []Node{}
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
nodes << NodeEmpty{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_fn_return_array_of_interface() {
|
||||||
|
lines := os.read_lines(@FILE) or { panic(err) }
|
||||||
|
pushed := pusher(lines)
|
||||||
|
println(pushed)
|
||||||
|
assert pushed.len > 0
|
||||||
|
}
|
Loading…
Reference in New Issue