Skip to content

fix(resolver): seed reachability from unconditionally-kept modules too - #117

Merged
Ch4s3 merged 1 commit into
mainfrom
fix/sibling-test-lib-reachability-pruning
Jul 29, 2026
Merged

Ch4s3 merged 1 commit into
mainfrom
fix/sibling-test-lib-reachability-pruning

Conversation

@Ch4s3

@Ch4s3 Ch4s3 commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • forge test compiles all discovered test files together but picks only ONE as the compile entry (alphabetically first — forge/lib/cmd_test.ml's run_files).
  • Reachability pruning (fix(resolver): resolve modules by declared name; stop silently dropping test modules #106) keeps a non-entry sibling test module's own declarations unconditionally, since DDescribe/DTest count as "global effect". But it never fed that sibling's own textual references back into the reachability BFS — the seed set was only the entry file's source plus explicit-import sources.
  • Net effect: a plain library module referenced only by a non-entry sibling test file (never by the entry file itself) is silently pruned from the merged program. This surfaces as a misleading Unknown module Foo. Did you mean Bar? at typecheck time — not a pruning diagnostic — for a module that plainly exists and is plainly used.
  • This isn't an edge case: any multi-file test suite where the alphabetically-first test file doesn't happen to textually mention every lib module some other test file needs will hit this. Found it while upgrading sigil (well, a fork under development) to current main: test/markdown_test.march sorts before test/sigil_test.march and never mentions Page/Build, which sigil_test.march uses extensively — so those two lib modules vanished from the compiled test binary.

Fix

Seed the reachability queue with the source text of every discovered module that's kept unconditionally via has_global_effect_decl, in addition to the entry file and explicit-import sources.

Verification

Test plan

  • run_compiler full suite green
  • run_eval full suite green
  • New test fails on revert, passes with fix

`forge test` compiles all test files together but picks only one as the
compile entry (alphabetically first). Reachability pruning (#106) keeps a
non-entry sibling test module's own decls unconditionally (DDescribe/DTest
count as global-effect), but never fed that sibling's OWN textual references
into the reachability BFS — only the entry file's source and explicit-import
sources were seeded.

So a plain library module referenced ONLY by a non-entry sibling test file
(never by the entry file itself) was silently pruned from the merged
program, surfacing as a misleading "Unknown module `Foo`. Did you mean
`Bar`?" at typecheck time instead of a pruning diagnostic. This isn't an
edge case: any multi-file test suite where the alphabetically-first test
file doesn't happen to mention every lib module a sibling test file needs
hits it.

Fix: seed the reachability queue with the source text of every discovered
module kept via `has_global_effect_decl`, not just entry_src + loaded_srcs.

Regression test: test_lib_module_used_only_by_sibling_test_is_not_pruned,
verified to fail with only the fix reverted (Expected true, Received false).

run_compiler: 615/615, run_eval: 256/256.
@Ch4s3
Ch4s3 force-pushed the fix/sibling-test-lib-reachability-pruning branch from dcd691c to 963b83e Compare July 29, 2026 17:41
@Ch4s3
Ch4s3 merged commit 69bec8f into main Jul 29, 2026
23 checks passed
@Ch4s3
Ch4s3 deleted the fix/sibling-test-lib-reachability-pruning branch July 29, 2026 18:12
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