commit 2cfd4ac6686de4cc15869fac4a9c64555fb1ab9d (tree)
parent e6cda567d009f8cdccd1b0b1611231483d91acda
Author: Motiejus <motiejus@jakstys.lt>
Date: Tue, 3 Mar 2026 07:41:10 +0000
sema: reuse callee func_decl for non-inline calls, bump 80→84
Fix non-inline function call to reuse the callee's existing func_decl
IP entry instead of creating a new one with func_inst as owner_nav.
Ported from upstream Sema.zig analyzeCall: func_val references the
resolved callee function, not a newly-created entry.
The callee is looked up by name in the file namespace. If the nav's
resolved_type already points to a func_decl (IP_KEY_FUNC), it's used
directly. Otherwise, the func_type from resolved_type is used to
construct and deduplicate the func_decl key.
Also fixes the coercion dedup fix from the previous commit: switched
semaCoerceIntRef from ipForceIntern to ipIntern now that skip_dedup
handles cross-shard separation.
Tests 80-83 now pass (call_inside_runtime_conditional, multi_func_call,
runtime_conditional_with_early_return, field_access_chain).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/stage0/corpus.zig b/stage0/corpus.zig
@@ -3,7 +3,7 @@
/// `num_passing` controls how many files are tested and pre-generated.
/// Both build.zig and stages_test.zig import this file.
/// To enable more tests: just increment `num_passing`.
-pub const num_passing: usize = 80;
+pub const num_passing: usize = 84;
pub const files = [_][]const u8{
"stage0/sema_tests/empty.zig",
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -6606,21 +6606,54 @@ static AirInstRef zirCall(
}
}
- // Intern a function type with the resolved return type.
- InternPoolKey ft_key;
- memset(&ft_key, 0, sizeof(ft_key));
- ft_key.tag = IP_KEY_FUNC_TYPE;
- ft_key.data.func_type.return_type = ret_ty;
- ft_key.data.func_type.param_count = runtime_args_count;
- InternPoolIndex func_type_ip = ipIntern(sema->ip, ft_key);
-
- // Intern a function value (unique per ZIR func inst).
- InternPoolKey fv_key;
- memset(&fv_key, 0, sizeof(fv_key));
- fv_key.tag = IP_KEY_FUNC;
- fv_key.data.func_decl.owner_nav = func_inst;
- fv_key.data.func_decl.ty = func_type_ip;
- InternPoolIndex func_val_ip = ipIntern(sema->ip, fv_key);
+ // Use the callee's existing func_decl. Ported from upstream
+ // Sema.zig analyzeCall: func_val is the resolved callee, not
+ // a newly-created func entry. Look up the callee's nav by name
+ // in the file namespace, then use its existing func_decl.
+ InternPoolIndex func_val_ip = IP_INDEX_NONE;
+ {
+ uint32_t callee_nav = UINT32_MAX;
+ if (callee_name_idx != 0
+ && sema->zcu->root_file_idx != UINT32_MAX) {
+ const char* cname
+ = (const char*)&sema->code.string_bytes[callee_name_idx];
+ uint32_t rns
+ = sema->zcu->file_namespaces[sema->zcu->root_file_idx];
+ callee_nav = findNavInNamespace(sema, rns, cname);
+ }
+ if (callee_nav != UINT32_MAX) {
+ const Nav* cn = ipGetNav(sema->ip, callee_nav);
+ InternPoolIndex resolved = cn->resolved_type;
+ // If resolved points to a func_decl, use it directly.
+ // If it points to a func_type, construct the func_decl
+ // key and look it up.
+ if (resolved != IP_INDEX_NONE
+ && sema->ip->items[resolved].tag == IP_KEY_FUNC) {
+ func_val_ip = resolved;
+ } else if (resolved != IP_INDEX_NONE) {
+ InternPoolKey fv_key;
+ memset(&fv_key, 0, sizeof(fv_key));
+ fv_key.tag = IP_KEY_FUNC;
+ fv_key.data.func_decl.owner_nav = callee_nav;
+ fv_key.data.func_decl.ty = resolved;
+ func_val_ip = ipIntern(sema->ip, fv_key);
+ }
+ } else {
+ // Fallback: create with func_inst as nav.
+ InternPoolKey ft_key;
+ memset(&ft_key, 0, sizeof(ft_key));
+ ft_key.tag = IP_KEY_FUNC_TYPE;
+ ft_key.data.func_type.return_type = ret_ty;
+ ft_key.data.func_type.param_count = runtime_args_count;
+ InternPoolIndex func_type_ip = ipForceIntern(sema->ip, ft_key);
+ InternPoolKey fv_key;
+ memset(&fv_key, 0, sizeof(fv_key));
+ fv_key.tag = IP_KEY_FUNC;
+ fv_key.data.func_decl.owner_nav = func_inst;
+ fv_key.data.func_decl.ty = func_type_ip;
+ func_val_ip = ipIntern(sema->ip, fv_key);
+ }
+ }
// Emit CALL extra: {args_len, arg_refs[0..args_len]}.
uint32_t call_extra = semaAddExtra(sema, runtime_args_count);