-
Notifications
You must be signed in to change notification settings - Fork 475
test: mixed-pp lib soundness + precision baselines #14586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
robinbb
wants to merge
1
commit into
main
Choose a base branch
from
robinbb-test-mixed-per-module-preprocess
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+164
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
85 changes: 85 additions & 0 deletions
85
test/blackbox-tests/test-cases/per-module-lib-deps/mixed-per-module-preprocess-precision.t
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| Reproduction: today, building only the consumer's `.cmo` of an | ||
| executable that depends on `mylib` (where `mylib` has two modules, | ||
| `a` default-pp and `b` `(staged_pps ...)`) fails on a compile error | ||
| in `mylib/b.ml` — even though the consumer references only `A`. | ||
| The cctx-wide `.cmi` glob over `mylib`'s objdir pulls `b.cmi` into | ||
| the consumer's compile rule, which forces dune to compile `b.ml`, | ||
| and `b.ml` contains an unresolvable identifier. | ||
|
|
||
| Companion to `mixed-per-module-preprocess.t` (the soundness sibling). | ||
|
|
||
| $ make_dune_project 3.24 | ||
|
|
||
| A no-op staged ppx (identical to the soundness reproducer). | ||
|
|
||
| $ mkdir ppx | ||
| $ cat > ppx/dune <<EOF | ||
| > (library | ||
| > (name ppx_noop) | ||
| > (kind ppx_rewriter) | ||
| > (ppx.driver (main Ppx_noop.main))) | ||
| > EOF | ||
| $ cat > ppx/ppx_noop.ml <<EOF | ||
| > let main () = | ||
| > let n = Array.length Sys.argv in | ||
| > if n < 4 || Sys.argv.(1) <> "--as-ppx" then assert false; | ||
| > let input = Sys.argv.(n - 2) in | ||
| > let output = Sys.argv.(n - 1) in | ||
| > Filename.quote_command "cp" [input; output] | ||
| > |> Sys.command | ||
| > |> exit | ||
| > EOF | ||
|
|
||
| `mylib`: `a` uses default preprocessing (Some-entry); `b` uses | ||
| `(staged_pps ...)` (None-entry). `a`'s source is independent of `b`; | ||
| `b.ml` contains an unresolvable identifier so any attempt to compile | ||
| it will fail. | ||
|
|
||
| $ mkdir mylib | ||
| $ cat > mylib/dune <<EOF | ||
| > (library | ||
| > (name mylib) | ||
| > (wrapped false) | ||
| > (preprocess (per_module ((staged_pps ppx_noop) b)))) | ||
| > EOF | ||
| $ cat > mylib/a.ml <<EOF | ||
| > let answer = 42 | ||
| > EOF | ||
| $ cat > mylib/b.ml <<EOF | ||
| > let bar = no_such_thing | ||
| > EOF | ||
|
|
||
| `consumer` references only `A`: | ||
|
|
||
| $ mkdir consumer | ||
| $ cat > consumer/dune <<EOF | ||
| > (executable (name consumer) (libraries mylib)) | ||
| > EOF | ||
| $ cat > consumer/consumer.ml <<EOF | ||
| > let () = print_int A.answer | ||
| > EOF | ||
|
|
||
| The consumer's compile rule tracks the wide glob over `mylib`'s | ||
| byte objdir — which materialises `b.cmi` and so forces dune to | ||
| compile `b.ml`. | ||
|
|
||
| $ dune rules --root . --format=json --deps '%{cmo:consumer/consumer}' > deps.json | ||
| $ jq -r 'include "dune"; .[] | depsGlobs | ||
| > | select(.dir | endswith("mylib/.mylib.objs/byte")) | ||
| > | .dir + " " + .predicate' < deps.json | ||
| _build/default/mylib/.mylib.objs/byte *.cmi | ||
| $ jq -r 'include "dune"; .[] | depsFilePaths | ||
| > | select(endswith("mylib/.mylib.objs/byte/a.cmi"))' < deps.json | ||
| $ jq -r 'include "dune"; .[] | depsFilePaths | ||
| > | select(endswith("mylib/.mylib.objs/byte/b.cmi"))' < deps.json | ||
|
|
||
| Build only the consumer's `.cmo` (compile rule, not link). Today, | ||
| dune attempts to compile `b.ml` to produce `b.cmi` and fails on | ||
| the unresolvable identifier. | ||
|
|
||
| $ dune build '%{cmo:consumer/consumer}' | ||
| File "mylib/b.ml", line 1, characters 10-23: | ||
| 1 | let bar = no_such_thing | ||
| ^^^^^^^^^^^^^ | ||
| Error: Unbound value no_such_thing | ||
| [1] | ||
79 changes: 79 additions & 0 deletions
79
test/blackbox-tests/test-cases/per-module-lib-deps/mixed-per-module-preprocess.t
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| An unwrapped library has two modules with mixed preprocessing: `a` | ||
| uses default preprocessing, `b` uses `(staged_pps ...)`. The | ||
| consumer references `A.identity` whose type is `B.t -> B.t`. Pins | ||
| that the consumer's compile rule correctly tracks `b.cmi` as a sandbox- | ||
| required dep — even though the consumer never names `B` in source. | ||
|
|
||
| $ make_dune_project 3.24 | ||
|
|
||
| A no-op staged ppx, modelled on | ||
| `test/blackbox-tests/test-cases/staged-pps-relative-directory-gh8158.t`. | ||
| The driver copies its input verbatim. | ||
|
|
||
| $ mkdir ppx | ||
| $ cat > ppx/dune <<EOF | ||
| > (library | ||
| > (name ppx_noop) | ||
| > (kind ppx_rewriter) | ||
| > (ppx.driver (main Ppx_noop.main))) | ||
| > EOF | ||
| $ cat > ppx/ppx_noop.ml <<EOF | ||
| > let main () = | ||
| > let n = Array.length Sys.argv in | ||
| > if n < 4 || Sys.argv.(1) <> "--as-ppx" then assert false; | ||
| > let input = Sys.argv.(n - 2) in | ||
| > let output = Sys.argv.(n - 1) in | ||
| > Filename.quote_command "cp" [input; output] | ||
| > |> Sys.command | ||
| > |> exit | ||
| > EOF | ||
|
|
||
| `mylib` is `(wrapped false)` with `a` default-pp and `b` staged-pps. | ||
| `a`'s interface mentions `B.t`, so the consumer's call to | ||
| `A.identity` forces the compiler to load `b.cmi` to resolve the | ||
| type. | ||
|
|
||
| $ mkdir mylib | ||
| $ cat > mylib/dune <<EOF | ||
| > (library | ||
| > (name mylib) | ||
| > (wrapped false) | ||
| > (preprocess (per_module ((staged_pps ppx_noop) b)))) | ||
| > EOF | ||
| $ cat > mylib/a.mli <<EOF | ||
| > val identity : B.t -> B.t | ||
| > EOF | ||
| $ cat > mylib/a.ml <<EOF | ||
| > let identity (x : B.t) = x | ||
| > EOF | ||
| $ cat > mylib/b.ml <<EOF | ||
| > type t = int | ||
| > let zero : t = 0 | ||
| > EOF | ||
|
|
||
| `consumer` references `A.identity` but never names `B`. The | ||
| `--sandbox=copy` build below is the discriminator: if a regression | ||
| dropped `b.cmi` from the consumer's compile-rule deps, the sandbox | ||
| would not stage it and the build would fail with "no such file" | ||
| deterministically rather than passing silently from a stale | ||
| `_build/`. | ||
|
|
||
| $ mkdir consumer | ||
| $ cat > consumer/dune <<EOF | ||
| > (executable (name consumer) (libraries mylib)) | ||
| > EOF | ||
| $ cat > consumer/consumer.ml <<EOF | ||
| > let _ = A.identity 0 | ||
| > EOF | ||
|
|
||
| $ dune build --sandbox=copy consumer/consumer.exe | ||
|
|
||
| The consumer's compile rule for `consumer` tracks `mylib`'s byte | ||
| objdir — both `a.cmi` (referenced) and `b.cmi` (needed for the | ||
| type of `A.identity`). | ||
|
|
||
| $ dune rules --root . --format=json --deps '%{cmo:consumer/consumer}' > deps.json | ||
| $ jq -r 'include "dune"; .[] | depsGlobs | ||
| > | select(.dir | endswith("mylib/.mylib.objs/byte")) | ||
| > | .dir + " " + .predicate' < deps.json | ||
| _build/default/mylib/.mylib.objs/byte *.cmi |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.