Skip to content

fix(cache): fall through to @import traversal on global-index miss (#20)#27

Merged
ericsssan merged 1 commit into
mainfrom
fix/crossfile-import-fallback-on-index-miss
Jun 11, 2026
Merged

fix(cache): fall through to @import traversal on global-index miss (#20)#27
ericsssan merged 1 commit into
mainfrom
fix/crossfile-import-fallback-on-index-miss

Conversation

@ericsssan

Copy link
Copy Markdown
Owner

Summary

findMethodCrossFile returned null as soon as the global type index had no matching (type, method) — reaching the @import-graph traversal only when the index errored (OOM). But the global index is built from the project walk, which deliberately skips vendor//build//cache dirs. So a type that's reachable through the file's own @import declarations, yet lives in a skipped dir, failed to resolve — even though the import path is right there. A global-index miss is not proof the type is unreachable.

Fix

On an index miss, fall through to the @import traversal instead of returning null. The fast path (index hit) is unchanged. Bounded: findMethodAcrossImports caches the result including the negative, so the traversal runs at most once per (type, method) per file.

Why this matters beyond tests

Verification

  • zig build + full zig build test green.
  • The strict cross-file tests are proven load-bearing: neutering the fall-through (restoring the early return null) makes the strict transitive-takes test fail with CrossFileResolutionFailed.

Refs #20.

findMethodCrossFile returned null as soon as the global type index had
no matching (type, method), reaching the @import-graph traversal only
when the index ERRORED (OOM). But the global index is built from the
project walk, which skips vendor/build/cache dirs — so a type reachable
through the file's own @import declarations, yet living in a skipped
dir, failed to resolve even though the import path is right there. A
global-index miss is not proof the type is unreachable.

Now an index miss falls through to the @import traversal instead of
giving up. Bounded: findMethodAcrossImports caches the result (incl. the
negative), so the traversal runs at most once per (type, method) per
file; the fast path (index hit) is unchanged.

This also removes the long-standing flakiness of the cross-file unit
tests: tmp fixtures under .zig-cache are skipped by the project walk, so
they only resolved when the index happened to error. The cross-file
ownership tests (#20) are tightened from best-effort `if`-guards to
deterministic assertions, verified load-bearing by neutering the
fall-through (the strict transitive test then fails to resolve).

Refs #20
@ericsssan
ericsssan merged commit 5104072 into main Jun 11, 2026
1 check passed
@ericsssan
ericsssan deleted the fix/crossfile-import-fallback-on-index-miss branch June 11, 2026 13:46
ericsssan added a commit that referenced this pull request Jun 11, 2026
Propagate the transitive effect flags (may_grow_collections /
may_invoke_gc / may_run_on_any_thread) across @import edges, and unify
the three near-identical same-file phases into one generic pass.

- The three propagate*One phases (Phase 5/6/7) collapse into
  propagateEffectOne(fn_decl, receiver_type, comptime Effect). Besides
  removing ~90 lines of duplication, it now also follows METHOD calls
  (`recv.method()`) — the old phases handled bare calls only and skipped
  method calls entirely. recv is resolved to its type (param via
  paramContainerName, or the enclosing type for self/this), then the
  callee summary is looked up same-file (summaryByMethod) or cross-file
  (summaryByMethodCrossFile).

- summaryByMethodCrossFile now carries the callee's DIRECT effect flags
  (via inferFromBody — cheap, body-level, no foreign-file propagation),
  and CachedTakes is extended to cache them so a cache hit doesn't drop
  them. So a fn that calls an imported method which grows a collection
  (etc.) now inherits the effect.

Bound: cross-file effects are DIRECT-only — a foreign method that merely
delegates the effect to its own callee isn't followed (effects are
narrow-value; transitive-within-foreign-file is deferred).

Tests: same-file may_grow via self.method() (new method leg), and
cross-file may_grow via an imported g.add() (deterministic since the #27
@import-fallback fix). Both verified load-bearing by neutering the
cross-file effect copy (only the cross-file test then fails).

Refs #20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant