Zulip Chat Archive
Stream: mathlib4
Topic: performance debug
Patrick Massot (Apr 20 2023 at 11:40):
I'd like to get help to debug huge performance issues with !4#3383. Each declaration compiles piecewise but some don't compile globally. For instance in
irreducible_def lift {r : R → R → Prop} :
{ f : R →+* T // ∀ ⦃x y⦄, r x y → f x = f y } ≃ (RingQuot r →+* T) :=
{ toFun := fun f' =>
let f := (f' : R →+* T)
{ toFun := fun x =>
Quot.lift f
(by
rintro _ _ r
induction r
case of _ _ r => exact f'.prop r
case add_left _ _ _ _ r' => rw [map_add, map_add, r']
case mul_left _ _ _ _ r' => rw [map_mul, map_mul, r']
case mul_right _ _ _ _ r' => rw [map_mul, map_mul, r'] )
x.toQuot
map_zero' := sorry/- by simp only [← zero_quot, f.map_zero] -/
map_add' := sorry/- by
rintro ⟨⟨x⟩⟩ ⟨⟨y⟩⟩
simp only [add_quot, f.map_add x y] -/
map_one' := sorry/- by simp only [← one_quot, f.map_one] -/
map_mul' := sorry/- by
rintro ⟨⟨x⟩⟩ ⟨⟨y⟩⟩
simp only [mul_quot, f.map_mul x y] -/ }
invFun := fun F =>
⟨F.comp (mkRingHom r), fun x y h => sorry/- by
dsimp
rw [mkRingHom_rel h] -/⟩
left_inv := fun f => sorry/- by
ext
simp [mkRingHom_def] -/
right_inv := fun F => sorry /- by
ext
simp [mkRingHom_def] -/ }
Each sorry replaces a proof that actually works. You can un-comment each one separately and it works. But uncommenting all of them at once will make Lean hang forever. A similar problem higher up in the file actually led to timeout and I got it to compile with set_option maxHeartbeats 800000 in
, but in the above case I don't even get a timeout, it simply runs forever, consuming all CPU power it can find. More generally editing this file doesn't feel like interactive theorem proving at all, more like "type a line and go make some coffee while Lean thinks about it". I'd be happy to see someone fixing that but I'd be even more interesting in learning how to debug such a disaster.
Sebastian Ullrich (Apr 20 2023 at 11:46):
For the case that terminates, it would be interesting to see where time is spent using profiler true
. When it doesn't terminate, the best approximation to that is running everything under gdb
and looking at a few stack traces, which, yes, is a significantly worse user experience
Patrick Massot (Apr 20 2023 at 12:02):
Sorry about disappearing. Lean 4 killed my computer and I had to reboot to regain control.
Patrick Massot (Apr 20 2023 at 12:03):
set_option profiler true
says
type checking took 377ms
type checking took 929ms
type checking took 971ms
type checking took 1.08s
type checking took 2.4s
compilation new took 104ms
compilation of RingQuot.instSemiring took 19.2s
Patrick Massot (Apr 20 2023 at 12:03):
Should I say something more to get more info?
Scott Morrison (Apr 20 2023 at 12:03):
Does forcing it to be noncomputable help?
Patrick Massot (Apr 20 2023 at 12:04):
I just tried after seeing that suspicious looking compilation
thing and it does help!
Patrick Massot (Apr 20 2023 at 12:05):
or maybe not
Patrick Massot (Apr 20 2023 at 12:05):
It stops printing compilation of RingQuot.instSemiring took 19.2s
but it still takes forever.
Matthew Ballard (Apr 20 2023 at 12:06):
Tracing isDefEq
and/or synthInstance
will report timings for each step with profiler
Patrick Massot (Apr 20 2023 at 12:07):
The actual time with noncomputable
is still around 20s.
Sebastian Ullrich (Apr 20 2023 at 12:11):
That sounds weird, it should at least get faster by that amount if the line disappears. If the expensive definition dominates file processing time (up to that point with #exit
after it), you can also run it on the cmdline with lean --profile
to print a grand total.
Patrick Massot (Apr 20 2023 at 12:15):
Tracing isDefEq
and synthInstance
doesn't show anything striking to me.
Patrick Massot (Apr 20 2023 at 12:16):
Sebastian, could you tell what I should run on the command line exactly?
Sebastian Ullrich (Apr 20 2023 at 12:16):
lake env lean --profile <file.lean>
Patrick Massot (Apr 20 2023 at 12:17):
Thanks. Without noncomputable
:
lake env lean --profile Mathlib/Algebra/RingQuot.lean
interpretation of Lean.mkStateFromImportedEntries._at.Mathlib.Prelude.Rename.initFn._@.Mathlib.Mathport.Rename._hyg.251._spec_1 took 102ms
import took 313ms
type checking took 375ms
type checking took 930ms
type checking took 963ms
type checking took 1.07s
type checking took 2.38s
compilation new took 105ms
compilation of RingQuot.instSemiring took 19.2s
elaboration took 11.2s
Mathlib/Algebra/RingQuot.lean:327:0: warning: using 'exit' to interrupt Lean
cumulative profiling times:
attribute application 1.87ms
compilation 19.3s
compilation new 138ms
dsimp 0.456ms
elaboration 11.3s
import 313ms
initialization 39ms
interpretation 805ms
linting 56.2ms
parsing 14.3ms
simp 135ms
tactic execution 110ms
type checking 5.87s
typeclass inference 581ms
Patrick Massot (Apr 20 2023 at 12:18):
with noncomputable
:
lake env lean --profile Mathlib/Algebra/RingQuot.lean
interpretation of Lean.mkStateFromImportedEntries._at.Mathlib.Prelude.Rename.initFn._@.Mathlib.Mathport.Rename._hyg.251._spec_1 took 102ms
import took 467ms
type checking took 375ms
type checking took 923ms
type checking took 960ms
type checking took 1.07s
type checking took 2.39s
elaboration took 10.9s
Mathlib/Algebra/RingQuot.lean:327:0: warning: using 'exit' to interrupt Lean
cumulative profiling times:
attribute application 1.86ms
compilation 46.1ms
compilation new 33.1ms
dsimp 0.456ms
elaboration 11s
import 467ms
initialization 30.8ms
interpretation 798ms
linting 56.3ms
parsing 14.7ms
simp 136ms
tactic execution 112ms
type checking 5.87s
typeclass inference 589ms
Sebastian Ullrich (Apr 20 2023 at 12:19):
That's still not very fast, but does the second version at least feel faster? (You can also prepend time
to the cmdline to make that more precise)
Patrick Massot (Apr 20 2023 at 12:22):
time
says:
real 0m38,883s
user 0m38,023s
sys 0m0,860s
vs
real 0m19,635s
user 0m19,280s
sys 0m0,356s
Patrick Massot (Apr 20 2023 at 12:22):
So the second version is indeed faster.
Patrick Massot (Apr 20 2023 at 12:22):
But both are horrible.
Scott Morrison (Apr 20 2023 at 12:23):
Without noncomputable
:
% time lake env lean --profile Mathlib/Algebra/RingQuot.lean
interpretation of Std.Linter.UnreachableTactic.initFn._@.Std.Linter.UnreachableTactic._hyg.1411 took 108ms
interpretation of Lean.mkStateFromImportedEntries._at.Mathlib.Prelude.Rename.initFn._@.Mathlib.Mathport.Rename._hyg.251._spec_1 took 133ms
import took 650ms
type checking took 580ms
type checking took 1.43s
type checking took 1.46s
type checking took 1.61s
type checking took 3.35s
compilation new took 135ms
compilation of RingQuot.instSemiring took 25.8s
elaboration took 17.1s
Mathlib/Algebra/RingQuot.lean:330:0: warning: using 'exit' to interrupt Lean
cumulative profiling times:
attribute application 2.78ms
compilation 25.8s
compilation new 181ms
dsimp 0.531ms
elaboration 17.3s
import 650ms
initialization 30ms
interpretation 1.58s
linting 71.7ms
parsing 18.1ms
simp 187ms
tactic execution 159ms
type checking 8.66s
typeclass inference 771ms
lake env lean --profile Mathlib/Algebra/RingQuot.lean 54.57s user 1.67s system 99% cpu 56.271 total
with noncomputable
% time lake env lean --profile Mathlib/Algebra/RingQuot.lean
interpretation of Lean.mkStateFromImportedEntries._at.Mathlib.Prelude.Rename.initFn._@.Mathlib.Mathport.Rename._hyg.251._spec_1 took 133ms
import took 665ms
type checking took 584ms
type checking took 1.41s
type checking took 1.47s
type checking took 1.65s
type checking took 3.41s
elaboration took 17.3s
Mathlib/Algebra/RingQuot.lean:330:0: warning: using 'exit' to interrupt Lean
cumulative profiling times:
attribute application 2.82ms
compilation 68.2ms
compilation new 46.7ms
dsimp 0.562ms
elaboration 17.5s
import 665ms
initialization 29.9ms
interpretation 1.56s
linting 71.8ms
parsing 18.6ms
simp 187ms
tactic execution 158ms
type checking 8.75s
typeclass inference 779ms
lake env lean --profile Mathlib/Algebra/RingQuot.lean 29.55s user 1.04s system 99% cpu 30.610 total
Sebastian Ullrich (Apr 20 2023 at 12:24):
The high type checking (kernel) time is curious, we don't see that very often. Could it be that the produced (proof) term is simply humongous?
Matthew Ballard (Apr 20 2023 at 12:24):
Which declarations are chewing up the processor in particular? Just lift
?
Scott Morrison (Apr 20 2023 at 12:25):
The relevant declaration is
instance instSemiring (r : R → R → Prop) : Semiring (RingQuot r) where
add := (· + ·)
mul := (· * ·)
zero := 0
one := 1
natCast := natCast r
natCast_zero := by simp [Nat.cast, natCast_def, ← zero_quot]
natCast_succ := by simp [Nat.cast, natCast_def, ← one_quot, add_quot]
add_assoc := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [add_quot, add_assoc]
zero_add := by
rintro ⟨⟨⟩⟩
simp [add_quot, ← zero_quot, zero_add]
add_zero := by
rintro ⟨⟨⟩⟩
simp only [add_quot, ← zero_quot, add_zero]
zero_mul := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← zero_quot, zero_mul]
mul_zero := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← zero_quot, mul_zero]
add_comm := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [add_quot, add_comm]
mul_assoc := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, mul_assoc]
one_mul := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← one_quot, one_mul]
mul_one := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← one_quot, mul_one]
left_distrib := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, add_quot, left_distrib]
right_distrib := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, add_quot, right_distrib]
npow n x := x ^ n
npow_zero := by
rintro ⟨⟨⟩⟩
simp only [pow_quot, ← one_quot, pow_zero]
npow_succ := by
rintro n ⟨⟨⟩⟩
simp only [pow_quot, mul_quot, pow_succ]
nsmul := (· • ·)
nsmul_zero := by
rintro ⟨⟨⟩⟩
simp only [smul_quot, zero_smul, zero_quot]
nsmul_succ := by
rintro n ⟨⟨⟩⟩
simp only [smul_quot, nsmul_eq_mul, Nat.cast_add, Nat.cast_one, add_mul, one_mul,
add_comm, add_quot]
which conspicuously has many structure fields, each with a tactic proof.
Scott Morrison (Apr 20 2023 at 12:25):
(This is the one Patrick and I are timing. lift
is further down the file (past the #exit) and even slower.)
Matthew Ballard (Apr 20 2023 at 12:25):
Does bisecting the fields help narrow it down?
Scott Morrison (Apr 20 2023 at 12:26):
I remember long ago in lean3 some quadratic effect?
Patrick Massot (Apr 20 2023 at 12:26):
Matthew, lift
doesn't compile at all. Currently we focus on one that does compile if you push MaxHearbeats
enough.
Scott Morrison (Apr 20 2023 at 12:27):
Indeed, sorry
ing the second half of the proofs drops elaboration time to 2s.
Matthew Ballard (Apr 20 2023 at 12:28):
Is it snappy with just the data carrying fields?
Scott Morrison (Apr 20 2023 at 12:28):
Similarly, sorry
ing instead the first half of the proofs drops elaboration time to 0.4s.
Scott Morrison (Apr 20 2023 at 12:29):
So it is a non-local effect of the many proofs...
Matthew Ballard (Apr 20 2023 at 12:29):
Those proofs overlap quite a bit
Scott Morrison (Apr 20 2023 at 12:30):
overlap?
Patrick Massot (Apr 20 2023 at 12:31):
Yes, you can sorry any combination of half the proofs to get something fast.
Matthew Ballard (Apr 20 2023 at 12:32):
The elements of the lists in the calls to simp
overlap.
Matthew Ballard (Apr 20 2023 at 12:33):
Hypothetically if *_quot
is somewhat slow them doing them in succession is very slow
Scott Morrison (Apr 20 2023 at 12:35):
The proof terms generated are getting bigger as you go through the list of fields:
Patrick Massot (Apr 20 2023 at 12:38):
Maybe the proof terms somehow include the proof terms of the previous fields?
Scott Morrison (Apr 20 2023 at 12:39):
Yes.
Matthew Ballard (Apr 20 2023 at 12:39):
Would factoring some stuff out to separate declarations prevent this?
Scott Morrison (Apr 20 2023 at 12:40):
Proof of add_assoc
(_proof_1) is 67kb, proof of zero_add
(_proof_2) is 260kb, but if you comment out add_assoc
then the proof of zero_add
drops to 30kb.
Scott Morrison (Apr 20 2023 at 12:41):
(These are all with pp.all
.)
Scott Morrison (Apr 20 2023 at 12:41):
@Matthew Ballard, presumably, but I think we want to treat this as a Lean bug for now. This is not good behaviour!
Matthew Ballard (Apr 20 2023 at 12:42):
What are the sizes in ML3?
Scott Morrison (Apr 20 2023 at 12:43):
Ah.. simple but terrible explanation. :-)
Scott Morrison (Apr 20 2023 at 12:44):
The HAdd
instance that is being used in the proof of zero_add
is:
(@HAdd.hAdd.{u_1, u_1, u_1} (@RingQuot.{u_1} R inst r) (@RingQuot.{u_1} R inst r) (@RingQuot.{u_1} R inst r)
(@instHAdd.{u_1} (@RingQuot.{u_1} R inst r)
(@AddSemigroup.toAdd.{u_1} (@RingQuot.{u_1} R inst r)
(@AddSemigroup.mk.{u_1} (@RingQuot.{u_1} R inst r)
(@Add.mk.{u_1} (@RingQuot.{u_1} R inst r) fun (x x_1 : @RingQuot.{u_1} R inst r) =>
@HAdd.hAdd.{u_1, u_1, u_1} (@RingQuot.{u_1} R inst r) (@RingQuot.{u_1} R inst r)
(@RingQuot.{u_1} R inst r)
(@instHAdd.{u_1} (@RingQuot.{u_1} R inst r) (@RingQuot.instAddRingQuot.{u_1} R inst r)) x x_1) ...
i.e. it is being deduced from an AddSemigroup
which contains the proof of add_assoc
!
Scott Morrison (Apr 20 2023 at 12:45):
This then snowballs as we get to the later fields, and the instances being used recursively contain copies of the proofs from earlier steps (which contain instances which ...).
Scott Morrison (Apr 20 2023 at 12:45):
This is all with pp.all
on, so the sizes I'm seeing are a bit unfair.
Scott Morrison (Apr 20 2023 at 12:46):
(Subexpression sharing, etc)
Yaël Dillies (Apr 20 2023 at 12:46):
Is that a general drawback of new structures, then?
Scott Morrison (Apr 20 2023 at 12:50):
@Sebastian Ullrich, does this make sense to you?
Patrick Massot (Apr 20 2023 at 12:52):
Thank you very much Scott for investigating this. This definitely reveals a bug either in Lean or in how mathlib uses Lean. There isn't much point in finding a workaround, we need a systematic fix.
Mario Carneiro (Apr 20 2023 at 12:54):
this is a known issue, I think
Patrick Massot (Apr 20 2023 at 12:54):
Is there a known fix then?
Mario Carneiro (Apr 20 2023 at 12:55):
It happens in ml3 as well, when you try to construct a deeply nested structure "in one go" without breaking out the parents into their own declarations
Scott Morrison (Apr 20 2023 at 12:56):
How slow was this in mathlib3? I don't remember.
Mario Carneiro (Apr 20 2023 at 12:56):
I would hope it doesn't get too bad, because of the abstraction of the _proof_i theorems
Scott Morrison (Apr 20 2023 at 12:56):
It seems they are not being abstracted properly here, however.
Mario Carneiro (Apr 20 2023 at 12:57):
it's possible that the way this abstraction is handled in lean 4 has changed in a way that is making the kernel see the full term
Scott Morrison (Apr 20 2023 at 12:57):
The actual proofs are showing up in the later proofs.
Scott Morrison (Apr 20 2023 at 12:57):
(That is, with pp.all
.)
Scott Morrison (Apr 20 2023 at 12:57):
But I would have hoped that they are behind _proof_n
.
Mario Carneiro (Apr 20 2023 at 12:57):
can this be MWE'd?
Mario Carneiro (Apr 20 2023 at 12:59):
Patrick Massot said:
Is there a known fix then?
there is a known workaround, which is as Matthew said: make a lemma
Sebastian Ullrich (Apr 20 2023 at 12:59):
I believe proofs are abstracted only after term elaboration
Scott Morrison (Apr 20 2023 at 13:00):
And that hasn't changed, I guess?
Mario Carneiro (Apr 20 2023 at 13:00):
I guess this is caused by a metavariable for the proof appearing in many places, somewhere in the structure instance elaborator
Mario Carneiro (Apr 20 2023 at 13:01):
even then it seems like it should be mostly okay since you get a dag-like term
Mario Carneiro (Apr 20 2023 at 13:01):
and after abstraction it shouldn't matter
Mario Carneiro (Apr 20 2023 at 13:02):
but shouldn't abstraction happen before it is sent to the kernel?
Sebastian Ullrich (Apr 20 2023 at 13:02):
You also mentioned another workaround above:
Mario Carneiro said:
breaking out the parents into their own declarations
This is a form of making the implicit term sharing explicit. Binding the suspected repeated metavariable with a let
would be another explicit sharing solution, but that might not be trivial at all to achieve.
Mario Carneiro (Apr 20 2023 at 13:03):
I worry about let
binders in instances making things weird in typeclass inference after unfolding
Mario Carneiro (Apr 20 2023 at 13:03):
not sure how much of an issue that is in reality
Sebastian Ullrich (Apr 20 2023 at 13:04):
Yes, it could definitely affect other things. But ideally it shouldn't be more problematic than splitting the code into multiple instances manually.
Patrick Massot (Apr 20 2023 at 13:04):
What is the Lean 4 syntax to say that missing fields should be taken from a previous named declaration?
Mario Carneiro (Apr 20 2023 at 13:04):
__ :=
should work
Sebastian Ullrich (Apr 20 2023 at 13:05):
I don't think identical proofs are abstracted into the same proof_N
declaration, so abstracting after duplication doesn't help all that much
Mario Carneiro (Apr 20 2023 at 13:05):
oof
Mario Carneiro (Apr 20 2023 at 13:06):
way to break term sharing
Sebastian Ullrich (Apr 20 2023 at 13:07):
My bad, there is indeed a cache
Patrick Massot (Apr 20 2023 at 13:08):
I can confirm this "fixes" the issue. But it's really really unnatural and ugly here.
Mario Carneiro (Apr 20 2023 at 13:10):
really? Looking at that definition above I would say it cries out for being factored into smaller pieces
Mario Carneiro (Apr 20 2023 at 13:10):
it's a bunch of things dependent over a function which is itself a quotient lift with a big proof in it
Patrick Massot (Apr 20 2023 at 13:12):
I'm talking about the SemiRing instance.
Mario Carneiro (Apr 20 2023 at 13:13):
you don't have to break it into every single parent, just enough to solve the performance issues
Mario Carneiro (Apr 20 2023 at 13:13):
like the notation typeclasses I would probably skip
Mario Carneiro (Apr 20 2023 at 13:14):
but you could split a semiring instance into a AddMonoid instance, a Monoid instance, and a semiring instance
Patrick Massot (Apr 20 2023 at 13:15):
I went with
instance instAddCommMonoid (r : R → R → Prop) : AddCommMonoid (RingQuot r) where
add := (· + ·)
zero := 0
add_assoc := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [add_quot, add_assoc]
zero_add := by
rintro ⟨⟨⟩⟩
simp [add_quot, ← zero_quot, zero_add]
add_zero := by
rintro ⟨⟨⟩⟩
simp only [add_quot, ← zero_quot, add_zero]
add_comm := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [add_quot, add_comm]
nsmul := (· • ·)
nsmul_zero := by
rintro ⟨⟨⟩⟩
simp only [smul_quot, zero_smul, zero_quot]
nsmul_succ := by
rintro n ⟨⟨⟩⟩
simp only [smul_quot, nsmul_eq_mul, Nat.cast_add, Nat.cast_one, add_mul, one_mul,
add_comm, add_quot]
instance instMonoidWithZero (r : R → R → Prop) : MonoidWithZero (RingQuot r) where
mul_assoc := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, mul_assoc]
one_mul := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← one_quot, one_mul]
mul_one := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← one_quot, mul_one]
zero_mul := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← zero_quot, zero_mul]
mul_zero := by
rintro ⟨⟨⟩⟩
simp only [mul_quot, ← zero_quot, mul_zero]
npow n x := x ^ n
npow_zero := by
rintro ⟨⟨⟩⟩
simp only [pow_quot, ← one_quot, pow_zero]
npow_succ := by
rintro n ⟨⟨⟩⟩
simp only [pow_quot, mul_quot, pow_succ]
instance instSemiring (r : R → R → Prop) : Semiring (RingQuot r) where
natCast := natCast r
natCast_zero := by simp [Nat.cast, natCast_def, ← zero_quot]
natCast_succ := by simp [Nat.cast, natCast_def, ← one_quot, add_quot]
left_distrib := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, add_quot, left_distrib]
right_distrib := by
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟩⟩
simp only [mul_quot, add_quot, right_distrib]
nsmul := (· • ·)
nsmul_zero := by
rintro ⟨⟨⟩⟩
simp only [smul_quot, zero_smul, zero_quot]
nsmul_succ := by
rintro n ⟨⟨⟩⟩
simp only [smul_quot, nsmul_eq_mul, Nat.cast_add, Nat.cast_one, add_mul, one_mul,
add_comm, add_quot]
__ := instAddCommMonoid r
__ := instMonoidWithZero r
Patrick Massot (Apr 20 2023 at 13:16):
Which roughly split in three equal pieces. But mathematically this is meaningless.
Patrick Massot (Apr 20 2023 at 13:16):
The reason it is meaningless is that R
already has all the required typeclasses anyway.
Mario Carneiro (Apr 20 2023 at 13:16):
sure it is meaningful. You don't need to give the full proof of semiring at once
Patrick Massot (Apr 20 2023 at 13:16):
Since they are needed to talk about RingQuot r
Mario Carneiro (Apr 20 2023 at 13:17):
lemma 1 is that it's a monoid, lemma 2 is that it's also an add monoid, and lemma 3 is that the structures cohere
Scott Morrison (Apr 20 2023 at 13:17):
It does seem like it wouldn't be too hard to MWE this, which might be worth doing just to help document the issue, even if no mitigation is planned.
Scott Morrison (Apr 20 2023 at 13:17):
I think I'm with Mario that this is fine as library code, but with Patrick that this is a horrible footgun.
Mario Carneiro (Apr 20 2023 at 13:18):
oh absolutely
Scott Morrison (Apr 20 2023 at 13:18):
It certainly feels like you should just be able to do all the easy proofs one after the other, so it's easy to write something extremely non-performant.
Scott Morrison (Apr 20 2023 at 13:19):
I'd also like to know why we got away with this in ml3.
Mario Carneiro (Apr 20 2023 at 13:19):
flat structures might play a role, although you still get some of the same issues as long as you have multiple layers of hierarchy
Patrick Massot (Apr 20 2023 at 13:20):
Needless to see, none of these proof would appear in the real world. The most you can hope for is explicitly leaving them to readers.
Mario Carneiro (Apr 20 2023 at 13:21):
I think about why lean couldn't just do this definition splitting automatically, but then things get weird as far as what the proof state actually is while you are proving it
Mario Carneiro (Apr 20 2023 at 13:21):
because these dependent proofs are actually visible in the tactic state if you click around
Mario Carneiro (Apr 20 2023 at 13:22):
and if we make a definition then you might have to block on some part of the proof getting finished before you can even proceed to show errors on the dependent parts
Mario Carneiro (Apr 20 2023 at 13:23):
which IIRC is a thing that actually happened in lean 3 in some situations
Floris van Doorn (Apr 21 2023 at 16:48):
These humongous subgoals also cause/expose the performance problems that to_additive
has in some files. In !4#3580 adding a single dsimp only
in a proof speeds up to_additive
4x.
Last updated: Dec 20 2023 at 11:08 UTC