Every ObligationCtxt heap-allocated its fulfillment engine as a Box<dyn TraitEngine>, making it the single largest allocation site in the compiler (161k allocations on a syn check build, created per candidate probe in method resolution among others). The solver choice is a per-session constant and both engine types are small, so store them inline in a two-variant enum with static dispatch. The enum's TraitEngine impl needs both FromSolverError bounds, which ripples to the generic impl blocks and two generic users; the concrete error types used everywhere implement both. The boxed engine remains for the per-body typeck root fulfillment context.
added
S-waiting-on-author
labels
Jul 31, 2026rust-bors Bot pushed a commit that referenced this pull request
Aug 2, 2026xmakro marked this pull request as ready for review
August 3, 2026 07:41
rustbot
added
S-waiting-on-review
and removed S-waiting-on-author
Status: This is awaiting some action (such as code changes or more information) from the author.labels
Aug 3, 2026rust-bors Bot pushed a commit that referenced this pull request
Aug 3, 2026Closed
rust-bors
Bot
added
S-waiting-on-bors
and removed S-waiting-on-review
Status: Awaiting review from the assignee but also interested parties.labels
Aug 4, 2026Merged
rust-bors Bot pushed a commit that referenced this pull request
Aug 4, 2026…uwer Rollup of 10 perf-sensitive pull requests Successful merges: - #157281 (perf: skip irrelevant foreign impls when building the specialization graph) - #159403 (Next steps for FnDef binder changes (instantiate most FnDef binders)) - #159763 (Optimize crate resolution for large workspace) - #160033 (Speed up `EverInitializedPlaces`) - #160268 (perf: store the fulfillment engine inline in ObligationCtxt) - #160317 (perf: Cache already-checked types in the privacy visitor) - #160399 (interpret: skip deref-projection validity checks when they are not needed) - #160451 (Deduplicate target and host filesearch) - #160453 (Add fast path to `escape_string_symbol`) - #160454 (Add offload guard flags to typeck to prevent perf regressions)
rust-timer added a commit that referenced this pull request
Aug 4, 2026Rollup merge of #160268 - xmakro:inline-fulfillment-engine, r=nnethercote perf: store the fulfillment engine inline in ObligationCtxt Every `ObligationCtxt` allocated its fulfillment engine on the heap as a `Box<dyn TraitEngine>`. This was the single largest allocation site in the compiler: 161k allocations on a `syn` check build (measured with DHAT). `ObligationCtxt`s are created in hot paths, for example once per candidate probe during method resolution. The allocation is easy to avoid. Which solver is used never changes during a compilation session, and both engine types are small (the obligation forest allocates its own storage separately). So this PR stores the engine directly inside `ObligationCtxt`, in a two-variant enum. Calls now go through a match on that enum instead of virtual dispatch. The enum's `TraitEngine` impl needs both `FromSolverError` bounds, so a few generic impl blocks and two generic users now need both bounds as well. The concrete error types used in practice already implement both, so nothing else changes for callers. The typeck root fulfillment context keeps the boxed engine; it is created once per function body, so the allocation does not matter there.