@@ -289,6 +289,7 @@ fn (mut g FlatGen) gen_node(id flat.NodeId) {
289289 && ! g.type_can_wrap_as_sum (expr_value_type, base)
290290 && ! g.types_numeric_compatible (expr_value_type, base)
291291 && ! g.call_constructs_type (ret_id, base)
292+ && ! g.clone_call_matches_base (ret_node, base)
292293 && expr_value_type ! is types.Primitive
293294 && expr_value_type ! is types.Unknown {
294295 g.writeln ('return (${ct }){.ok = false};' )
@@ -586,8 +587,8 @@ fn (mut g FlatGen) return_expr_string(node flat.Node, ret_id flat.NodeId, ret_no
586587 && ! g.expr_is_nil_pointer_payload (ret_id, base)
587588 && ! g.type_can_wrap_as_sum (expr_value_type, base)
588589 && ! g.types_numeric_compatible (expr_value_type, base)
589- && ! g.call_constructs_type (ret_id, base) && expr_value_type ! is types.Primitive
590- && expr_value_type ! is types.Unknown {
590+ && ! g.call_constructs_type (ret_id, base) && ! g. clone_call_matches_base (ret_node, base)
591+ && expr_value_type ! is types.Primitive && expr_value_type ! is types. Unknown {
591592 return '(${ct }){.ok = false}'
592593 }
593594 return '(${ct }){.ok = true, .value = ${g .expr_to_string_with_expected_type (ret_id , base )}}'
@@ -737,8 +738,16 @@ fn (g &FlatGen) selector_call_return_type(fn_node flat.Node) ?types.Type {
737738 }
738739 }
739740 }
740- base_type := g.tc.resolve_type (base_id)
741+ base_type0 := g.usable_expr_type (base_id)
742+ base_type := if base_type0 is types.Unknown || base_type0 is types.Void {
743+ g.tc.resolve_type (base_id)
744+ } else {
745+ base_type0
746+ }
741747 clean_type := types.unwrap_pointer (base_type)
748+ if fn_node.value == 'clone' && (clean_type is types.Array || clean_type is types.Map ) {
749+ return base_type
750+ }
742751 mut receiver_name := clean_type.name ()
743752 if clean_type is types.Struct {
744753 receiver_name = clean_type.name
@@ -848,6 +857,67 @@ fn (g &FlatGen) optional_result_matches_base(expr_type types.Type, base types.Ty
848857 return g.option_c_name_for_base (inner) == g.option_c_name_for_base (base)
849858}
850859
860+ fn (g &FlatGen) clone_call_matches_base (call_node flat.Node, base types.Type) bool {
861+ mut node := call_node
862+ for node.kind in [.expr_stmt, .paren] && node.children_count > 0 {
863+ node = * g.a.child_node (& node, 0 )
864+ }
865+ if node.kind != .call || node.children_count == 0 {
866+ return false
867+ }
868+ fn_node := g.a.child_node (& node, 0 )
869+ if fn_node.kind == .ident {
870+ base_ct := g.tc.c_type (types.unwrap_pointer (base))
871+ return (fn_node.value == 'array__clone' && base_ct == 'Array' )
872+ || (fn_node.value == 'map__clone' && base_ct == 'map' )
873+ }
874+ if fn_node.kind != .selector || fn_node.value != 'clone' || fn_node.children_count == 0 {
875+ return false
876+ }
877+ base_id := g.a.child (fn_node, 0 )
878+ receiver_type0 := g.usable_expr_type (base_id)
879+ receiver_type := if receiver_type0 is types.Unknown || receiver_type0 is types.Void {
880+ g.tc.resolve_type (base_id)
881+ } else {
882+ receiver_type0
883+ }
884+ clean_receiver := types.unwrap_pointer (receiver_type)
885+ clean_base := types.unwrap_pointer (base)
886+ if g.type_names_match (clean_receiver, clean_base) {
887+ return true
888+ }
889+ receiver_ct0 := g.tc.c_type (clean_receiver)
890+ base_ct0 := g.tc.c_type (clean_base)
891+ if receiver_ct0 .len > 0 && base_ct0 .len > 0 && receiver_ct0 == base_ct0 {
892+ return true
893+ }
894+ receiver := if clean_receiver is types.Alias {
895+ clean_receiver.base_type
896+ } else {
897+ clean_receiver
898+ }
899+ expected := if clean_base is types.Alias {
900+ clean_base.base_type
901+ } else {
902+ clean_base
903+ }
904+ if expected is types.Array || expected is types.Map {
905+ receiver_ct := g.tc.c_type (receiver)
906+ expected_ct := g.tc.c_type (expected)
907+ if receiver_ct.len > 0 && receiver_ct == expected_ct {
908+ return true
909+ }
910+ }
911+ if receiver is types.Array && expected is types.Array {
912+ return g.type_names_match (receiver.elem_type, expected.elem_type)
913+ }
914+ if receiver is types.Map && expected is types.Map {
915+ return g.type_names_match (receiver.key_type, expected.key_type)
916+ && g.type_names_match (receiver.value_type, expected.value_type)
917+ }
918+ return false
919+ }
920+
851921// option_c_name_for_base returns the C optional type name used for a `?base`/`!base`
852922// value, mirroring optional_type_name without its side effects.
853923fn (g &FlatGen) option_c_name_for_base (base types.Type) string {
@@ -911,6 +981,9 @@ fn (g &FlatGen) expr_is_nil_value(id flat.NodeId) bool {
911981fn (g &FlatGen) usable_expr_type (id flat.NodeId) types.Type {
912982 if int (id) > = 0 && int (id) < g.a.nodes.len {
913983 node := g.a.nodes[int (id)]
984+ if node.kind in [.expr_stmt, .paren] && node.children_count > 0 {
985+ return g.usable_expr_type (g.a.child (& node, 0 ))
986+ }
914987 if node.kind == .ident {
915988 if typ := g.cur_param_types[node.value] {
916989 return typ
@@ -952,6 +1025,22 @@ fn (g &FlatGen) usable_expr_type(id flat.NodeId) types.Type {
9521025 return types.Type (types.u8_ )
9531026 }
9541027 }
1028+ if node.kind == .call && node.children_count > 0 {
1029+ fn_node := g.a.child_node (& node, 0 )
1030+ if fn_node.kind == .ident {
1031+ if typ := g.tc.cur_scope.lookup (fn_node.value) {
1032+ ret := fn_type_return_type (typ)
1033+ if ret ! is types.Unknown && ret ! is types.Void {
1034+ return ret
1035+ }
1036+ }
1037+ if ret := g.fn_decl_return_type_for_call_name (fn_node.value) {
1038+ if ret ! is types.Unknown && ret ! is types.Void {
1039+ return ret
1040+ }
1041+ }
1042+ }
1043+ }
9551044 }
9561045 if typ := g.tc.expr_type (id) {
9571046 if typ ! is types.Unknown && typ ! is types.Void {
@@ -1041,11 +1130,22 @@ fn (g &FlatGen) is_runtime_array_flags_stmt(id flat.NodeId) bool {
10411130 return owner_type is types.Array || owner_type.name () == 'strings.Builder'
10421131}
10431132
1133+ fn (g &FlatGen) multi_return_expr_type (id flat.NodeId) ? types.MultiReturn {
1134+ rtype := g.tc.resolve_type (id)
1135+ if rtype is types.MultiReturn {
1136+ return rtype
1137+ }
1138+ utype := g.usable_expr_type (id)
1139+ if utype is types.MultiReturn {
1140+ return utype
1141+ }
1142+ return none
1143+ }
1144+
10441145// gen_decl_assign emits decl assign output for c.
10451146fn (mut g FlatGen) gen_decl_assign (node flat.Node) {
10461147 if node.children_count > = 3 {
1047- rhs_type := g.tc.resolve_type (g.a.child (& node, 1 ))
1048- if rhs_type is types.MultiReturn {
1148+ if _ := g.multi_return_expr_type (g.a.child (& node, 1 )) {
10491149 g.gen_multi_return_decl (node)
10501150 return
10511151 }
@@ -1325,17 +1425,15 @@ fn (mut g FlatGen) gen_fixed_array_copy_from_node(dst string, rhs_id flat.NodeId
13251425
13261426fn (mut g FlatGen) gen_multi_return_decl (node flat.Node) {
13271427 rhs_id := g.a.child (& node, 1 )
1328- rhs_type := g.tc.resolve_type (rhs_id)
1428+ rhs_multi := g.multi_return_expr_type (rhs_id) or { return }
1429+ rhs_type := types.Type (rhs_multi)
13291430 ct := g.tc.c_type (rhs_type)
13301431 tmp := g.tmp_name ()
13311432 g.write ('${ct } ${tmp } = ' )
13321433 g.gen_expr_with_expected_type (rhs_id, rhs_type)
13331434 g.writeln (';' )
13341435 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- }
1436+ multi_types := rhs_multi.types.clone ()
13391437 for j in 0 .. num_lhs {
13401438 lhs_idx := if j == 0 { 0 } else { j + 1 }
13411439 lhs_id := g.a.child (& node, lhs_idx)
@@ -1376,8 +1474,7 @@ fn (mut g FlatGen) gen_multi_return_decl(node flat.Node) {
13761474fn (mut g FlatGen) gen_assign (node flat.Node) {
13771475 if node.children_count > = 3 {
13781476 rhs_id := g.a.child (& node, 1 )
1379- rhs_type := g.tc.resolve_type (rhs_id)
1380- if rhs_type is types.MultiReturn {
1477+ if _ := g.multi_return_expr_type (rhs_id) {
13811478 g.gen_multi_return_assign (node)
13821479 return
13831480 }
@@ -1427,6 +1524,11 @@ fn (mut g FlatGen) gen_assign(node flat.Node) {
14271524 g.gen_expr (g.a.child (& node, i + 1 ))
14281525 g.writeln (';' )
14291526 }
1527+ } else {
1528+ g.gen_expr (g.a.child (& node, i))
1529+ g.write (' <<= ' )
1530+ g.gen_expr (g.a.child (& node, i + 1 ))
1531+ g.writeln (';' )
14301532 }
14311533 } else {
14321534 rhs_id := g.a.child (& node, i + 1 )
@@ -1601,17 +1703,15 @@ fn (g &FlatGen) assign_lhs_needs_deref(lhs_id flat.NodeId, lhs_type types.Type,
16011703// gen_multi_return_assign emits multi return assign output for c.
16021704fn (mut g FlatGen) gen_multi_return_assign (node flat.Node) {
16031705 rhs_id := g.a.child (& node, 1 )
1604- rhs_type := g.tc.resolve_type (rhs_id)
1706+ rhs_multi := g.multi_return_expr_type (rhs_id) or { return }
1707+ rhs_type := types.Type (rhs_multi)
16051708 ct := g.tc.c_type (rhs_type)
16061709 tmp := g.tmp_name ()
16071710 g.write ('${ct } ${tmp } = ' )
16081711 g.gen_expr_with_expected_type (rhs_id, rhs_type)
16091712 g.writeln (';' )
16101713 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- }
1714+ multi_types := rhs_multi.types.clone ()
16151715 for j in 0 .. num_lhs {
16161716 lhs_idx := if j == 0 { 0 } else { j + 1 }
16171717 lhs_id := g.a.child (& node, lhs_idx)
0 commit comments