@@ -69,9 +69,11 @@ fn sanitize_staged_c_source(c_source string) string {
6969 // Pointer dereference for pass-by-pointer array params:
7070 source = source.replace ('(_idx_s < ((a)).len)' , '(_idx_s < (*(a)).len)' )
7171 source = source.replace ('&((string*)((a)).data)' , '&((string*)(*(a)).data)' )
72- // Result struct declarations that the backend may omit:
73- source = ensure_result_struct_decl (source, '_result_int' , 'int' )
74- source = ensure_result_struct_decl (source, '_result_rune' , 'rune' )
72+ // Result struct declarations that the backend may omit
73+ // (e.g. due to ARM64 chained-access map bugs in self-hosted binaries):
74+ source = ensure_result_type (source, '_result_string' , 'string' )
75+ source = ensure_result_type (source, '_result_int' , 'int' )
76+ source = ensure_result_type (source, '_result_rune' , 'rune' )
7577 // Builtin function body replacements (V source doesn't lower correctly yet):
7678 source = replace_generated_c_fn (source, 'string u64_to_hex(u64 nn, u8 len)' , sanitized_u64_to_hex_fn ())
7779 source = replace_generated_c_fn (source, 'string u64_to_hex_no_leading_zeros(u64 nn, u8 len)' ,
@@ -114,14 +116,26 @@ fn sanitize_staged_c_source(c_source string) string {
114116 return source
115117}
116118
117- fn ensure_result_struct_decl (source string , struct_name string , elem_c_type string ) string {
118- if source.contains ('struct ${struct_name } {' ) {
119+ // ensure_result_type ensures that a _result_* type has both typedef and struct definition
120+ // in the generated C source. This is a safety net for when the cleanc backend's alias
121+ // registration fails (e.g. due to ARM64 chained-access map bugs in self-hosted binaries).
122+ fn ensure_result_type (source string , type_name string , val_type string ) string {
123+ if source.contains ('struct ${type_name } {' ) {
119124 return source
120125 }
121- anchor := 'struct _result_string { bool is_error; IError err; u8 data[sizeof(string) > 1 ? sizeof(string) : 1]; };'
122- replacement := anchor +
123- '\n struct ${struct_name } { bool is_error; IError err; u8 data[sizeof(${elem_c_type }) > 1 ? sizeof(${elem_c_type }) : 1]; };'
124- return source.replace (anchor, replacement)
126+ // Find insertion point: after the _result base struct, or after typedef section
127+ decl := 'typedef struct ${type_name } ${type_name };\n ' +
128+ 'struct ${type_name } { bool is_error; IError err; u8 data[sizeof(${val_type }) > 1 ? sizeof(${val_type }) : 1]; };\n '
129+ // Try to insert after the base _result struct definition
130+ anchor := 'struct _result { bool is_error; IError err; };\n '
131+ if source.contains (anchor) {
132+ return source.replace (anchor, anchor + decl)
133+ }
134+ // Fallback: insert before the first function forward declaration
135+ fwd_marker := source.index ('\n void __v_live_init' ) or {
136+ source.index ('\n int main(' ) or { return source }
137+ }
138+ return source[..fwd_marker] + '\n ' + decl + source[fwd_marker..]
125139}
126140
127141fn ensure_string_eq_impl (source string ) string {
0 commit comments