Zulip Chat Archive
Stream: mathlib4
Topic: Strange `field_simp` failure
Adam Topaz (Oct 17 2023 at 02:17):
One of the students in my formalization class found the following curious behavior of field_simp
:
import Mathlib.Tactic
class Test (M : Type) extends Mul M -- comment out this line...
example (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring -- fails
Commenting out the Test
class line makes the example work just fine. Also, replacing Mul
with Add
in the definition of Test
also fixes the issue. I spent a few minutes trying to minimize the example, but couldn't find a smaller example.
Damiano Testa (Oct 17 2023 at 06:59):
Adam, I am assuming that you are working in a project that depends on Mathlib, right?
Within Mathlib, adding variable {F}/variable {F : Type _}
switches the behaviour: Test
confuses ring
field_simp
, omitting it makes it work.
import Mathlib.Tactic
variable {F}
--class Test (M : Type) extends Mul M -- uncomment this line...
example (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring -- fails
However, variable {F : Type*}
seems to work fine regardless of the presence of Test
.
David Renshaw (Oct 17 2023 at 11:32):
on the first example, with set_option trace.Tactic.field_simp true
I see
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ❌ discharge IsLeftRegular z
[Tactic.field_simp] ❌ discharge IsRightRegular (1 - z)
and then when I comment out the class
command I see
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge (1 - z) * (z * (1 - z)) ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
[Tactic.field_simp] ✅ discharge z * (1 - z) ≠ 0
[Tactic.field_simp] ✅ discharge z ≠ 0
[Tactic.field_simp] ✅ discharge 1 - z ≠ 0
David Renshaw (Oct 17 2023 at 12:10):
Ah, the problem is that F
is an auto-implicit (as Damiano also discovered).
David Renshaw (Oct 17 2023 at 12:10):
This works as expected:
example {F : Type*} (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp; ring
Adam Topaz (Oct 17 2023 at 12:53):
Ok, yes, I agree that auto implicit had something to do with it in the original example, but I still have no idea why the following doesn't work
import Mathlib.Tactic
set_option autoImplicit false
class Test (M : Type) extends Mul M -- comment out this line...
example {F : Type _} (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring -- fails
but the following works just fine:
import Mathlib.Tactic
set_option autoImplicit false
example {F : Type _} (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring -- works
Adam Topaz (Oct 17 2023 at 12:54):
Aha! This works as well:
import Mathlib.Tactic
set_option autoImplicit false
class Test (M : Type _) extends Mul M -- comment out this line...
example {F : Type _} (x y z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring -- works
Adam Topaz (Oct 17 2023 at 12:55):
So it actually looks like the issue has to do with universes somehow!
David Renshaw (Oct 17 2023 at 12:56):
With {F : Type _}
, the universe of F
is a metavariable
David Renshaw (Oct 17 2023 at 12:56):
with {F : Type*}
, the universe is explicitly bound
Adam Topaz (Oct 17 2023 at 12:56):
I understand, but why does adding class Test ...
change the behavior?
Adam Topaz (Oct 17 2023 at 12:56):
In the {F : Type _}
case.
Sebastien Gouezel (Oct 17 2023 at 12:56):
Rule of thumb: left of the colon, always use Type*
or Type u
, never Type _
.
Adam Topaz (Oct 17 2023 at 12:57):
I'm not looking for rules of thumb. I want to understand what's actually going on.
Matthew Ballard (Oct 17 2023 at 12:58):
Do you have just (M : Type)
there?
Kevin Buzzard (Oct 17 2023 at 12:59):
Yeah. Changing it to the evil Type _
fixes it :-)
Matthew Ballard (Oct 17 2023 at 12:59):
Sounds like it is bailing after failing to unify the first universe pair it finds
David Renshaw (Oct 17 2023 at 12:59):
yeah, my working principle is that if metavariables are showing up in my goal view, then all bets are off
Adam Topaz (Oct 17 2023 at 12:59):
yeah exactly. that's another mystery
Matthew Ballard (Oct 17 2023 at 13:01):
Ah, the old "field_simp
refused to clear denominators"
Adam Topaz (Oct 17 2023 at 13:01):
Oh that's been pointed out before?
Matthew Ballard (Oct 17 2023 at 13:02):
In my experience, that is the number one type of failure. I still have an open PR that helps with this and other things
Matthew Ballard (Oct 17 2023 at 13:02):
But I got pulled away
Adam Topaz (Oct 17 2023 at 13:04):
Oh, that's precisely what's happening.... field simp will not clear the z * (1 - z)
denominators, but it clears z
and (1-z)
.
Sebastien Gouezel (Oct 17 2023 at 13:04):
Funny fact: if you replace example
with lemma
, it works. But it fails with def
.
Matthew Ballard (Oct 17 2023 at 13:04):
Oh my
Adam Topaz (Oct 17 2023 at 13:04):
Ok, now I'm even more confused.
Adam Topaz (Oct 17 2023 at 13:05):
Just to clarify, I know very well when to use explicit universes Type u
and/or Type*
. This came up when one of the students in my class was playing around with some code I wrote during class. I think such issues really don't look good for newcomers :-/
Eric Rodriguez (Oct 17 2023 at 13:06):
Is this the thing about lemma
forcing elaboration of the expected type?
Eric Rodriguez (Oct 17 2023 at 13:06):
Or has that vanished since lean3?
Mauricio Collares (Oct 17 2023 at 13:08):
Matthew Ballard (Oct 17 2023 at 13:20):
Lean really wants Group F
in the failure case
Matthew Ballard (Oct 17 2023 at 13:21):
Actually in both cases
Adam Topaz (Oct 17 2023 at 13:22):
yeah I think the trace that David posted above is quite telling.
Adam Topaz (Oct 17 2023 at 13:22):
FWIW, here's a slightly smaller example to play with:
import Mathlib.Tactic
set_option autoImplicit false
class Test (M : Type) extends Mul M -- comment out this line...
example {F : Type _} (z w : F) [Field F] (h₁ : z ≠ 0) (h₂ : w ≠ 0) :
1 + 1 / z + 1 / w = (w + z) / (z * w) + 1 := by
field_simp
ring -- fails
Adam Topaz (Oct 17 2023 at 13:23):
Moving the 1 +
to the other side of the LHS of the equality makes the example work again :rofl:
Matthew Ballard (Oct 17 2023 at 13:26):
It wants docs#div_eq_iff
Matthew Ballard (Oct 17 2023 at 13:28):
It gets that in both cases. But it cannot discharge z * (1 -z) ≠ 0
with docs#mul_ne_zero
Matthew Ballard (Oct 17 2023 at 13:29):
It looks like it has trouble with Mul F
Matthew Ballard (Oct 17 2023 at 13:31):
[Tactic.field_simp] ❌ discharge z * (1 - z) ≠ 0 ▼
[Meta.Tactic.simp.unify] @sub_self:1000, failed to unify
?a - ?a
with
1 - z
[Meta.Tactic.simp.discharge] @tsub_eq_zero_of_le, failed to synthesize instance
CanonicallyOrderedAddCommMonoid F
[Meta.Tactic.simp.discharge] @CharTwo.sub_eq_add, failed to synthesize instance
CharP F 2
[Meta.Tactic.simp.unify] @Ordinal.enum_le_enum:1000, failed to unify
¬?r (Ordinal.enum ?r ?o' ?ho') (Ordinal.enum ?r ?o ?ho)
with
z * (1 - z) ≠ 0
[Meta.Tactic.simp.rewrite] @ne_eq:1000, z * (1 - z) ≠ 0 ==> ¬z * (1 - z) = 0
[Meta.Tactic.simp.discharge] @mul_ne_zero, failed to synthesize instance
Mul F
Matthew Ballard (Oct 17 2023 at 13:34):
[Meta.synthInstance] 💥 Mul F ▼
[] new goal Mul F ▼
[instances] #[@Semigroup.toMul, @MulOneClass.toMul, @MulZeroClass.toMul, @Distrib.toMul, @NonUnitalNonAssocSemiring.toMul, @NonUnitalNonAssocRing.toMul, @CanonicallyOrderedCommSemiring.toMul, @Test.toMul]
[] 💥 apply @Test.toMul to Mul F ▼
[tryResolve] 💥 Mul F ≟ Mul ?m.5577
Matthew Ballard (Oct 17 2023 at 13:47):
A have : Mul F := inferInstance
is totally fine though. And it isn't any secret timeout
Matthew Ballard (Oct 17 2023 at 13:48):
Perhaps there is something about how the discharger is written
Matthew Ballard (Oct 17 2023 at 14:08):
No it most likely due to something with universe unification
Adam Topaz (Oct 17 2023 at 14:35):
Here's a fully minimal example
import Mathlib.Tactic
set_option autoImplicit false
class Test (M : Type) extends Mul M -- comment out this line...
example {F : Type _} (z w : F) [Field F] (h₁ : z ≠ 0) (h₂ : w ≠ 0) : z * w ≠ 0 := by
field_simp
Matthew Ballard (Oct 17 2023 at 14:41):
simp
doesn't close it either
Adam Topaz (Oct 17 2023 at 14:42):
Sure, but I wouldn't expect it to.
Matthew Ballard (Oct 17 2023 at 14:42):
But it does apply mul_eq_zero
Adam Topaz (Oct 17 2023 at 14:45):
the full simp trace without the class:
[Meta.Tactic.simp.unify] @Ordinal.enum_le_enum:1000, failed to unify
¬?r (Ordinal.enum ?r ?o' ?ho') (Ordinal.enum ?r ?o ?ho)
with
z * w ≠ 0
[Meta.Tactic.simp.rewrite] @ne_eq:1000, z * w ≠ 0 ==> ¬z * w = 0
[Meta.Tactic.simp.rewrite] @mul_ne_zero:1000, z * w = 0 ==> False
[Meta.Tactic.simp.unify] @Ordinal.enum_le_enum:1000, failed to unify
¬?r (Ordinal.enum ?r ?o' ?ho') (Ordinal.enum ?r ?o ?ho)
with
¬False
[Meta.Tactic.simp.rewrite] not_false_eq_true:1000, ¬False ==> True
and with the class, here are the first few lines of the trace:
[Meta.Tactic.simp.unify] @Ordinal.enum_le_enum:1000, failed to unify
¬?r (Ordinal.enum ?r ?o' ?ho') (Ordinal.enum ?r ?o ?ho)
with
z * w ≠ 0
[Meta.Tactic.simp.rewrite] @ne_eq:1000, z * w ≠ 0 ==> ¬z * w = 0
[Meta.Tactic.simp.discharge] @mul_ne_zero, failed to synthesize instance
Mul F
Adam Topaz (Oct 17 2023 at 14:45):
this is the usual simp trace, but with the field_simp
tactic.
Adam Topaz (Oct 17 2023 at 14:45):
I suppose this is something you already noticed, Matt?
Matthew Ballard (Oct 17 2023 at 14:46):
Yeah, it just blows up at the Mul F
synthesis
Adam Topaz (Oct 17 2023 at 14:48):
Changing Test
to either
class A (X : Type)
[inst : Mul X]
or
class A (X : Type) [Mul X]
both resolve the issue as well.
Matthew Ballard (Oct 17 2023 at 14:49):
simp
does not appear to need this
Matthew Ballard said:
[Meta.synthInstance] 💥 Mul F ▼ [] new goal Mul F ▼ [instances] #[@Semigroup.toMul, @MulOneClass.toMul, @MulZeroClass.toMul, @Distrib.toMul, @NonUnitalNonAssocSemiring.toMul, @NonUnitalNonAssocRing.toMul, @CanonicallyOrderedCommSemiring.toMul, @Test.toMul] [] 💥 apply @Test.toMul to Mul F ▼ [tryResolve] 💥 Mul F ≟ Mul ?m.5577
More precisely
Matthew Ballard (Oct 17 2023 at 14:52):
I would nice to pull this out of field_simp
Heather Macbeth (Oct 17 2023 at 14:58):
I think there's also a positivity bug here. Note that this works:
import Mathlib.Tactic
class Test (M : Type) extends Mul M -- comment out this line...
example (x y z : ℚ) (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) :
(x + y/z) + x * z/(1 - z) = (x - y)/(1-z) + y/(z * (1-z)) := by
field_simp
ring
Heather Macbeth (Oct 17 2023 at 14:58):
I'm guessing the issue is:
import Mathlib.Tactic.Positivity
import Mathlib.Data.Rat.Order
example (z : F) [Field F] (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) : z * (1 - z) ≠ 0 := by
positivity -- fails
example (z : ℚ) (h₁ : z ≠ 0) (h₂ : 1 - z ≠ 0) : z * (1 - z) ≠ 0 := by
positivity -- works
Heather Macbeth (Oct 17 2023 at 14:59):
i.e. perhaps the multiplication positivity discharger is specialized unnecessarily to ordered fields?
Matthew Ballard (Oct 17 2023 at 14:59):
Can at least reduce to import Mathlib.Tactic.FieldSimp
Heather Macbeth (Oct 17 2023 at 15:01):
I'm guessing this line is too demanding.
Matthew Ballard (Oct 17 2023 at 15:05):
If I yank out positivity from field_simp
it still fails
Matthew Ballard (Oct 17 2023 at 15:08):
Actually if I yank out the whole discharger it still fails
Heather Macbeth (Oct 17 2023 at 15:08):
My guess: there are two different bugs, and Adam's was not caught earlier because people usually use field_simp
on ordered fields and positivity
was covering for Adam's bug.
Matthew Ballard (Oct 17 2023 at 15:08):
With the same error of course
Matthew Ballard (Oct 17 2023 at 15:10):
Set dis
to none
here and we still end up not synthesizing Mul F
Matthew Ballard (Oct 17 2023 at 15:25):
syntax (name := myfieldSimp) "myfield_simp" : tactic
elab_rules : tactic
| `(tactic| myfield_simp) => withMainContext do
let loc := expandOptLocation (mkOptionalNode none)
let thms0 ← getSimpTheorems
let some ext ← getSimpExtension? `field_simps | throwError "field_simps not found"
let thms ← ext.getTheorems
let ctx : Simp.Context := {
simpTheorems := #[thms,thms0]
congrTheorems := (← getSimpCongrTheorems)
}
_ ← simpLocation ctx none loc
still has the same behavior
Matthew Ballard (Oct 17 2023 at 17:13):
This still has the Mul F
synthesization problem. You need to register_simp_attr mysimp
in a dependent file.
import Mathlib.Init.ZeroOne
import Mathlib.Tactic.Attr.Register
universe u v w
class Semigroup' (α : Type u) extends Mul α
open Lean Elab Tactic Meta
syntax (name := mySimp) "my_simp" : tactic
elab_rules : tactic
| `(tactic| my_simp) => withMainContext do
let loc := expandOptLocation (mkOptionalNode none)
let some ext ← getSimpExtension? `mysimp | throwError "💩"
let thms ← ext.getTheorems
let ctx : Simp.Context := {
simpTheorems := #[thms]
}
_ ← simpLocation ctx none loc
class Test (M : Type) extends Mul M -- comment out this line...
@[mysimp]
theorem ne_eq' {α : Sort v} (a b : α) : (a ≠ b) = ¬(a = b) := rfl
@[mysimp]
theorem mul_ne_zero' {M₀ : Type w} [Mul M₀] [Zero M₀] {a b : M₀}
(ha : a ≠ 0) (hb : b ≠ 0) : a * b ≠ 0 := sorry
set_option trace.Meta.Tactic.simp true in
example {F : Type _} (z w : F) [Semigroup' F] [Zero F] (h₁ : z ≠ 0) (h₂ : w ≠ 0) : z * w ≠ 0 := by
my_simp
Matthew Ballard (Oct 17 2023 at 17:32):
Forgot
[Meta.isLevelDefEq] 💥 0 =?= ?u.4092 ▼
[stuck] 0 =?= ?u.4092
Matthew Ballard (Oct 17 2023 at 17:38):
Looks like a problem unifying universe number literals because (M : Type 10)
behaves the same
Matthew Ballard (Oct 17 2023 at 17:41):
I assume we never recover from a stuck universe unification problem?
Matthew Ballard (Oct 17 2023 at 17:52):
Smaller
import Mathlib.Init.ZeroOne
universe u w
class Semigroup' (α : Type u) extends Mul α
class Test (M : Type 10) extends Mul M -- comment out this line...
theorem mul_ne_zero' {M₀ : Type w} [Mul M₀] [Zero M₀] {a b : M₀} : ¬ (a * b = 0) := sorry
set_option trace.Meta.isLevelDefEq true in
set_option trace.Meta.Tactic.simp true in
example {F : Type _} (z w : F) [Semigroup' F] [Zero F] : ¬ (z * w = 0) := by
simp only [mul_ne_zero'] -- failed to synthesize instance Mul F
Matthew Ballard (Oct 17 2023 at 17:58):
Mathlib free
universe u v w
def TooShort (M : Type w) : Prop := sorry
class Semigroup' (α : Type u) extends Mul α
class Test (M : Type 10) extends Mul M
theorem mul_ne_zero' {M₀ : Type v} [Mul M₀] : TooShort M₀ := sorry
set_option trace.Meta.isLevelDefEq true in
set_option trace.Meta.Tactic.simp true in
example {F : Type _} [Semigroup' F] : TooShort F := by
simp only [mul_ne_zero']
/-
[Meta.isLevelDefEq] 💥 10 =?= ?u.63 ▼
[stuck] 10 =?= ?u.63
[Meta.Tactic.simp.discharge] @mul_ne_zero', failed to synthesize instance
Mul F
-/
Matthew Ballard (Oct 17 2023 at 18:00):
Change Semigroup'
to Mul
and it succeeds. Change (F : Type _)
to a variable or change (M : Type 10)
to a variable and it succeeds
Matthew Ballard (Oct 17 2023 at 18:02):
Sadly I would have to use «Too$hort»
Damiano Testa (Oct 17 2023 at 18:31):
If you swap Semigroup'
and Test
it succeeds.
Matthew Ballard (Oct 17 2023 at 18:33):
Instance priority
Matthew Ballard (Oct 17 2023 at 18:33):
Can I open private
with core files?
Alex J. Best (Oct 17 2023 at 18:35):
Matthew Ballard said:
Can I
open private
with core files?
you should be able to yes
Matthew Ballard (Oct 17 2023 at 18:40):
Can I alias the declaration at the same time?
Mario Carneiro (Oct 17 2023 at 18:43):
you can do an alias
after opening it, or use export private
instead
Matthew Ballard (Oct 17 2023 at 18:46):
Oh, export private
is more pleasant
Matthew Ballard (Oct 18 2023 at 12:46):
The reason this fails is because the metacontext depth (2) exceeds the metavariable depth for
?u
from (F : Type _)
(0) so it is not assignable.
I am still confused as to why there are metavariables of depth > 0 around here
[Meta.synthInstance] 💥 Mul.{?_uniq.63} _uniq.73 ▼
[] new goal Mul.{?_uniq.63} _uniq.73 ▼
[instances] #[Uno.toMul.{?_uniq.105}, Dos.toMul]
[] 💥 apply Dos.toMul to Mul.{?_uniq.63} _uniq.73 ▼
[tryResolve] 💥 Mul.{?_uniq.63} _uniq.73 ≟ Mul.{10} ?_uniq.106 ▼
[isDefEq] 💥 Mul.{?_uniq.63} _uniq.73 =?= Mul.{10} ?_uniq.106 ▼
[] 💥 _uniq.73 =?= ?_uniq.106 ▼
[] _uniq.73 [nonassignable] =?= ?_uniq.106 [assignable]
[] 💥 Type.{10} =?= Type.{?_uniq.63} ▼
[isLevelDefEq] 💥 10 =?= ?u.63 ▼
[] ?u.63 is not assignable
[] 10 is not assignable
[] At depth 2
[] [(_uniq.65, 0), (_uniq.66, 0), (_uniq.63, 0), (_uniq.69, 0), (_uniq.88, 0), (_uniq.62, 0), (_uniq.100, 1), (_uniq.68, 0), (_uniq.105, 2)] -- A list of current metavariables in the context and their depths
[] [Mul.{?_uniq.100} ?_uniq.101, Type.{?_uniq.100}]
[stuck] Here I am 10 =?= ?u.63
(I added some more verbosity to my toolchain for this output)
Matthew Ballard (Oct 18 2023 at 12:46):
I changed the example a bit
universe u v w
def TooShort (M : Type w) : Prop := sorry
class Uno (α : Type u) extends Mul α
class Dos (M : Type 10) extends Mul M -- comment out this line...
theorem short_short {M₀ : Type v} [Mul M₀] : TooShort M₀ := sorry
set_option pp.raw true in
set_option trace.Meta.isLevelDefEq true in
set_option trace.Meta.synthInstance true in
set_option trace.Meta.isDefEq true in
set_option trace.Debug.Meta.Tactic.simp true in
example {F : Type _} [Uno F] : TooShort F := by
simp only [short_short]
Matthew Ballard (Oct 18 2023 at 12:50):
I am guessing there is +1 from entering the simp
and +1 from TC for Mul
in short_short
Matthew Ballard (Oct 18 2023 at 12:52):
_uniq.105
arises from a list of the available instances but doesn't play any role in the unification problem at hand itself. The same is true for _uniq.100
Matthew Ballard (Oct 18 2023 at 13:06):
If I comment out to remove the depth 2 metavariable,
class Uno (α : Type u) --extends Mul α
then I get something I understand less
[Meta.isDefEq] ✅ TooShort.{?_uniq.85} ?_uniq.86 =?= TooShort.{?_uniq.48} _uniq.58 ▼
[] ✅ ?_uniq.86 =?= _uniq.58 ▼
[] ?_uniq.86 [assignable] =?= _uniq.58 [nonassignable]
[] ✅ Type.{?_uniq.85} =?= Type.{?_uniq.48} ▼
[isLevelDefEq] ✅ ?u.85 =?= ?u.48
[isLevelDefEq] ✅ ?u.85 =?= ?u.48 ▼
[] ✅ ?u.48 =?= ?u.48
[Meta.synthInstance] 💥 Mul.{?_uniq.48} _uniq.58 ▼
[] new goal Mul.{?_uniq.48} _uniq.58 ▼
[instances] #[Dos.toMul]
[] 💥 apply Dos.toMul to Mul.{?_uniq.48} _uniq.58 ▼
[tryResolve] 💥 Mul.{?_uniq.48} _uniq.58 ≟ Mul.{10} ?_uniq.90 ▼
[isDefEq] 💥 Mul.{?_uniq.48} _uniq.58 =?= Mul.{10} ?_uniq.90 ▼
[] 💥 _uniq.58 =?= ?_uniq.90 ▼
[] _uniq.58 [nonassignable] =?= ?_uniq.90 [assignable]
[] 💥 Type.{10} =?= Type.{?_uniq.48} ▼
[isLevelDefEq] 💥 10 =?= ?u.48 ▼
[] ?u.48 is not assignable
[] 10 is not assignable
[] At depth 2
[] [(_uniq.85, 1), (_uniq.50, 0), (_uniq.73, 0), (_uniq.51, 0), (_uniq.54, 0), (_uniq.48, 0), (_uniq.53, 0), (_uniq.47, 0)]
[] [Mul.{?_uniq.85} ?_uniq.86, Type.{?_uniq.85}]
[stuck] Here I am 10 =?= ?u.48
Why I am depth 2 when all my metavariables are at most 1? Why is _uniq.85
appearing when it gets assigned to _uniq.48
when unifying TooShort
?
Last updated: Dec 20 2023 at 11:08 UTC