Skip to content

perf: linear cold compiles, and one warm cache for check/run/pack#4098

Open
hellovai wants to merge 4 commits into
canaryfrom
hellovai/compiler-perf-fixes
Open

perf: linear cold compiles, and one warm cache for check/run/pack#4098
hellovai wants to merge 4 commits into
canaryfrom
hellovai/compiler-perf-fixes

Conversation

@hellovai

@hellovai hellovai commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What this does

Six fixes that came out of benchmarking the BAML compiler head-to-head against tsgo (native TypeScript) and go build on generated, semantically-identical corpora from 1.5k to 295k LOC.

Compiler core

  1. Jinja type env memoized (jinja_base_types salsa query per package+namespace) + skipped for files with no prompts/template_strings. It was rebuilt per checked file — O(N²) — and twice per compile via get_bytecode's error gate. This was ~95% of the quadratic CPU.
  2. ProjectDatabase handle clones O(files) → O(1) (Arc-wrapped file maps). The parallel drivers clone a handle per work chunk (~1.55N per compile); the deep map copies were the second quadratic (CPU + peak RSS).
  3. Cache-path check collector parallelizedcheck/run routed through a serial loop while the identical parallel machinery sat next to it (only reachable with the cache disabled).
  4. get_bytecode no longer re-checks the whole project inside emit — the LSP proves errors once and calls get_bytecode_unchecked. To keep that sound, the LSP diagnostics candidate now includes package-level diagnostics (cross-file name conflicts / namespace shadows), which previously never reached the editor at all.

CLI cache surface
5. baml pack now uses the bytecode cache (it never opened one — every pack was fully cold). Whole-program hit / per-file reuse / store, sharing run+check's key space. Packed Program is target-independent; emit determinism keeps reused images byte-identical.
6. baml check now seeds the cache after a clean check (only when it advances the manifest — no-op checks stay emit-free; a failed emit is logged, never a check failure). Check-only workflows finally reach the warm path.

Plus sha2/asm (hardware SHA for the ~230MB of unit hashing per warm run at large sizes; target-gated, wasm unaffected).

End-user impact (measured, Apple Silicon, hyperfine medians)

Cold compiles scale linearly now (was ~quadratic: 5× the code cost 33× the CPU):

project size check before check after run before run after pack before pack after
59k LOC 1.56 s 1.01 s 2.30 s 1.04 s 1.75 s 1.06 s
295k LOC 21–46 s 7.1 s 27–35 s 7.3 s 40.5 s 7.2 s

At 295k LOC: user CPU 125.7 s → 8.9 s (14×), peak RSS 5.3 GB → 3.6 GB.

One warm cache now serves every command (59k LOC project):

baml check   1.0 s    (cold, seeds the cache)
baml check   0.5 s    (warm)
baml run     0.10 s   (whole-program hit)
baml pack    0.13 s   (hit — was a full cold compile, every time)

Re-pack of a 295k LOC project: 40.5 s → 0.61 s (packed binary verified to execute).

For context at 59k LOC: cold check+emit+cache-store now lands at classic tsc --noEmit speed (1.01 vs 1.00 s) and ahead of go build (1.23 s); tsgo remains far ahead (0.13 s) — closing that further is warm-floor work (tracked below), not this PR.

Trade-off made deliberately: cold check at mid-size projects (~15–30k LOC) is ~10% slower than before because it now emits + stores once to warm the cache; every subsequent check/run/pack is then served warm.

