Zulip Chat Archive

Stream: new members

Topic: maxHeartsbeats increase after updating to v4.27.0


ZhiKai Pong (Feb 07 2026 at 15:46):

mwe:

import Mathlib

/-- The equivalence between `Fin n.succ` and `Fin 1 ⊕ Fin n` extracting the
  `i`th component. -/
def finExtractOne {n : } (i : Fin (n + 1)) : Fin (n + 1)  Fin 1  Fin n :=
  (finCongr (by omega : n.succ = i + 1 + (n - i))).trans <|
  finSumFinEquiv.symm.trans <|
  (Equiv.sumCongr (finSumFinEquiv.symm.trans (Equiv.sumComm (Fin i) (Fin 1)))
    (Equiv.refl (Fin (n-i)))).trans <|
  (Equiv.sumAssoc (Fin 1) (Fin i) (Fin (n - i))).trans <|
  Equiv.sumCongr (Equiv.refl (Fin 1)) (finSumFinEquiv.trans (finCongr (by omega)))

/-- The position `r0` ends up in `r` on adding it via `List.orderedInsert _ r0 r`. -/
def orderedInsertPos {I : Type} (le1 : I  I  Prop) [DecidableRel le1] (r : List I) (r0 : I) :
    Fin (List.orderedInsert le1 r0 r).length :=
  (List.takeWhile (fun b => decide ¬ le1 r0 b) r).length, by
    rw [List.orderedInsert_length]
    have h1 : (List.takeWhile (fun b => decide ¬le1 r0 b) r).length  r.length :=
      List.Sublist.length_le (List.takeWhile_sublist fun b => decide ¬le1 r0 b)
    omega

lemma orderedInsertPos_lt_length {I : Type} (le1 : I  I  Prop) [DecidableRel le1] (r : List I)
    (r0 : I) : orderedInsertPos le1 r r0 < (r0 :: r).length := by
  sorry

def orderedInsertEquiv {I : Type} (le1 : I  I  Prop) [DecidableRel le1] (r : List I) (r0 : I) :
    Fin (r.length + 1)  Fin (List.orderedInsert le1 r0 r).length := by
  let e2 : Fin (List.orderedInsert le1 r0 r).length  Fin (r0 :: r).length :=
    (Fin.castOrderIso (List.orderedInsert_length le1 r r0)).toEquiv
  let e3 : Fin (r0 :: r).length  Fin 1  Fin (r).length := finExtractOne 0
  let e4 : Fin (r0 :: r).length  Fin 1  Fin (r).length :=
    finExtractOne orderedInsertPos le1 r r0, orderedInsertPos_lt_length le1 r r0
  exact e3.trans (e4.symm.trans e2.symm)

lemma orderedInsertEquiv_get {I : Type} (le1 : I  I  Prop) [DecidableRel le1] (r : List I)
    (r0 : I) :
    (r0 :: r).get  (orderedInsertEquiv le1 r r0).symm = (List.orderedInsert le1 r0 r).get := by
  sorry

lemma orderedInsert_eq_insertIdx_orderedInsertPos {I : Type} (le1 : I  I  Prop) [DecidableRel le1]
    (r : List I) (r0 : I) :
    List.orderedInsert le1 r0 r = List.insertIdx r (orderedInsertPos le1 r r0).1 r0 := by
  apply List.ext_get
  · simp only [List.orderedInsert_length]
    rw [List.length_insertIdx]
    have h1 := orderedInsertPos_lt_length le1 r r0
    exact (if_pos (Nat.le_of_succ_le_succ h1)).symm
  intro n h1 h2
  obtain n', hn' := (orderedInsertEquiv le1 r r0).surjective n, h1
  rw [ hn']
  have hn'' : n = ((orderedInsertEquiv le1 r r0) n').val := by rw [hn']
  subst hn''
  rw [ orderedInsertEquiv_get]
  simp only [List.length_cons, Function.comp_apply, Equiv.symm_apply_apply, List.get_eq_getElem]
  match n' with
  | 0, h0 => sorry
  | Nat.succ n', h0 => sorry

on older versions (e.g. v4.24.0 available in the playground) the code compiles fine, but on v4.27.0 onwards (including live) it exceeds the heartbeat limit on the final match block. The code is old and probably can use some cleaning up, but is this an indicator of something breaking in the update?

(cc @Joseph Tooby-Smith this is in PhysLean.Mathematics.List)

Kevin Buzzard (Feb 07 2026 at 17:06):

If you stick

set_option trace.profiler.useHeartbeats true in
set_option trace.profiler true in
set_option maxHeartbeats 800000 in

in front of the last declaration then you can unfold and see what's taking 10 million mheartbeats. It seems to be this:

                                                                [] [9684268.000000] ❌️ Fin.cast 
                                                                      ((finExtractOne
                                                                            ⟨↑(orderedInsertPos le1 r r0), ⋯⟩).symm
                                                                        ((finExtractOne 0)
                                                                          n')) =?= Fin.cast 
                                                                      ((finExtractOne
                                                                            ⟨↑(orderedInsertPos le1 r r0), ⋯⟩).symm
                                                                        ((finExtractOne 0) 0, h0)) 

i.e. typeclass inference taking a lot of time to fail.

ZhiKai Pong (Feb 07 2026 at 18:09):

full proof

here's the full proof for reference.


Last updated: Feb 28 2026 at 14:05 UTC