@@ -73,7 +73,11 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
7373 }
7474 g.write_indent ()
7575 g.sb.write_string ('${typ} ${name} = ' )
76- g.expr (rhs_expr)
76+ if typ == 'string' && is_none_like_expr (rhs_expr) {
77+ g.sb.write_string ('((string){.str = "", .len = 0, .is_lit = 1})' )
78+ } else {
79+ g.expr (rhs_expr)
80+ }
7781 g.sb.writeln (';' )
7882 g.remember_runtime_local_type (name, typ)
7983 }
@@ -314,6 +318,8 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
314318 // Rename V variables that clash with C type names
315319 if name == 'array' {
316320 name = '_v_array'
321+ } else {
322+ name = escape_c_keyword (name)
317323 }
318324 // Keep fixed-size arrays as C arrays in local declarations.
319325 if rhs is ast.ArrayInitExpr {
@@ -364,6 +370,14 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
364370 }
365371 }
366372 mut typ := g.get_expr_type (rhs)
373+ mut type_from_selector_field := false
374+ if rhs is ast.SelectorExpr {
375+ field_type := g.selector_field_type (rhs)
376+ if field_type != '' {
377+ typ = field_type
378+ type_from_selector_field = true
379+ }
380+ }
367381 // For Ident RHS referencing a struct-typed constant (e.g., `col := no_color`
368382 // where no_color is `#define`d as a Color struct literal), use the const type.
369383 if (typ == 'int' || typ == '' ) && rhs is ast.Ident {
@@ -383,13 +397,27 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
383397 typ = cast_type
384398 }
385399 }
400+ if rhs is ast.PrefixExpr && rhs.op == .mul && rhs.expr is ast.CastExpr {
401+ cast_type := g.expr_type_to_c (rhs.expr.typ)
402+ if cast_type.ends_with ('*' ) {
403+ typ = cast_type.trim_right ('*' )
404+ }
405+ }
406+ rhs_is_concrete_literal := rhs is ast.BasicLiteral || rhs is ast.StringLiteral
386407 // For temp variables registered by the transformer with a specific type,
387408 // prefer the scope-registered type over the RHS expression type.
388409 if name.starts_with ('_or_t' ) || name.starts_with ('_tmp_' ) || name.starts_with ('_defer_t' ) {
389410 if raw_type := g.get_raw_type (lhs) {
390411 scope_type := g.types_type_to_c (raw_type)
391412 if scope_type != '' && scope_type != 'int' {
392- typ = scope_type
413+ generic_container_fallback :=
414+ (typ == 'array' && scope_type.starts_with ('Array_' ))
415+ || (typ == 'map' && scope_type.starts_with ('Map_' ))
416+ if ! rhs_is_concrete_literal && ! type_from_selector_field && (typ == ''
417+ || typ == 'int' || typ == 'int_literal' || typ == 'void*'
418+ || typ == 'voidptr' || generic_container_fallback) {
419+ typ = scope_type
420+ }
393421 // Ensure result/option wrapper types are registered so their
394422 // typedef and struct definitions get emitted in the C output.
395423 if scope_type.starts_with ('_result_' ) || scope_type.starts_with ('_option_' ) {
@@ -456,6 +484,14 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
456484 typ = target_type + '*'
457485 }
458486 }
487+ mut type_from_typed_deref := false
488+ if rhs is ast.PrefixExpr && rhs.op == .mul && rhs.expr is ast.CastExpr {
489+ target_type := g.expr_type_to_c (rhs.expr.typ)
490+ if target_type.ends_with ('*' ) {
491+ typ = target_type[..target_type.len - 1 ]
492+ type_from_typed_deref = true
493+ }
494+ }
459495 mut elem_type_from_array := false
460496 if rhs is ast.CallExpr {
461497 if rhs.lhs is ast.Ident
@@ -541,7 +577,8 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
541577 type_from_tuple_field = sel_lhs.name.starts_with ('_tuple_t' )
542578 }
543579 }
544- if ! elem_type_from_array && ! type_from_tuple_field && name != ''
580+ if ! elem_type_from_array && ! type_from_selector_field && ! type_from_tuple_field
581+ && ! rhs_is_concrete_literal && ! type_from_typed_deref && name != ''
545582 && g.cur_fn_scope != unsafe { nil } {
546583 if obj := g.cur_fn_scope.lookup_parent (name, 0 ) {
547584 if obj ! is types.Module {
@@ -584,6 +621,12 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
584621 }
585622 }
586623 }
624+ if typ == '' || typ == 'int' || typ == 'int_literal' {
625+ fn_ptr_ret := g.fn_pointer_return_type (rhs.lhs)
626+ if fn_ptr_ret != '' && fn_ptr_ret != 'int' && fn_ptr_ret != 'void' {
627+ typ = fn_ptr_ret
628+ }
629+ }
587630 // For interface vtable method calls (e.g., w->size(w->_object)),
588631 // look up the method's return type from the interface declaration.
589632 if (typ == '' || typ == 'int' ) && rhs.lhs is ast.SelectorExpr {
@@ -623,7 +666,17 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
623666 is_or_tmp := rhs.lhs is ast.Ident && rhs.lhs.name.starts_with ('_or_t' )
624667 if container_type.starts_with ('_result_' ) || container_type.starts_with ('_option_' )
625668 || is_or_tmp {
626- cast_type := if typ != '' && typ != 'int_literal' && typ != 'float_literal' {
669+ payload_type := if container_type.starts_with ('_result_' ) {
670+ g.result_value_type (container_type)
671+ } else if container_type.starts_with ('_option_' ) {
672+ option_value_type (container_type)
673+ } else {
674+ ''
675+ }
676+ cast_type := if payload_type != '' {
677+ payload_type
678+ } else if typ != '' && typ != 'int_literal' && typ != 'float_literal'
679+ && ! typ.starts_with ('_result_' ) && ! typ.starts_with ('_option_' ) {
627680 typ
628681 } else if rhs_type != '' && rhs_type != 'int_literal' && rhs_type != 'float_literal' {
629682 rhs_type
@@ -832,6 +885,11 @@ fn (mut g Gen) gen_assign_stmt(node ast.AssignStmt) {
832885 if typ == '' || typ == 'void' {
833886 typ = 'int'
834887 }
888+ g.register_alias_type (typ)
889+ if typ.starts_with ('Array_' ) && ! typ.starts_with ('Array_fixed_' ) && ! typ.ends_with ('*' ) {
890+ g.sb.writeln ('typedef array ${typ} ;' )
891+ g.write_indent ()
892+ }
835893 // Check if declaring an interface pointer initialized with a concrete type
836894 if typ.ends_with ('*' ) && name != '' {
837895 decl_base := typ.trim_right ('*' )
0 commit comments