Skip to content

perf: store the fulfillment engine inline in ObligationCtxt - #160268

Draft
xmakro wants to merge 1 commit into
rust-lang:mainfrom
xmakro:inline-fulfillment-engine
Draft

perf: store the fulfillment engine inline in ObligationCtxt#160268
xmakro wants to merge 1 commit into
rust-lang:mainfrom
xmakro:inline-fulfillment-engine

Conversation

@xmakro

@xmakro xmakro commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

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). ObligationCtxts 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.

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.
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 31, 2026
@panstromek

Copy link
Copy Markdown
Contributor

related: #155714

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants