Files
sx/issues/0131-protocol-call-extra-args-silently-dropped.md
agra c21b683b08 docs(issues): mark 17 already-fixed issues RESOLVED with verified banners
Each banner was re-verified against the current binary (repro now behaves
correctly) and cites the actual fix location in current src/** plus the covering
regression example. Closes the stale-but-fixed backlog: 0019, 0042-0056, 0131.
No compiler change.
2026-06-21 09:25:52 +03:00

3.2 KiB

0131 — protocol method call with extra arguments compiles and silently drops them

RESOLVED. Protocol-dispatch lowering matched the call args against the method's parameter list without an arity check, so extra trailing args were silently truncated (and missing args left the thunk reading garbage). Fixed in src/ir/lower/protocol.zig:emitProtocolDispatch (lines 531-538), which now exact-arity-checks and emits '{name}' expects N argument(s), but M were given at the call span. Regression pinned by examples/1634-protocol-call-arity.

Symptom

Calling a protocol method with MORE arguments than the protocol declares is accepted by the compiler; the extra arguments are silently dropped at the call. Observed: Allocator.dealloc_bytes is declared (ptr: *void), yet a.dealloc_bytes(p, 12345) compiles and runs under both sx run and sx build. Expected: a compile diagnostic ("expected 1 argument, got 2"), exactly as for plain function calls.

Found via std.http (PLAN-HTTPZ S7a): three dealloc_bytes(ptr, size) calls — written against an imagined two-arg signature — compiled clean and survived the full example sweep. Corrected in 81fa50c; this issue is about the missing diagnostic.

Reproduction

#import "modules/std.sx";

main :: () -> i32 {
    gpa := GPA.init();
    a : Allocator = xx gpa;
    p := a.alloc_bytes(64);
    a.dealloc_bytes(p, 12345);   // protocol declares (ptr) — must be rejected
    print("compiled and ran\n");
    return 0;
}

Run sx run repro.sx: prints "compiled and ran", exit 0. Expected: a compile error naming the arity mismatch.

Investigation prompt

The sx compiler accepts protocol method calls with extra trailing arguments and silently drops them (repro above — Allocator. dealloc_bytes(ptr) called with (ptr, extra) compiles and runs). Plain function calls DO arity-check, so the gap is specific to the protocol-dispatch call path. Suspected area: the protocol call planning/lowering in src/ir/lower/call.zig (and/or the protocol method resolution in src/ir/protocols.zig) — wherever a protocol method's parameter list is matched against call-site args, the arg-count check that plain calls get is likely skipped, and lowering then truncates args to the method's param count. The fix should emit the same diagnostic plain calls produce (expected N args, got M) for both too many AND verify too few is also caught. Verify with the repro (expect a compile error) plus a negative-test example or a call.test.zig case pinning the diagnostic; then zig build && zig build test && bash tests/run_examples.sh all green (existing examples must not regress — if any example relied on dropped extra args, that example is itself a latent bug to fix in the same session).

Resolution

RESOLVED (merged master d7808f6, 2026-06-12, Agra-directed in-session fix). emitProtocolDispatch arity-checks exactly (extra AND missing args) with the standard "expects N arguments" diagnostic at the call span. Regression pinned by examples/1634-protocol-call-arity; sweep 622/622 + unit tests green — nothing in the tree relied on the leniency. The three std.http call sites that exposed the gap were corrected separately in 81fa50c.