@@ -5189,10 +5189,19 @@ fn (mut tc TypeChecker) register_fn_signature(name string, ret_type Type, params
51895189
51905190// register_fn_name_alias updates register fn name alias state for types.
51915191fn (mut tc TypeChecker) register_fn_name_alias(name string, ret_type Type, params []Type, shared_params []bool, is_variadic bool, implicit_veb_ctx bool) {
5192- if owner_module := tc.fn_type_modules[name] {
5193- if owner_module != tc.cur_module && tc.cur_module !in ['', 'main', 'builtin']
5194- && !name.starts_with('${tc.cur_module}.') {
5195- return
5192+ // C externs live in one global namespace and modules routinely redeclare
5193+ // them with refined types (builtin: `C.pthread_join(thread voidptr, ...)`,
5194+ // v3.workers: `C.pthread_join(thread C.pthread_t, ...)`). The
5195+ // first-registration guard below must not drop those refinements: cgen's
5196+ // module-blind parameter lookup would then see `voidptr` and take the
5197+ // address of struct-typed handles (gen-2 compilers panicked with
5198+ // `failed to join compiler worker 0`).
5199+ if !name.starts_with('C.') {
5200+ if owner_module := tc.fn_type_modules[name] {
5201+ if owner_module != tc.cur_module && tc.cur_module !in ['', 'main', 'builtin']
5202+ && !name.starts_with('${tc.cur_module}.') {
5203+ return
5204+ }
51965205 }
51975206 }
51985207 tc.fn_ret_types[name] = ret_type
@@ -5204,8 +5213,15 @@ fn (mut tc TypeChecker) register_fn_name_alias(name string, ret_type Type, param
52045213 tc.fn_shared_params.delete(name)
52055214 }
52065215 if tc.cur_file.len > 0 {
5207- tc.fn_type_files[name] = tc.cur_file
5208- tc.fn_type_modules[name] = tc.cur_module
5216+ // A refined C-extern redeclaration updates the signature tables above
5217+ // but must not steal ownership: is_builtin_unsafe_c_call keys the
5218+ // unsafe-block requirement for the C.m*/C.s* memory externs off the
5219+ // builtin owner, so a module redeclaring C.malloc (json does) would
5220+ // otherwise suppress that diagnostic program-wide.
5221+ if !name.starts_with('C.') || name !in tc.fn_type_modules {
5222+ tc.fn_type_files[name] = tc.cur_file
5223+ tc.fn_type_modules[name] = tc.cur_module
5224+ }
52095225 }
52105226 tc.fn_variadic[name] = is_variadic
52115227 if implicit_veb_ctx || tc.fn_implicit_veb_ctx.len > 0 {
0 commit comments