This PR fixes how we determine whether a function parameter is an
instance.
Previously, we relied on binder annotations (e.g., `[Ring A]` vs `{_ :
Ring A}`)
to make this determination. This is unreliable because users
legitimately use
`{..}` binders for class types when the instance is already available
from
context. For example:
```lean
structure OrdSet (α : Type) [Hashable α] [BEq α] where
...
def OrdSet.insert {_ : Hashable α} {_ : BEq α} (s : OrdSet α) (a : α) : OrdSet α :=
...
```
Here, `Hashable` and `BEq` are classes, but the `{..}` binder is
intentional, the
instances come from `OrdSet`'s parameters, so type class resolution is
unnecessary.
The fix checks the parameter's *type* using `isClass?` rather than its
syntax, and
caches this information in `FunInfo`. This affects several subsystems:
- **Discrimination trees**: instance parameters should not be indexed
even if marked with `{..}`
- **Congruence lemma generation**: instances require special treatment
- **`grind` canonicalizer**: must ensure canonical instances
**Potential regressions**: automation may now behave differently in
cases where it
previously misidentified instance parameters. For example, a rewrite
rule in `simp` that was
not firing due to incorrect indexing may now fire.
---------
Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Claude <noreply@anthropic.com>
62 lines
2.1 KiB
Text
62 lines
2.1 KiB
Text
variable {α β γ : Type}
|
||
|
||
structure Equiv (α β : Type) where
|
||
toFun : α → β
|
||
invFun : β → α
|
||
|
||
infixl:25 " ≃ " => Equiv
|
||
|
||
namespace Equiv
|
||
|
||
instance : CoeFun (α ≃ β) (fun _ => α → β) := ⟨toFun⟩
|
||
|
||
@[ext, grind ext] theorem ext {f g : Equiv α β} (H : ∀ x, f x = g x) : f = g := sorry
|
||
|
||
theorem congr_fun {f g : Equiv α β} (h : f = g) (x : α) : f x = g x := by rw [h]
|
||
|
||
def symm (e : α ≃ β) : β ≃ α := ⟨e.invFun, e.toFun⟩
|
||
|
||
def trans (e₁ : α ≃ β) (e₂ : β ≃ γ) : α ≃ γ := ⟨e₂ ∘ e₁, e₁.symm ∘ e₂.symm⟩
|
||
|
||
def sigmaCongrRight {α : Type} {β₁ β₂ : α → Type} (F : ∀ a, β₁ a ≃ β₂ a) : (Σ a, β₁ a) ≃ Σ a, β₂ a where
|
||
toFun a := ⟨a.1, F a.1 a.2⟩
|
||
invFun a := ⟨a.1, (F a.1).symm a.2⟩
|
||
|
||
def sigmaEquivProd (α β : Type) : (Σ _ : α, β) ≃ α × β where
|
||
toFun a := ⟨a.1, a.2⟩
|
||
invFun a := ⟨a.1, a.2⟩
|
||
|
||
end Equiv
|
||
|
||
variable {α₁ β₁ β₂ : Type} (e : α₁ → β₁ ≃ β₂)
|
||
|
||
def prodCongrRight : α₁ × β₁ ≃ α₁ × β₂ where
|
||
toFun ab := ⟨ab.1, e ab.1 ab.2⟩
|
||
invFun ab := ⟨ab.1, (e ab.1).symm ab.2⟩
|
||
|
||
example :
|
||
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
|
||
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
|
||
grind -reducible only [Equiv.congr_fun]
|
||
|
||
example :
|
||
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
|
||
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
|
||
grind -reducible only => finish only [Equiv.congr_fun]
|
||
|
||
example :
|
||
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
|
||
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
|
||
grind -reducible => cases #d592 <;> instantiate only [Equiv.congr_fun]
|
||
|
||
/--
|
||
info: Try these:
|
||
[apply] grind -reducible only [Equiv.congr_fun, #d592]
|
||
[apply] grind -reducible only [Equiv.congr_fun]
|
||
[apply] grind -reducible => cases #d592 <;> instantiate only [Equiv.congr_fun]
|
||
-/
|
||
#guard_msgs in
|
||
example :
|
||
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
|
||
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
|
||
grind? -reducible [Equiv.congr_fun]
|