perf: streamline MF2 declaration execution - #26
Merged
Merged
Conversation
Validate `OutSlice` and `OutExpr` offsets against the verified `LITS` string before accepting bytecode. Validating the whole chunk alone does not make arbitrary byte slices valid UTF-8. Keep `Catalog::literal` within the `LITS` chunk and use checked string slicing for public offsets. Reuse the load-time UTF-8 invariant so reads remain constant-time. Cover split code points, empty interior slices, missing chunks, and out-of-chunk reads without executing malformed strings.
Run each fixture once and check expected output and diagnostic multisets independently. Preserve absent versus empty `expErrors`, report nested selector errors, and stop accepting unrelated error aliases. Preserve null parameters and explicitly fail unsupported parameter types and `expParts` expectations. Report initialization failures as failures instead of disguising them as expected spec errors. Find the sibling WG corpus from worktrees and make `wg_scoreboard` exit unsuccessfully when fixtures fail. Add deterministic harness regressions. The pinned WG corpus reports 404/462 passing; remaining failures include unsupported expectations.
Inherit `expParts` and `params` from `defaultTestProperties`, preserving explicitly empty per-case parameters. Reject unsupported structured values even when the parameter name is unused by the message. This prevents default expectations and unused unsupported inputs from silently passing. The WG baseline remains 404/462 passing.
waywardmonkeys
force-pushed
the
fix/mf2-option-recovery
branch
from
September 9, 2026 03:35
68f2aa8 to
4a57702
Compare
waywardmonkeys
force-pushed
the
perf/mf2-execution-storage
branch
from
September 9, 2026 03:35
e834943 to
296ced1
Compare
waywardmonkeys
force-pushed
the
perf/mf2-execution-storage
branch
2 times, most recently
from
September 15, 2026 10:58
99837dd to
28bffdc
Compare
Keep numeric payloads and effective options until output formatting so `:number`, `:integer`, and `:offset` can inherit and override options without parsing formatted text. Preserve exact integers and separate numeric selection from display; use checked arithmetic for offsets. Evaluate declarations once into per-format local slots. Retain failed resolution metadata so selection reports `BadSelector` without repeating the original diagnostic. Let `Host` callbacks report recoverable errors while returning a usable value, and document the API migration. Cover option inheritance, precision, exact and plural selection, dynamic `select` errors, declaration evaluation counts, and local-slot validation. Update conformance assertions to require exact diagnostic multisets. The WG corpus passes 416 of 462 cases, up from 404 with the corrected harness.
Declaration AST spans already contain document offsets. Avoid adding the pattern body offset again when lowering declarations, so manifest errors point at the actual function annotation.
Short-circuit function resolution when a stored operand is a fallback,
without repeating the original error or producing `BadOperand`.
Give each failed local its own fallback name when storing declarations,
so aliases render `{$a}` and `{$b}` independently. Preserve failure state
through `ExprFallback` and `StoreLocal`, then clear it before unrelated
expressions.
When a later selector rejects an exact numeric variant, try matching plural or ordinal variants before falling back to wildcard candidates. Reuse stored numeric values for both dispatch passes so declarations still resolve once. Apply the same dispatch to stored `:offset` results, and default raw offset operands to plural selection while preserving inherited modes. Cover variant ordering, exact precedence, and multi-selector offsets.
Keep inherited number formatting settings in their parsed form, with explicit selection provenance, instead of cloning and reparsing an owned string map. Compute plural operands directly from retained integers and decimals, preserving visible precision and half-expand rounding. Resolve integral floats within the exact integer range without allocating text. Preserve negative zero and the existing representation of larger floating-point inputs.
Validate each source selector before comparing variants. Keep generated exact and plural dispatches free of repeated diagnostics, and compare locals by private slot index instead of cloning their resolved values. Verify both new local-selector instructions before execution. Emit repeated default subtrees once and jump to their shared continuation, closing intervening select scopes. Preserve exact-to-plural retry when a later selector rejects an exact variant. Keep function metadata available for manifest validation and document the catalog migration.
Resolve string declarations once, retaining raw text and direction metadata until output. Later annotations consume the raw string instead of bidi isolation characters. Compare resolved strings without numeric coercion and let custom hosts observe string input resolution. Carry failures as `Value::Fallback` through nested calls and local aliases. Remove instruction-dependent failure flags so nested calls skip failed operands even when option loads intervene. Preserve each alias fallback name and keep independent expression diagnostics separate. Document eager declaration evaluation and the resolved-string migration. The WG corpus remains at 415/462 passing.
Measure repeated numeric locals, string-to-number reannotation, and a multi-selector match that rejects an exact variant before using a plural candidate. Reuse formatter state and resolved handles so setup is outside the measured operation.
Enable `libm` for runtime-only ICU builds while retaining it for compiler-only builds. Keep compiler-only helpers out of runtime builds and satisfy Clippy across the no-std feature matrix.
Use ICU4X `2.3.0`, `icu_locale` `2.3.1`, and `fixed_decimal` `0.7.2`. Refresh the corresponding lockfile graph, including the provider patch and the upstream locale-fallback split. Preserve optional dependencies and compiled-data feature settings. No source adaptations or new formatting features are needed. ICU4X's Rust `1.88` requirement matches the workspace minimum. WG results remain unchanged at 415/462 passing.
Omit fallback-valued options from function calls while retaining whether their keys came from variables. Expose that information through borrowed `FunctionOptions`, so custom hosts and built-ins share the same contract without copying an option map. Load input option variables independently of operands. Report missing variables and omitted options when option resolution runs; discard those diagnostics when operand failure short-circuits the expression. Preserve variable provenance when substituting local literals. Keep dynamic `select` unselectable even when its value is omitted, while allowing the resolved number to format and inherit unaffected options. Document the callback migration and catalog recompilation requirement. The WG corpus remains at 415/462 passing.
Store compact digit counts and box only the large ICU decimal payload. Integral resolved numbers no longer allocate, while `Value` remains 32 bytes. `Value::Number` now contains `ResolvedNumber` directly; callers matching the variant should remove `Box` assumptions.
Keep execution-scoped values in reusable formatter storage and address them by index from the operand stack and local slots. Local loads no longer clone resolved values, and unary host calls borrow their operands. Clear values and scratch vectors after both successful formatting and traps while retaining their capacity for the next execution.
Resolve plural and ordinal categories through `CallSelect` only when keyword matching reaches that pass. Stored numbers retain their exact payload and selection mode without eagerly computing a category during ordinary formatting. Lower numeric local keyword matching through the stored value, and remove the VM category side channel that is no longer needed.
waywardmonkeys
force-pushed
the
perf/mf2-execution-storage
branch
from
September 15, 2026 12:39
28bffdc to
dccece5
Compare
waywardmonkeys
changed the base branch from
fix/mf2-option-recovery
to
main
September 15, 2026 12:46
waywardmonkeys
force-pushed
the
perf/mf2-execution-storage
branch
from
September 16, 2026 02:49
dccece5 to
154050e
Compare
waywardmonkeys
force-pushed
the
perf/mf2-execution-storage
branch
from
September 16, 2026 02:53
154050e to
6926559
Compare
This was referenced Sep 16, 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
Make MF2 declaration execution explicit, stored once, and reusable without replaying host calls or rediscovering source intent at runtime.
local_eval.rsandrewrite.rscompiler paths.The compiler plan owns declaration evaluation order, storage, and format/select use. The VM executes that plan and does not reconstruct compiler intent.
Review fixes
Regression coverage includes:
:stringto numeric declarations through literals, aliases, and annotated inputs;:stringselection;stdfeature combinations.Two independent Astra reviews found no remaining Must or Should issues after the fixes. The final review also exercised 55,991 short malformed inputs without a panic.
Validation
cargo fmt --alltaplo fmttyposcargo test --workspace --all-features— 479 core tests, 219 compiler tests, workspace green, 11 doctestscargo test -p message-format --no-default-features --features compile— 372 tests, 11 doctestscargo clippy --workspace --all-targets --all-features -- -D warningscargo check -p message-format --no-default-features --features compile,icu4xcargo doc --workspace --all-features --no-depsWG scoreboard: 422/462. Of the remaining 40, 21 are unsupported harness expectations/inputs and 19 are runtime or parser-diagnostic mismatches.
The combined replacement is one atomic commit because the new storage opcodes and direct declaration lowering are one behavioral invariant; an attempted backend/frontend split compiled but failed four existing tests at the intermediate revision.
Performance
The original stored-value work materially reduced number formatting and repeated declaration costs. Subsequent declaration-heavy compiler measurements improved approximately 3% at 128 locals and were flat at smaller sizes. Later runtime/raw-match comparisons were invalidated by changing machine load, so this PR makes no additional broad speedup claim beyond the established stored-value benchmarks.