diff --git a/Cargo.lock b/Cargo.lock index b74eb36e..b44c8d3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1558,12 +1558,9 @@ name = "quonlint" version = "0.2.0" dependencies = [ "ariadne", - "backend", "frontend", "glob", "insta", - "melior", - "mlir_bridge", "quon_core", "rayon", "serde", diff --git a/Justfile b/Justfile index a807d8d5..c7d0290d 100644 --- a/Justfile +++ b/Justfile @@ -148,6 +148,10 @@ ci-rust: setup-python cargo clippy --workspace {{WORKSPACE_EXCLUDE}} --all-targets -- -D warnings cargo build --release --workspace {{WORKSPACE_EXCLUDE}} cargo build --examples --workspace {{WORKSPACE_EXCLUDE}} + # MLIR-free module-seam feature combinations (issue #407). Runs after + # the release workspace build so `cargo build --release -p quonc` is a + # cache hit and the dev-profile MLIR-free builds reuse clippy's deps. + just ci-feature-seams export PATH="$PWD/.venv/bin:$PATH" export QUON_REQUIRE_LIT=1 cargo nextest run --workspace {{WORKSPACE_EXCLUDE}} @@ -209,6 +213,24 @@ na-rap-sweep: --csv /tmp/quon_na_rap_sweep/rap_table_i_sweep.csv echo "wrote /tmp/quon_na_rap_sweep/rap_table_i_sweep.csv" +# Feature-combination module-seam checks (issue #407). Verifies the +# MLIR-free seams stay MLIR-free: parser-only, analysis-only, and the +# MLIR-free neutral-atom library build without linking LLVM/MLIR, while the +# full compiler combination (quonc with frontend `full` + quon_na `mlir`) +# still builds. Run inside `ci-rust` so the `--release -p quonc` line reuses +# the release workspace build above as a cache hit. +ci-feature-seams: + #!/usr/bin/env bash + set -euo pipefail + echo "==> frontend parser-only (no MLIR)" + cargo build -p frontend --no-default-features + echo "==> frontend analysis-only (no MLIR)" + cargo build -p frontend --no-default-features --features analyze + echo "==> quon_na MLIR-free (no LLVM/MLIR)" + cargo build -p quon_na --no-default-features + echo "==> quonc full compiler (frontend full + quon_na mlir)" + cargo build --release -p quonc + # quonfmt · quonlint · LSP smoke on CI corpus ci-tooling: _tooling-build #!/usr/bin/env bash diff --git a/docs/agents/validation.md b/docs/agents/validation.md index 8576d727..7c8402c8 100644 --- a/docs/agents/validation.md +++ b/docs/agents/validation.md @@ -14,7 +14,7 @@ Static analysis and refinement-type checks for the Quon workspace. | `just test-fast` | `cargo test --workspace --exclude flux_verify` (lit soft-skips if tools missing; no Aer) | | `just test-ci` | Local CI parity: `ci-rust` + `ci-tooling` + `ci-docs-assert` (not the website build) | | `just ci-rust` | What the `ci.yml` `rust` job runs (sets `QUON_REQUIRE_LIT`); its `cargo test --workspace` step already includes the sample corpus catalog lint (`quonc/tests/samples_catalog.rs`, ADR-0025 / #185) as an ordinary workspace test crate | -| `just ci-samples` | Local-only convenience: re-run just the sample corpus catalog lint (schema, paths, category coverage, README sections, `ci: smoke` typecheck) in isolation. **Not** part of `test-ci` or `ci.yml` — it would double-pay for what `ci-rust` already covers | +| `just ci-feature-seams` | Invoked inside `just ci-rust` (#407): builds frontend parser-only, frontend analysis-only, `quon_na` MLIR-free (no LLVM/MLIR link), and the full-compiler `quonc` combination to keep the MLIR-free module seams intact | | `just ci-tooling` | What the `ci.yml` `tooling` job runs | | `just tooling-full` | Broader local fmt/lint corpus (not CI) | | `just qec-benchmarks-smoke` | #254 local convenience: one-cell ablation + nested Sinter (`--mode smoke`). CI smoke is the unittest in `just ci-rust`. | diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index a9b44db3..8f128036 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -14,8 +14,10 @@ default = ["full"] # is buildable and testable without linking LLVM/MLIR (ADR-0038, issue #206). analyze = ["dep:quon_core", "dep:z3"] # `full`: the whole frontend including the `lower` → `quantum.circ` MLIR adapter, -# which pulls in `mlir_bridge` / `melior`. `quonc` / `quon_lsp` take this by -# default; `quonfmt` uses `default-features = false` (parser only). +# which pulls in `mlir_bridge` / `melior`. Only the compiler binary (`quonc`) +# opts into this; `quonfmt` (parser only), `quonlint`, and `quon_lsp` +# (analysis only) all use `default-features = false` so they never link +# LLVM/MLIR (ADR-0038, issue #407). full = ["analyze", "dep:mlir_bridge", "dep:melior", "dep:anyhow"] [dependencies] diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index bbfb41a6..44442e73 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -23,11 +23,11 @@ pub mod pretty; // specialize) gates on `analyze`, which pulls in only `quon_core` / `z3` — no // `mlir_bridge` / `melior`. `specialized_circuit` (issue #206) is the typed // boundary between `elaborate` and `lower`. `lower` — the `quantum.circ` MLIR -// adapter — is the only module that needs `full` (Melior). Cargo unifies -// features across the workspace, so `quonfmt`'s `default-features = false` -// (parser only) never strips these from `quon_lsp` / `quonc` (`full`), and -// specialization is buildable/testable under `--features analyze` without -// linking LLVM/MLIR. +// adapter — is the only module that needs `full` (Melior). Only `quonc` opts +// into `full`; `quonfmt` (parser only), `quonlint`, and `quon_lsp` (analysis +// only) all use `default-features = false` so a tooling build never links +// LLVM/MLIR, and specialization is buildable/testable under `--features +// analyze` without linking LLVM/MLIR (ADR-0038, issue #407). #[cfg(feature = "analyze")] pub mod analysis; #[cfg(feature = "analyze")] diff --git a/quon_lsp/Cargo.toml b/quon_lsp/Cargo.toml index 721f7919..125923da 100644 --- a/quon_lsp/Cargo.toml +++ b/quon_lsp/Cargo.toml @@ -11,7 +11,7 @@ name = "quon_lsp" path = "src/main.rs" [dependencies] -frontend = { path = "../frontend" } +frontend = { path = "../frontend", default-features = false, features = ["analyze"] } quonfmt = { path = "../quonfmt" } quonlint = { path = "../quonlint" } tower-lsp = { workspace = true } diff --git a/quon_na/Cargo.toml b/quon_na/Cargo.toml index e21b3844..b8c60908 100644 --- a/quon_na/Cargo.toml +++ b/quon_na/Cargo.toml @@ -8,7 +8,7 @@ repository.workspace = true description = "MLIR-free neutral-atom layout, schedule, and reporting types for Quon" [features] -default = ["mlir"] +default = [] # Opt-in Flux refinement-type checking. Off by default so the stable workspace # build never compiles `flux-rs`; enabled by `cargo flux -p quon_na # --no-default-features --features flux` (nightly). diff --git a/quonc/Cargo.toml b/quonc/Cargo.toml index 5f70d62f..530795b3 100644 --- a/quonc/Cargo.toml +++ b/quonc/Cargo.toml @@ -23,11 +23,11 @@ default = [] solver = ["quon_na/solver"] [dependencies] -frontend = { path = "../frontend" } +frontend = { path = "../frontend", default-features = false, features = ["full"] } mlir_bridge = { path = "../mlir_bridge" } backend = { path = "../backend" } quon_core = { path = "../quon_core" } -quon_na = { path = "../quon_na" } +quon_na = { path = "../quon_na", default-features = false, features = ["mlir"] } quon_qec = { path = "../quon_qec" } melior = { workspace = true } clap = { workspace = true } diff --git a/quonlint/Cargo.toml b/quonlint/Cargo.toml index 248b9f64..383f0cb5 100644 --- a/quonlint/Cargo.toml +++ b/quonlint/Cargo.toml @@ -8,14 +8,14 @@ repository.workspace = true [features] default = [] -ir-analysis = ["dep:mlir_bridge", "dep:melior", "dep:backend"] +# quonlint only needs the Melior-free analysis pipeline (parse → desugar → +# typecheck → elaborate). IR/lowering rules are out of scope here; the +# `frontend` `analyze` feature pulls in `quon_core` / `z3` only — no +# `mlir_bridge` / `melior` (ADR-0038, issue #407). [dependencies] -frontend = { path = "../frontend" } +frontend = { path = "../frontend", default-features = false, features = ["analyze"] } quon_core = { path = "../quon_core" } -backend = { path = "../backend", optional = true } -mlir_bridge = { path = "../mlir_bridge", optional = true } -melior = { workspace = true, optional = true } thiserror = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true }