perf: isDefEqProj (#4004)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
This commit is contained in:
Leonardo de Moura 2024-04-28 01:30:35 +02:00 committed by GitHub
parent e3592e40cf
commit a359586a96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 311 additions and 3 deletions

View file

@ -313,6 +313,12 @@ structure Context where
progress processing universe constraints.
-/
univApprox : Bool := false
/--
`inTypeClassResolution := true` when `isDefEq` is invoked at `tryResolve` in the type class
resolution module. We don't use `isDefEqProjDelta` when performing TC resolution due to performance issues.
This is not a great solution, but a proper solution would require a more sophisticased caching mechanism.
-/
inTypeClassResolution : Bool := false
/--
The `MetaM` monad is a core component of Lean's metaprogramming framework, facilitating the

View file

@ -1759,7 +1759,7 @@ private def isDefEqDeltaStep (t s : Expr) : MetaM DeltaStepResult := do
| .eq =>
-- Remark: if `t` and `s` are both some `f`-application, we use `tryHeuristic`
-- if `f` is not a projection. The projection case generates a performance regression.
if tInfo.name == sInfo.name && !(← isProjectionFn tInfo.name) then
if tInfo.name == sInfo.name then
if t.isApp && s.isApp && (← tryHeuristic t s) then
return .eq
else
@ -1803,8 +1803,11 @@ where
| _, _ => Meta.isExprDefEqAux t s
private def isDefEqProj : Expr → Expr → MetaM Bool
| .proj m i t, .proj n j s =>
if i == j && m == n then
| .proj m i t, .proj n j s => do
if (← read).inTypeClassResolution then
-- See comment at `inTypeClassResolution`
pure (i == j && m == n) <&&> Meta.isExprDefEqAux t s
else if i == j && m == n then
isDefEqProjDelta t s i
else
return false

View file

@ -711,6 +711,7 @@ def synthInstance? (type : Expr) (maxResultSize? : Option Nat := none) : MetaM (
(return m!"{exceptOptionEmoji ·} {← instantiateMVars type}") do
withConfig (fun config => { config with isDefEqStuckEx := true, transparency := TransparencyMode.instances,
foApprox := true, ctxApprox := true, constApprox := false, univApprox := false }) do
withReader (fun ctx => { ctx with inTypeClassResolution := true }) do
let localInsts ← getLocalInstances
let type ← instantiateMVars type
let type ← preprocess type

298
tests/lean/run/3965_3.lean Normal file
View file

@ -0,0 +1,298 @@
section Mathlib.Init.Order.Defs
universe u
variable {α : Type u}
class Preorder (α : Type u) extends LE α, LT α
theorem le_trans [Preorder α] : ∀ {a b c : α}, a ≤ b → b ≤ c → a ≤ c := sorry
class PartialOrder (α : Type u) extends Preorder α where
le_antisymm : ∀ a b : α, a ≤ b → b ≤ a → a = b
end Mathlib.Init.Order.Defs
section Mathlib.Init.Set
set_option autoImplicit true
def Set (α : Type u) := α → Prop
namespace Set
protected def Mem (a : α) (s : Set α) : Prop :=
s a
instance : Membership α (Set α) :=
⟨Set.Mem⟩
def image (f : α → β) (s : Set α) : Set β := fun b => ∃ a, ∃ (_ : a ∈ s), f a = b
end Set
end Mathlib.Init.Set
section Mathlib.Data.Subtype
attribute [coe] Subtype.val
end Mathlib.Data.Subtype
section Mathlib.Order.Notation
class Sup (α : Type _) where
sup : ααα
class Inf (α : Type _) where
inf : ααα
@[inherit_doc]
infixl:68 " ⊔ " => Sup.sup
@[inherit_doc]
infixl:69 " ⊓ " => Inf.inf
class Top (α : Type _) where
top : α
class Bot (α : Type _) where
bot : α
notation "" => Top.top
notation "⊥" => Bot.bot
end Mathlib.Order.Notation
section Mathlib.Data.Set.Defs
universe u
namespace Set
variable {α : Type u}
@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s}
instance : CoeSort (Set α) (Type u) := ⟨Elem⟩
end Set
end Mathlib.Data.Set.Defs
section Mathlib.Order.Basic
universe u
variable {α : Type u}
def Preorder.lift {α β} [Preorder β] (f : α → β) : Preorder α where
le x y := f x ≤ f y
lt x y := f x < f y
def PartialOrder.lift {α β} [PartialOrder β] (f : α → β) : PartialOrder α :=
{ Preorder.lift f with le_antisymm := sorry }
namespace Subtype
instance le [LE α] {p : α → Prop} : LE (Subtype p) :=
⟨fun x y ↦ (x : α) ≤ y⟩
instance lt [LT α] {p : α → Prop} : LT (Subtype p) :=
⟨fun x y ↦ (x : α) < y⟩
instance partialOrder [PartialOrder α] (p : α → Prop) : PartialOrder (Subtype p) :=
PartialOrder.lift (fun (a : Subtype p) ↦ (a : α))
end Subtype
end Mathlib.Order.Basic
section Mathlib.Order.Lattice
universe u
variable {α : Type u}
class SemilatticeSup (α : Type u) extends Sup α, PartialOrder α where
protected le_sup_left : ∀ a b : α, a ≤ a ⊔ b
protected le_sup_right : ∀ a b : α, b ≤ a ⊔ b
protected sup_le : ∀ a b c : α, a ≤ c → b ≤ c → a ⊔ b ≤ c
section SemilatticeSup
variable [SemilatticeSup α] {a b c : α}
theorem sup_le : a ≤ c → b ≤ c → a ⊔ b ≤ c := sorry
end SemilatticeSup
class SemilatticeInf (α : Type u) extends Inf α, PartialOrder α where
protected inf_le_left : ∀ a b : α, a ⊓ b ≤ a
protected inf_le_right : ∀ a b : α, a ⊓ b ≤ b
protected le_inf : ∀ a b c : α, a ≤ b → a ≤ c → a ≤ b ⊓ c
section SemilatticeInf
variable [SemilatticeInf α] {a b c d : α}
theorem inf_le_left : a ⊓ b ≤ a := sorry
theorem le_inf_iff : a ≤ b ⊓ c ↔ a ≤ b ∧ a ≤ c := sorry
end SemilatticeInf
class Lattice (α : Type u) extends SemilatticeSup α, SemilatticeInf α
namespace Subtype
protected def semilatticeSup [SemilatticeSup α] {P : α → Prop}
(Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) :
SemilatticeSup { x : α // P x } where
sup x y := ⟨x.1 ⊔ y.1, sorry⟩
le_sup_left _ _ := sorry
le_sup_right _ _ := sorry
sup_le _ _ _ h1 h2 := sorry
protected def semilatticeInf [SemilatticeInf α] {P : α → Prop}
(Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) :
SemilatticeInf { x : α // P x } where
inf x y := ⟨x.1 ⊓ y.1, sorry⟩
inf_le_left _ _ := sorry
inf_le_right _ _ := sorry
le_inf _ _ _ h1 h2 := sorry
end Subtype
end Mathlib.Order.Lattice
section Mathlib.Order.BoundedOrder
universe u
class OrderTop (α : Type u) [LE α] extends Top α where
le_top : ∀ a : α, a ≤
class OrderBot (α : Type u) [LE α] extends Bot α where
bot_le : ∀ a : α, ⊥ ≤ a
end Mathlib.Order.BoundedOrder
section Mathlib.Data.Set.Intervals.Basic
variable {α : Type _} [Preorder α]
def Set.Iic (b : α) : Set α := fun x => x ≤ b
end Mathlib.Data.Set.Intervals.Basic
section Mathlib.Order.SetNotation
universe u
variable {α : Type u}
class SupSet (α : Type _) where
sSup : Set αα
class InfSet (α : Type _) where
sInf : Set αα
export SupSet (sSup)
export InfSet (sInf)
end Mathlib.Order.SetNotation
section Mathlib.Order.CompleteLattice
variable {α : Type _}
class CompleteSemilatticeSup (α : Type _) extends PartialOrder α, SupSet α where
sSup_le : ∀ s a, (∀ b ∈ s, b ≤ a) → sSup s ≤ a
section
variable [CompleteSemilatticeSup α] {s t : Set α} {a b : α}
theorem sSup_le : (∀ b ∈ s, b ≤ a) → sSup s ≤ a := sorry
end
class CompleteSemilatticeInf (α : Type _) extends PartialOrder α, InfSet α where
le_sInf : ∀ s a, (∀ b ∈ s, a ≤ b) → a ≤ sInf s
section
variable [CompleteSemilatticeInf α] {s t : Set α} {a b : α}
theorem le_sInf : (∀ b ∈ s, a ≤ b) → a ≤ sInf s := sorry
end
class CompleteLattice (α : Type _) extends Lattice α, CompleteSemilatticeSup α,
CompleteSemilatticeInf α, Top α, Bot α where
protected le_top : ∀ x : α, x ≤
protected bot_le : ∀ x : α, ⊥ ≤ x
instance (priority := 100) CompleteLattice.toOrderTop [h : CompleteLattice α] : OrderTop α :=
{ h with }
instance (priority := 100) CompleteLattice.toOrderBot [h : CompleteLattice α] : OrderBot α :=
{ h with }
end Mathlib.Order.CompleteLattice
section Mathlib.Order.LatticeIntervals
variable {α : Type _}
namespace Set
namespace Iic
instance semilatticeInf [SemilatticeInf α] {a : α} : SemilatticeInf (Iic a) :=
Subtype.semilatticeInf fun _ _ hx _ => le_trans inf_le_left hx
instance semilatticeSup [SemilatticeSup α] {a : α} : SemilatticeSup (Iic a) :=
Subtype.semilatticeSup fun _ _ hx hy => sup_le hx hy
instance [Lattice α] {a : α} : Lattice (Iic a) :=
{ Iic.semilatticeInf, Iic.semilatticeSup with }
instance orderTop [Preorder α] {a : α} : OrderTop (Iic a) := sorry
instance orderBot [Preorder α] [OrderBot α] {a : α} : OrderBot (Iic a) := sorry
end Iic
end Set
end Mathlib.Order.LatticeIntervals
section Mathlib.Order.CompleteLatticeIntervals
variable {α : Type _}
namespace Set.Iic
variable [CompleteLattice α] {a : α}
def instCompleteLattice : CompleteLattice (Iic a) where
sSup S := ⟨sSup (Set.image (fun x : Iic a => (x : α)) S), sorry⟩
sInf S := ⟨a ⊓ sInf (Set.image (fun x : Iic a => (x : α)) S), sorry⟩
sSup_le S b hb := sSup_le <| fun c' ⟨c, hc, hc'⟩ ↦ hc' ▸ hb c hc
le_sInf S b hb := le_inf_iff.mpr
⟨b.property, le_sInf fun d' ⟨d, hd, hd'⟩ ↦ hd' ▸ hb d hd⟩
le_top := sorry
bot_le := sorry
example : CompleteLattice (Iic a) where
sSup S := ⟨sSup (Set.image (fun x : Iic a => (x : α)) S), sorry⟩
sInf S := ⟨a ⊓ sInf (Set.image (fun x : Iic a => (x : α)) S), sorry⟩
sSup_le S b hb := sSup_le (α := α) <| fun c' ⟨c, hc, hc'⟩ ↦ hc' ▸ hb c hc
le_sInf S b hb := (le_inf_iff (α := α)).mpr
⟨b.property, le_sInf fun d' ⟨d, hd, hd'⟩ ↦ hd' ▸ hb d hd⟩
le_top := sorry
bot_le := sorry
end Set.Iic
end Mathlib.Order.CompleteLatticeIntervals