Skip to content

perf: skip re-attempting pending TC mvars with unchanged instantiated goals (quadratic resumption, #14448)#14449

Open
grandchildrice wants to merge 1 commit into
leanprover:masterfrom
grandchildrice:t6-upstream
Open

perf: skip re-attempting pending TC mvars with unchanged instantiated goals (quadratic resumption, #14448)#14449
grandchildrice wants to merge 1 commit into
leanprover:masterfrom
grandchildrice:t6-upstream

Conversation

@grandchildrice

@grandchildrice grandchildrice commented Jul 19, 2026

Copy link
Copy Markdown

Fixes the quadratic re-attempt behavior described in #14448.

Elab.synthesizeSyntheticMVars' resumption loop re-attempts every pending .typeClass synthetic metavariable whenever any single one makes progress; chained literal statements resolve one mvar per pass, giving O(k²) underdetermined synthInstance attempts per command (~101 ms/command at 16 chained literals on master, quadratic scaling ×3.3–3.7 per doubling; see the issue for the full series and linear controls).

Change: memoize per pending .typeClass mvar the instantiated goal type at its last failed attempt (Term.State.tcSynthAttempt : MVarIdMap Expr); skip the re-attempt when the instantiated goal is unchanged. synthInstance is deterministic in the instantiated goal for a fixed env/local-instance context, so the skip elides only attempts whose outcome is already known — pending mvars stay pending, and resolution happens exactly when the goal actually changes.

Gated behind Elab.tcSkipUnchanged (default false) so it can be evaluated safely; intended to become default-on if accepted (happy to drop the option or flip the default per maintainer preference).

Evidence (this branch, on top of 25ba8c3):

k (chained literals) per-command, off per-command, on
4 7.38 ms 3.41 ms
16 100.8 ms 21.4 ms (4.7×)
  • oleans byte-identical with the option on vs off; on-vs-on deterministic
  • failing proofs produce identical errors
  • on a 4.34.0-pre fork: Batteries corpus builds clean with the option on (188 oleans, oleans byte-identical on Batteries.Data.List.Lemmas); real numeral-dense Mathlib module (NumberTheory.PythagoreanTriples) −7.4 % wall; isolated-literal modules neutral (win is specific to the chained-literal regime)

…ntheticMVars

The resumption loop re-attempts every pending `.typeClass` synthetic
metavariable whenever any single one makes progress. In statements whose
literals/operators create a chain of interdependent default-instance
mvars (each assignment unlocks the next), k pending instances cost
k+(k-1)+... = O(k^2) synthInstance attempts, each an expensive
underdetermined (mvar-headed) search.

Microbench (200 theorems `7 + ... + 7 = 7 + ... + 7`, k per side,
term-mode rfl), per-command elaboration cost on master (25ba8c3):
1.64 / 3.22 / 8.43 / 27.6 / 101.4 ms for k = 1/2/4/8/16 (x3.3-3.7 per
doubling => quadratic). Controls: the same expressions in defs (known
expected type) and theorems over variables are both linear.

Fix: memoize per pending mvar the instantiated goal type at its last
failed attempt (one MVarIdMap Expr in Term.State); skip the re-attempt
when the instantiated goal is unchanged. synthInstance is deterministic
in the instantiated goal for a fixed env/local-instance context, so the
skip elides only attempts whose outcome is already known. With the fix
the k=16 case drops ~4.7x and oleans are byte-identical.

Gated behind `Elab.tcSkipUnchanged` (default false) for evaluation.
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Jul 19, 2026
@mathlib-lean-pr-testing

Copy link
Copy Markdown

Mathlib CI status (docs):

  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2026-07-19 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-19 10:30:16)

@leanprover-bot

Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026-07-19 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026-07-19 10:30:18)

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

Labels

toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants