test: observational baseline for the wrapped-closure precision gap (#4572)#14365
Merged
Alizter merged 1 commit intoApr 29, 2026
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new blackbox (cram) test case documenting the current rebuild behavior for a “wrapped sibling lib + transitive unwrapped dep” scenario where an unreached transitive module interface change still forces a consumer rebuild (i.e., captures the current precision gap in inter-library dep tracking).
Changes:
- Add
wrapped-closure-precision.tto record the current rebuild targets when editing an unreached transitive module interface. - Exercise the scenario via an auto-wrapped re-export library (
lib_re_export) and a consumer referencing the wrapper module in source.
Records the precision gap that any per-module dep filter must navigate when a wrapped sibling library's wrapper appears in a consumer's reference set, and the consumer reaches one entry of the wrapper's transitive [Lib.closure] via an alias chain inside one of the wrapper's children. Setup: - [dep_lib] is unwrapped with two entry modules, [reached_module] and [unreached_module]. - [lib_re_export] is wrapped (dune auto-generates the wrapper) with a single child [pprint] that aliases only [reached_module] of [dep_lib]. - [consumer_lib] writes [Lib_re_export.Pprint.Re.x], naming [Lib_re_export] in source. The consumer reaches [reached_module] through [pprint]'s alias chain but never reaches [unreached_module]. Editing [unreached_module]'s interface still rebuilds the consumer on trunk (cctx-wide [-I]/[-H] glob over [dep_lib]'s objdir fires on the [.cmi] content change). The same outcome holds for any per-module filter that conservatively globs the [Lib.closure] of a wrapped sibling in the reference set; only a deeper filter that descends through wrapped libs' children to find the alias chain can drop the dep on [unreached_module]. Companion to the soundness regression guards in [auto-wrapped-child-reexport.t] and [wrapped-reexport-via-open-flag.t]: those assert the consumer DOES rebuild on a reached transitive module's change (soundness preservation); this one asserts the consumer rebuilds on an UNREACHED transitive module's change (precision gap). Signed-off-by: Robin Bate Boerop <me@robinbb.com>
a2df84f to
f52cc6b
Compare
Collaborator
|
The PR description mentions a rebuild count but the test isn't counting. Could you update the PR description since I believe that is stale? |
Alizter
approved these changes
Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a cram test recording which compile-rule
target_filesrebuild when a consumer references a wrapped sibling library
whose
Lib.closureincludes a transitively-reached unwrappedlibrary, and an unread module of that transitive library is
edited.
Setup
dep_libis unwrapped with two entry modules:reached_module(transitively reached via an alias chain) and
unreached_module(which no source in the test reaches).
lib_re_exportis wrapped (dune auto-generates the wrapper) witha single child
pprintthat aliases onlyreached_moduleofdep_lib.consumer_libwritesLib_re_export.Pprint.Re.x, namingLib_re_exportin source.What the test records
Editing
unreached_module.mlirebuilds the consumer on trunktoday: the cctx-wide
-I/-Hglob coversdep_lib's objdir,so any
.cmicontent change indep_libinvalidates theconsumer regardless of whether the change is to a module the
consumer's alias chain actually reaches.
A precision-perfect filter could observe that
pprint's ocamldepoutput names only
reached_moduleand emit a per-module dep onreached_module.cmialone — leaving the consumer untouched onunreached_module.mlichanges.The test asserts the current rebuild list (the consumer's
.cmi/.cmtirule re-runs) so a future filter improvement thatcloses the precision gap will flip the array to
[].Relationship to #14116
#14116's per-module filter does not close this specific gap. Its
conservative wrapped-lib soundness fix globs the entire
Lib.closureof any wrapped sibling that appears in theconsumer's reference set, which covers
dep_libhere — sounreached_modulechanges still invalidate the consumer throughthe glob. The deeper filter that walks ocamldep through wrapped
libs' children to extract exactly which transitive entry modules
are reached is described as follow-on work in
lib_file_deps.ml.This PR is purely observational; no code change. The test
companions the soundness regression guards in
auto-wrapped-child-reexport.tand
wrapped-reexport-via-open-flag.t:those assert the consumer DOES rebuild on a reached transitive
module's change (soundness preservation); this one asserts the
consumer rebuilds on an unreached transitive module's change
(precision gap).
Related: #4572, #14116