Skip to content

test: cross-library .cmi baseline for dotted -open path#15056

Merged
robinbb merged 2 commits into
ocaml:mainfrom
robinbb:robinbb-14492-test-open-flag-module-path
Jun 9, 2026
Merged

test: cross-library .cmi baseline for dotted -open path#15056
robinbb merged 2 commits into
ocaml:mainfrom
robinbb:robinbb-14492-test-open-flag-module-path

Conversation

@robinbb

@robinbb robinbb commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

A fifth sibling to the cross-library .cmi regression baselines from #14584, covering an intermediate library compiled with (flags (-open Prelude.Color)) — a dotted module path naming a submodule of a wrapped dependency, rather than a bare top-level module.

The fixture asserts build success under --sandbox=copy. It builds on main today (no per-module narrowing) and pins behaviour that the per-module narrowing work in #14492 must preserve: the effective--open detection has to key on the head component of the path (Prelude from Prelude.Color), since only top-level module names map to libraries. Without that, the dotted open is dropped from the cross-library frontier and the sandboxed build regresses.

Test-only; no changelog.

@robinbb robinbb self-assigned this Jun 8, 2026
A fifth sibling to the cross-library `.cmi` regression baselines (ocaml#14584), covering `(flags (-open Prelude.Color))` where the intermediate library opens a *dotted* module path naming a submodule of a wrapped dependency, rather than a bare top-level module.

As in `cross-lib-open-flag-barrier.t`, the intermediate's source never names `Prelude` (the open hides it) and the consumer never names it either, so `ocamldep` sees no syntactic chain to `prelude`. The fixture asserts build success under `--sandbox=copy`, pinning that the consumer's compile tracks `prelude`'s `.cmi`s.

The forthcoming per-module narrowing work (ocaml#14492) must key its effective-`-open` detection on the head component of the path (`Prelude` from `Prelude.Color`), since only top-level module names map to libraries; without that, the dotted open would be dropped from the cross-library frontier and the sandboxed build would regress.

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
@robinbb robinbb force-pushed the robinbb-14492-test-open-flag-module-path branch from c499fab to c419eaf Compare June 8, 2026 01:49
@robinbb robinbb requested a review from Copilot June 8, 2026 18:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new blackbox regression fixture to the per-module-lib-deps test suite to pin cross-library .cmi dependency behavior when an intermediate library is compiled with a dotted -open module path (Prelude.Color). This specifically safeguards the per-module dependency narrowing work by ensuring Dune attributes -open Prelude.Color to the dependency library keyed by the head component (Prelude).

Changes:

  • Add a new cross-library .cmi baseline fixture covering (flags (:standard -open Prelude.Color)) in an intermediate library.
  • Assert the build succeeds under --sandbox=copy for a consumer whose compilation implicitly requires the dependency library’s .cmis via the -open effect.

@robinbb robinbb marked this pull request as ready for review June 8, 2026 18:18
@robinbb robinbb requested a review from Alizter June 8, 2026 18:19
@Alizter

Alizter commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Here is another complication that OCaml gives us:

-open Prelude -open Color

Is also the same as:

-open Prelude.Color

but this means that args to -open cannot be assumed to be compilation units. IIUC this is being done in L5.

@robinbb

robinbb commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

You're right that -open arguments are longidents resolved against the accumulating open scope, not compilation units — -open Prelude -open Color makes Color mean Prelude.Color, so the second argument names a submodule. (They aren't quite the same as -open Prelude.Color, since the sequential form also opens Prelude's top level, but that doesn't change the point.)

The detection doesn't rely on the arguments being compilation units, though — it's a conservative over-approximation of which libraries an -open can make referenceable, not a precise resolver, and it stays sound under your example. The root of any -open chain is a compilation unit (or a default-scope module like Stdlib), and that root's head maps to its library, so the library gets reached; a submodule argument's contents live in that same library (or are a re-export, which the wrapped/re-export recoveries already cover). A bare argument that isn't a unit (Color) is added to the BFS frontier and then either maps to no library (a no-op) or collides with an unrelated same-named library (over-conservative — it keeps an extra .cmi, it never drops a needed one). Neither case under-tracks.

For your exact example: -open Prelude reaches lib prelude, which covers Color's contents, so it's sound — I confirmed -open Prelude -open Color builds under --sandbox=copy. This is also independent of the dotted-path handling, which only rewrites dotted arguments (Foo.Bar → head Foo); a bare -open Color is added as Color either way.

(Small pointer: extract_open_module_names is actually introduced and first used in #14516 — seeding the initial BFS frontier — rather than in L5; L5 only adds the dep-lib stanza -open call site.)

@Alizter Alizter left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

A sibling to the cross-library `.cmi` regression baselines (ocaml#14584), covering two chained opens `(flags (-open Prelude -open Color))` where the second argument resolves through the first: `Color` is the `Color` submodule of the wrapped dependency `prelude`, brought into scope by `-open Prelude`, not a top-level module.

As in `cross-lib-open-flag-barrier.t`, the intermediate's source names neither `Prelude` nor `Color`, so `ocamldep` sees no syntactic chain to `prelude`. The fixture asserts build success under `--sandbox=copy`, pinning that the consumer's compile tracks `prelude`'s `.cmi`s.

Per-module narrowing (ocaml#14492) must stay sound when an `-open` argument is not a compilation unit: here `-open Prelude` already reaches `prelude`, covering `Color`'s contents.

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
@robinbb

robinbb commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

@Alizter I'll add some testing for that, here, too.

@robinbb robinbb merged commit 19568fd into ocaml:main Jun 9, 2026
57 of 58 checks passed
@robinbb robinbb deleted the robinbb-14492-test-open-flag-module-path branch June 9, 2026 04:56
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.

3 participants