Editor fix riding along: cross-file duplicate-name / namespace-shadow errors now appear in editor diagnostics (they were silently dropped by the LSP's per-file sweep).

Not in this PR (known, profiled, next)

  • The warm-path O(project) floor: the throws-gate safety compare re-parses every file, and check loads all unit bytes it doesn't need (~90% of warm no-op cost at 295k LOC). Design for fixing it (TIR-space throws compare + manifest-resident unit metadata) is under adversarial review.
  • LSP single-sweep / changed-file-first publish.
  • baml test's separate emit_test_cases keyspace still doesn't share this cache.

Letting CI run the test suites for verification; diagnostics output was verified byte-identical (cold + warm) against the pre-fix binary on an error-heavy corpus during development.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo

Summary by CodeRabbit

  • Performance

    • Faster repeated project checks and packaging using bytecode caching with incremental, fresh diagnostics reused for later runs.
    • Improved hashing throughput on supported platforms with runtime-detected hardware-accelerated SHA-2, while keeping MSVC builds on the portable path.
    • Faster Jinja template validation via memoized, package-aware type information and early exits for irrelevant files.
  • Bug Fixes

    • More complete cross-file package diagnostics (e.g., namespace conflicts) surfaced during compilation.
    • More consistent error-only diagnostic reporting.
  • Developer Experience

    • More robust handling of empty project directories during project-mode compilation.

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jul 22, 2026 3:38am
promptfiddle Ready Ready Preview, Comment Jul 22, 2026 3:38am
promptfiddle2 Ready Ready Preview, Comment Jul 22, 2026 3:38am

Request Review

@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds cache-aware project checking and packing, incremental and package-level diagnostics, unchecked bytecode generation after validation, memoized Jinja type environments, shared database maps, and target-specific SHA-2 assembly configuration.

Changes

Incremental compilation pipeline

Layer / File(s) Summary
Cache-aware check and pack flows
baml_language/Cargo.toml, baml_language/crates/bex_cache/Cargo.toml, baml_language/crates/baml_cli/src/check_command.rs, baml_language/crates/baml_cli/src/pack_command.rs
Check and project-mode pack reuse bytecode-cache entries, collect incremental diagnostics, compile dirty artifacts, and seed or verify the cache. Standalone --file packing remains a cold compile path; SHA-2 assembly is configured per target.
Diagnostic and bytecode generation plumbing
baml_language/crates/baml_project/src/check.rs, baml_language/crates/baml_project/src/db.rs, baml_language/crates/baml_project/src/lib.rs, baml_language/crates/bex_project/src/project.rs
Diagnostic filtering and package-level diagnostics are exposed, database maps use Arc<HashMap<...>>, and validated compilation uses get_bytecode_unchecked.
Memoized Jinja type checking
baml_language/crates/baml_lsp2_actions/src/check.rs, baml_language/crates/sys_jinja_types/src/evaluate_type/*
Jinja checks use package-aware Salsa memoization, skip files without templates, and add equality derivations to related types.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant ProjectDatabase
  participant Diagnostics
  participant BytecodeCache
  CLI->>ProjectDatabase: build project database
  ProjectDatabase->>Diagnostics: collect incremental diagnostics
  Diagnostics-->>CLI: return merged and fresh diagnostics
  CLI->>BytecodeCache: load reuse plan
  CLI->>ProjectDatabase: compile dirty artifacts
  ProjectDatabase->>BytecodeCache: verify and store artifacts
Loading

Possibly related PRs

  • BoundaryML/baml#3924: Updates the same CLI compilation flows with content-addressed bytecode-cache behavior.

Suggested reviewers: aaronvg, antoniosarosi

Poem

I’m a rabbit with cache in my feet,
Warm bytecode makes builds hop sweet.
Jinja types rest in a memoized burrow,
Fresh diagnostics need not furrow.
SHA-2 gears hum fast and bright—
Check and pack now leap just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main performance work and shared warm-cache changes across check, run, and pack.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hellovai/compiler-perf-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

Binary size checks passed

7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
baml-cli Linux 🔒 25.6 MB 10.9 MB file 25.3 MB +316.2 KB (+1.3%) OK
packed-program Linux 🔒 17.3 MB 7.1 MB file 17.0 MB +218.6 KB (+1.3%) OK
baml-cli macOS 🔒 19.8 MB 9.5 MB file 19.6 MB +264.7 KB (+1.4%) OK
packed-program macOS 🔒 13.5 MB 6.2 MB file 13.2 MB +231.5 KB (+1.8%) OK
baml-cli Windows 🔒 21.4 MB 9.7 MB file 21.1 MB +261.6 KB (+1.2%) OK
packed-program Windows 🔒 14.4 MB 6.3 MB file 14.2 MB +200.7 KB (+1.4%) OK
bridge_wasm WASM 16.3 MB 🔒 4.4 MB gzip 4.4 MB +13.1 KB (+0.3%) OK

🔒 = the size this artifact is GATED on (ceiling + delta). Binaries gate on file size (installed binary); WASM gates on gzip (download size). The other size is shown for information only.


Generated by cargo size-gate · workflow run

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
baml_language/crates/baml_project/src/db.rs (1)

645-660: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider a debug-only guard on get_bytecode_unchecked's precondition.

This is pub (needed cross-crate by bex_project.rs) and can panic in the runtime-conversion boundary if called on an error-bearing project, per its own doc comment. Since the diagnostics query it would re-derive is salsa-memoized, a debug_assert! re-checking the "no user-file errors" invariant would be nearly free when callers already checked (cache hit) and would catch future misuse early.

🛡️ Optional debug-only safety net
     pub fn get_bytecode_unchecked(
         &self,
     ) -> Result<bex_vm_types::Program, baml_compiler2_emit::LoweringError> {
+        #[cfg(debug_assertions)]
+        debug_assert!(
+            !self.get_bytecode().is_err_or(|e| !matches!(e, baml_compiler2_emit::LoweringError::ProjectHasErrors { .. })),
+            "get_bytecode_unchecked called on a project with unresolved user-file errors"
+        );
         let opts = baml_compiler2_emit::CompileOptions {
             emit_test_cases: false,
         };
         baml_compiler2_emit::generate_project_bytecode(self, &opts)
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_project/src/db.rs` around lines 645 - 660, Add a
debug-only assertion at the start of get_bytecode_unchecked that rechecks the
documented no-user-file-errors precondition using the existing memoized
diagnostics query or established validation helper. Keep the release behavior
and bytecode generation flow unchanged, and make the assertion clearly fail when
the method is called on an error-bearing project.
baml_language/crates/baml_cli/src/check_command.rs (1)

37-147: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Extract the shared warm-cache orchestration into one helper.

Both sites re-implement the identical prepare_warm_db → incremental-diagnostics → compile_program_artifacts/verify_and_store sequence, and both comment-blocks explicitly claim parity with each other (and with run_command.rs, not shown here). Any future change to the cache contract (WarmPrep/ReusePlan shape, error handling, sampled verification) has to be hand-applied in every copy, and a missed spot would silently regress that command's warm-cache path without a compiler error to catch it.

  • baml_language/crates/baml_cli/src/check_command.rs#L37-L147: extract the prepare_warm_db + incremental-diagnostics-collection + conditional-seed sequence into a shared helper in bytecode_cache.rs (or a new small module) parameterized by the emit-failure policy (log-and-continue for check vs. bail for pack/run).
  • baml_language/crates/baml_cli/src/pack_command.rs#L266-L352: replace the equivalent inline sequence in load_and_compile_project with a call to that same shared helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_cli/src/check_command.rs` around lines 37 - 147,
Extract the duplicated warm-cache orchestration into a shared helper in
bytecode_cache.rs or a small shared module, covering prepare_warm_db,
incremental diagnostics collection, conditional compile_program_artifacts, and
verify_and_store. Update baml_language/crates/baml_cli/src/check_command.rs
lines 37-147 to use the helper with log-and-continue emit failures, and
baml_language/crates/baml_cli/src/pack_command.rs lines 266-352 to use it with
bail-on-error behavior; preserve each command’s existing diagnostics and cache
verification semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@baml_language/Cargo.toml`:
- Around line 294-297: Update the sha2 dependency declaration in Cargo.toml to
remove the asm feature while retaining the existing version and oid feature.
Remove the adjacent comment’s asm/ARMv8 performance claims so it accurately
describes the remaining configuration.

---

Nitpick comments:
In `@baml_language/crates/baml_cli/src/check_command.rs`:
- Around line 37-147: Extract the duplicated warm-cache orchestration into a
shared helper in bytecode_cache.rs or a small shared module, covering
prepare_warm_db, incremental diagnostics collection, conditional
compile_program_artifacts, and verify_and_store. Update
baml_language/crates/baml_cli/src/check_command.rs lines 37-147 to use the
helper with log-and-continue emit failures, and
baml_language/crates/baml_cli/src/pack_command.rs lines 266-352 to use it with
bail-on-error behavior; preserve each command’s existing diagnostics and cache
verification semantics.

In `@baml_language/crates/baml_project/src/db.rs`:
- Around line 645-660: Add a debug-only assertion at the start of
get_bytecode_unchecked that rechecks the documented no-user-file-errors
precondition using the existing memoized diagnostics query or established
validation helper. Keep the release behavior and bytecode generation flow
unchanged, and make the assertion clearly fail when the method is called on an
error-bearing project.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a8771fb6-b2e2-44b4-ab0f-b0e7693a4292

📥 Commits

Reviewing files that changed from the base of the PR and between 070b3a3 and 78e07bc.

⛔ Files ignored due to path filters (1)
  • baml_language/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • baml_language/Cargo.toml
  • baml_language/crates/baml_cli/src/check_command.rs
  • baml_language/crates/baml_cli/src/pack_command.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_project/src/check.rs
  • baml_language/crates/baml_project/src/db.rs
  • baml_language/crates/baml_project/src/lib.rs
  • baml_language/crates/bex_project/src/project.rs
  • baml_language/crates/sys_jinja_types/src/evaluate_type/mod.rs
  • baml_language/crates/sys_jinja_types/src/evaluate_type/types.rs

Comment thread baml_language/Cargo.toml Outdated
hellovai and others added 4 commits July 21, 2026 20:08
… the cache-path check

Three independent O(N^2) / serialization fixes, found by profiling a
5000-module (295k LOC) corpus where cold check burned 126s of CPU:

- Memoize the package-wide Jinja type environment as a salsa query
  (jinja_base_types, keyed by NamespaceId) instead of rebuilding it
  inside every check_file call, and skip it entirely for files with no
  LLM prompts or template_strings. The env walk was O(package items)
  per file, i.e. O(N^2) per full check - and ran twice per compile
  because get_bytecode's error gate re-checks the project.
  PredefinedTypes and friends gain PartialEq so salsa can backdate:
  edits that leave the env unchanged don't invalidate prompt checks.

- Arc-wrap ProjectDatabase's file_map / file_id_to_path so cloning a
  db handle is O(1) instead of O(files). The parallel check and emit
  drivers mint a handle per work chunk (~1.55N clones per compile),
  which deep-cloned two N-entry PathBuf maps each time: quadratic
  coordinator CPU and the dominant term in peak RSS.

- Run the narrowed (cache-path) diagnostics collector through the same
  rayon fan-out as the honest collector. baml check / run route
  through the narrowed collector, which checked files serially - the
  parallel machinery next to it was only reachable with the cache
  disabled.

- compile_outcome (LSP) now proves the project error-free once and
  calls a new get_bytecode_unchecked instead of letting get_bytecode
  re-run a full project check inside emit. To keep that sound, the
  diagnostics candidate now includes package-level diagnostics
  (cross-file name conflicts / namespace shadows) - which previously
  never reached the editor at all.

Measured on the 295k LOC corpus: cold check 21-46s -> 7.1s wall,
125.7s -> 8.9s user CPU, peak RSS 5.3GB -> 3.6GB; scaling is now
~linear in project size (verified to 8000 modules).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo
Two gaps kept most workflows off the incremental path:

- baml pack never opened a CacheContext: every pack was a fully cold
  compile, even immediately after a successful run of the same
  sources. Pack now follows run's exact flow - whole-program hit when
  nothing changed, per-file unit reuse on a dirty edit, store after a
  fresh compile. Pack compiles with emit_test_cases:false, so it
  shares run/check's cache key space; the packaged Program is
  target-independent (the --target triple only selects host binary
  bytes) and emit determinism guarantees a reused image is
  byte-identical to a fresh compile. Standalone --file mode stays
  cold, same as run.

- baml check reused cache entries but never wrote them, so a
  check-only workflow (editors, CI lint jobs) recompiled everything
  forever. A clean check now runs the same emit-and-store path as
  run/test - gated to checks that actually advance the manifest
  (missing/stale manifest or dirty files), so no-op checks stay
  emit-free. Seeding is best-effort: an emit failure on a
  diagnostics-clean project is logged, never surfaced as a check
  failure.

End-user effect (59k LOC project): check 1.0s (cold, seeds) ->
check 0.5s -> run 0.10s -> pack 0.13s, all from one warmed cache.
Re-pack of a 295k LOC project: 40.5s -> 0.61s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo
The warm bytecode-cache path hashes every cached unit payload on each
run (~230MB of hashing at a 295k LOC project) and was using sha2's
software fallback - the asm feature (SHA-NI / ARMv8 crypto extensions,
runtime-detected, target-gated so wasm builds are unaffected) was
never enabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo
sha2's asm feature does not build under MSVC (sha2-asm ships GAS .S
sources cl.exe cannot assemble), so move the feature from the
workspace dependency to target-gated tables in bex_cache: every
non-MSVC target keeps the hardware backend, MSVC falls back to the
portable implementation.

Also fix a rustdoc -D warnings failure: the doc comment on
collect_package_level_diagnostics linked the private
package_level_diagnostics item.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/baml_project/src/db.rs (1)

163-180: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Share the remaining owned maps too
#[derive(Clone)] still deep-copies compiler2_file_map and removed_file_tombstones, so each parallel_db_handle() clone can still scale with those maps’ size. Move them behind shared/COW storage if clone cost matters.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_project/src/db.rs` around lines 163 - 180, Wrap
compiler2_file_map and removed_file_tombstones in shared copy-on-write storage,
matching the existing Arc and Arc::make_mut pattern used by file_map and
file_id_to_path. Update their mutation sites and accessors accordingly so
parallel_db_handle() clones remain O(1) while preserving independent mutations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@baml_language/crates/baml_project/src/db.rs`:
- Around line 163-180: Wrap compiler2_file_map and removed_file_tombstones in
shared copy-on-write storage, matching the existing Arc and Arc::make_mut
pattern used by file_map and file_id_to_path. Update their mutation sites and
accessors accordingly so parallel_db_handle() clones remain O(1) while
preserving independent mutations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a593b13e-4b3b-4ae2-8ebe-87cce68307f2

📥 Commits

Reviewing files that changed from the base of the PR and between b45539e and 7862b2c.

⛔ Files ignored due to path filters (1)
  • baml_language/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • baml_language/Cargo.toml
  • baml_language/crates/baml_cli/src/check_command.rs
  • baml_language/crates/baml_cli/src/pack_command.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_project/src/check.rs
  • baml_language/crates/baml_project/src/db.rs
  • baml_language/crates/baml_project/src/lib.rs
  • baml_language/crates/bex_cache/Cargo.toml
  • baml_language/crates/bex_project/src/project.rs
  • baml_language/crates/sys_jinja_types/src/evaluate_type/mod.rs
  • baml_language/crates/sys_jinja_types/src/evaluate_type/types.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • baml_language/Cargo.toml
  • baml_language/crates/sys_jinja_types/src/evaluate_type/types.rs
  • baml_language/crates/baml_cli/src/check_command.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_cli/src/pack_command.rs

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