Compare commits

...

1 Commits

Author SHA1 Message Date
Leonardo de Moura
3b59c5c51a fix: assertion violation in mkEqProofImpl
This PR fixes an assertion violation in `grind` reported at #12246
This assertion fails when in examples containing heterogenous
equalities with elements of different types (e.g., `Fin n` and `Fin m`) attached to the same
theory solver.

Closes #12246
2026-02-13 16:28:03 -08:00
3 changed files with 53 additions and 3 deletions

View File

@@ -334,7 +334,8 @@ It assumes `a` and `b` are in the same equivalence class.
-/
@[export lean_grind_mk_eq_proof]
def mkEqProofImpl (a b : Expr) : GoalM Expr := do
assert! ( hasSameType a b)
unless ( hasSameType a b) do
throwError "internal `grind` error, `mkEqProof` invoked with terms of different types{indentExpr a}\nhas type{indentExpr (← inferType a)}\nbut{indentExpr b}\nhas type{indentExpr (← inferType b)}"
mkEqProofCore a b (heq := false)
@[export lean_grind_mk_heq_proof]

View File

@@ -1967,7 +1967,10 @@ def SolverExtension.markTerm (ext : SolverExtension σ) (e : Expr) : GoalM Unit
| .nil => return .next id e .nil
| .next id' e' sTerms' =>
if id == id' then
( solverExtensionsRef.get)[id]!.newEq e e'
-- Skip if `e` and `e'` have different types (e.g., they were merged via `HEq` from `cast`).
-- This can happen when we have heterogenous equalities in an equivalence class containing types such as `Fin n` and `Fin m`
if ( pure !root.heqProofs <||> hasSameType e e') then
( solverExtensionsRef.get)[id]!.newEq e e'
return sTerms
else if id < id' then
return .next id e sTerms
@@ -2047,7 +2050,11 @@ where
match p with
| .nil => return ()
| .eq solverId lhs rhs rest =>
( solverExtensionsRef.get)[solverId]!.newEq lhs rhs
-- Skip if `lhs` and `rhs` have different types (e.g., they were merged via `HEq` from `cast`).
-- This can happen when we have heterogenous equalities in an equivalence class containing types such as `Fin n` and `Fin m`
let root getRootENode lhs
if ( pure !root.heqProofs <||> hasSameType lhs rhs) then
( solverExtensionsRef.get)[solverId]!.newEq lhs rhs
go rest
| .diseqs solverId parentSet rest =>
forEachDiseq parentSet (propagateDiseqOf solverId)

View File

@@ -0,0 +1,42 @@
import Std.Do
import Std.Tactic.Do
def Matrix' (α β γ : Type) : Type := α β γ
namespace Matrix'
variable {α : Type} {m n : Nat} {M : Matrix' (Fin m) (Fin n) α}
variable {i i' : Fin m} {j j' : Fin n}
def shuffleRows (M : Matrix' (Fin m) (Fin n) α) (j : Fin n) :
Matrix' (Fin m) (Fin n) α := sorry
def altColSort (M : Matrix' (Fin m) (Fin n) α) :
Matrix' (Fin m) (Fin n) α := Id.run do
let mut M' : Matrix' (Fin m) (Fin n) α := M
for hj : j in [:n] do M' := M'.shuffleRows j, by sorry
return M'
open Std.Do
variable [LE α] [Std.IsLinearOrder α]
set_option mvcgen.warning false
def Monotone' {α : Type} [LE α] (f : Fin n α) : Prop := i j, i j f i f j
attribute [grind =] Fin.le_def Monotone'
theorem altColSort_rowSorted' (hM : i, Monotone' (M i)) (i : Fin m) :
Monotone' (M.altColSort i) := by
generalize h : M.altColSort = x
apply Id.of_wp_run_eq h
mvcgen invariants
| inv1 => cur, M' => ( j : Fin n, j < cur.pos Monotone' (M' · j))
case vc2 => grind
case vc3 => sorry
case vc1 =>
fail_if_success grind -verbose
sorry
end Matrix'