@@ -265,7 +265,8 @@ fn (mut g FlatGen) gen_node(id flat.NodeId) {
265265 if g.optional_result_matches_base (raw_expr_type, base)
266266 || g.optional_result_matches_base (expr_type, base)
267267 || g.optional_result_matches_base (call_ret_type, base)
268- || g.optional_result_matches_base (decl_ret_type, base) {
268+ || g.optional_result_matches_base (decl_ret_type, base)
269+ || g.clone_call_matches_base (ret_node, base) {
269270 g.write ('return ' )
270271 g.gen_expr (ret_id)
271272 g.writeln (';' )
@@ -565,7 +566,8 @@ fn (mut g FlatGen) return_expr_string(node flat.Node, ret_id flat.NodeId, ret_no
565566 if g.optional_result_matches_base (raw_expr_type, base)
566567 || g.optional_result_matches_base (expr_type, base)
567568 || g.optional_result_matches_base (call_ret_type, base)
568- || g.optional_result_matches_base (decl_ret_type, base) {
569+ || g.optional_result_matches_base (decl_ret_type, base)
570+ || g.clone_call_matches_base (ret_node, base) {
569571 return g.expr_to_string (ret_id)
570572 }
571573 mut expr_value_type := expr_type
@@ -737,8 +739,16 @@ fn (g &FlatGen) selector_call_return_type(fn_node flat.Node) ?types.Type {
737739 }
738740 }
739741 }
740- base_type := g.tc.resolve_type (base_id)
742+ base_type0 := g.usable_expr_type (base_id)
743+ base_type := if base_type0 is types.Unknown || base_type0 is types.Void {
744+ g.tc.resolve_type (base_id)
745+ } else {
746+ base_type0
747+ }
741748 clean_type := types.unwrap_pointer (base_type)
749+ if fn_node.value == 'clone' && (clean_type is types.Array || clean_type is types.Map ) {
750+ return base_type
751+ }
742752 mut receiver_name := clean_type.name ()
743753 if clean_type is types.Struct {
744754 receiver_name = clean_type.name
@@ -848,6 +858,27 @@ fn (g &FlatGen) optional_result_matches_base(expr_type types.Type, base types.Ty
848858 return g.option_c_name_for_base (inner) == g.option_c_name_for_base (base)
849859}
850860
861+ fn (g &FlatGen) clone_call_matches_base (call_node flat.Node, base types.Type) bool {
862+ if call_node.kind != .call || call_node.children_count == 0 {
863+ return false
864+ }
865+ fn_node := g.a.child_node (& call_node, 0 )
866+ if fn_node.kind != .selector || fn_node.value != 'clone' || fn_node.children_count == 0 {
867+ return false
868+ }
869+ base_id := g.a.child (fn_node, 0 )
870+ clean_receiver := types.unwrap_pointer (g.tc.resolve_type (base_id))
871+ clean_base := types.unwrap_pointer (base)
872+ if clean_receiver is types.Array && clean_base is types.Array {
873+ return g.type_names_match (clean_receiver.elem_type, clean_base.elem_type)
874+ }
875+ if clean_receiver is types.Map && clean_base is types.Map {
876+ return g.type_names_match (clean_receiver.key_type, clean_base.key_type)
877+ && g.type_names_match (clean_receiver.value_type, clean_base.value_type)
878+ }
879+ return false
880+ }
881+
851882// option_c_name_for_base returns the C optional type name used for a `?base`/`!base`
852883// value, mirroring optional_type_name without its side effects.
853884fn (g &FlatGen) option_c_name_for_base (base types.Type) string {
@@ -911,6 +942,9 @@ fn (g &FlatGen) expr_is_nil_value(id flat.NodeId) bool {
911942fn (g &FlatGen) usable_expr_type (id flat.NodeId) types.Type {
912943 if int (id) > = 0 && int (id) < g.a.nodes.len {
913944 node := g.a.nodes[int (id)]
945+ if node.kind in [.expr_stmt, .paren] && node.children_count > 0 {
946+ return g.usable_expr_type (g.a.child (& node, 0 ))
947+ }
914948 if node.kind == .ident {
915949 if typ := g.cur_param_types[node.value] {
916950 return typ
@@ -952,6 +986,22 @@ fn (g &FlatGen) usable_expr_type(id flat.NodeId) types.Type {
952986 return types.Type (types.u8_ )
953987 }
954988 }
989+ if node.kind == .call && node.children_count > 0 {
990+ fn_node := g.a.child_node (& node, 0 )
991+ if fn_node.kind == .ident {
992+ if typ := g.tc.cur_scope.lookup (fn_node.value) {
993+ ret := fn_type_return_type (typ)
994+ if ret ! is types.Unknown && ret ! is types.Void {
995+ return ret
996+ }
997+ }
998+ if ret := g.fn_decl_return_type_for_call_name (fn_node.value) {
999+ if ret ! is types.Unknown && ret ! is types.Void {
1000+ return ret
1001+ }
1002+ }
1003+ }
1004+ }
9551005 }
9561006 if typ := g.tc.expr_type (id) {
9571007 if typ ! is types.Unknown && typ ! is types.Void {
@@ -1041,11 +1091,22 @@ fn (g &FlatGen) is_runtime_array_flags_stmt(id flat.NodeId) bool {
10411091 return owner_type is types.Array || owner_type.name () == 'strings.Builder'
10421092}
10431093
1094+ fn (g &FlatGen) multi_return_expr_type (id flat.NodeId) ? types.MultiReturn {
1095+ rtype := g.tc.resolve_type (id)
1096+ if rtype is types.MultiReturn {
1097+ return rtype
1098+ }
1099+ utype := g.usable_expr_type (id)
1100+ if utype is types.MultiReturn {
1101+ return utype
1102+ }
1103+ return none
1104+ }
1105+
10441106// gen_decl_assign emits decl assign output for c.
10451107fn (mut g FlatGen) gen_decl_assign (node flat.Node) {
10461108 if node.children_count > = 3 {
1047- rhs_type := g.tc.resolve_type (g.a.child (& node, 1 ))
1048- if rhs_type is types.MultiReturn {
1109+ if _ := g.multi_return_expr_type (g.a.child (& node, 1 )) {
10491110 g.gen_multi_return_decl (node)
10501111 return
10511112 }
@@ -1325,17 +1386,15 @@ fn (mut g FlatGen) gen_fixed_array_copy_from_node(dst string, rhs_id flat.NodeId
13251386
13261387fn (mut g FlatGen) gen_multi_return_decl (node flat.Node) {
13271388 rhs_id := g.a.child (& node, 1 )
1328- rhs_type := g.tc.resolve_type (rhs_id)
1389+ rhs_multi := g.multi_return_expr_type (rhs_id) or { return }
1390+ rhs_type := types.Type (rhs_multi)
13291391 ct := g.tc.c_type (rhs_type)
13301392 tmp := g.tmp_name ()
13311393 g.write ('${ct } ${tmp } = ' )
13321394 g.gen_expr_with_expected_type (rhs_id, rhs_type)
13331395 g.writeln (';' )
13341396 num_lhs := node.children_count - 1
1335- mut multi_types := []types.Type{}
1336- if rhs_type is types.MultiReturn {
1337- multi_types = rhs_type.types.clone ()
1338- }
1397+ multi_types := rhs_multi.types.clone ()
13391398 for j in 0 .. num_lhs {
13401399 lhs_idx := if j == 0 { 0 } else { j + 1 }
13411400 lhs_id := g.a.child (& node, lhs_idx)
@@ -1376,8 +1435,7 @@ fn (mut g FlatGen) gen_multi_return_decl(node flat.Node) {
13761435fn (mut g FlatGen) gen_assign (node flat.Node) {
13771436 if node.children_count > = 3 {
13781437 rhs_id := g.a.child (& node, 1 )
1379- rhs_type := g.tc.resolve_type (rhs_id)
1380- if rhs_type is types.MultiReturn {
1438+ if _ := g.multi_return_expr_type (rhs_id) {
13811439 g.gen_multi_return_assign (node)
13821440 return
13831441 }
@@ -1427,6 +1485,11 @@ fn (mut g FlatGen) gen_assign(node flat.Node) {
14271485 g.gen_expr (g.a.child (& node, i + 1 ))
14281486 g.writeln (';' )
14291487 }
1488+ } else {
1489+ g.gen_expr (g.a.child (& node, i))
1490+ g.write (' <<= ' )
1491+ g.gen_expr (g.a.child (& node, i + 1 ))
1492+ g.writeln (';' )
14301493 }
14311494 } else {
14321495 rhs_id := g.a.child (& node, i + 1 )
@@ -1601,17 +1664,15 @@ fn (g &FlatGen) assign_lhs_needs_deref(lhs_id flat.NodeId, lhs_type types.Type,
16011664// gen_multi_return_assign emits multi return assign output for c.
16021665fn (mut g FlatGen) gen_multi_return_assign (node flat.Node) {
16031666 rhs_id := g.a.child (& node, 1 )
1604- rhs_type := g.tc.resolve_type (rhs_id)
1667+ rhs_multi := g.multi_return_expr_type (rhs_id) or { return }
1668+ rhs_type := types.Type (rhs_multi)
16051669 ct := g.tc.c_type (rhs_type)
16061670 tmp := g.tmp_name ()
16071671 g.write ('${ct } ${tmp } = ' )
16081672 g.gen_expr_with_expected_type (rhs_id, rhs_type)
16091673 g.writeln (';' )
16101674 num_lhs := node.children_count - 1
1611- mut multi_types := []types.Type{}
1612- if rhs_type is types.MultiReturn {
1613- multi_types = rhs_type.types.clone ()
1614- }
1675+ multi_types := rhs_multi.types.clone ()
16151676 for j in 0 .. num_lhs {
16161677 lhs_idx := if j == 0 { 0 } else { j + 1 }
16171678 lhs_id := g.a.child (& node, lhs_idx)
0 commit comments