lean4-htt/tests/lean/run/isDefEqProjIssue.lean
jrr6 4759506bcf
chore: use note and hint' for message addenda (#8980)
This PR improves the consistency of error message formatting by
rendering addenda of several existing error messages as labeled notes
and hints.
2025-06-27 15:16:01 +00:00

103 lines
3 KiB
Text

import Lean
open Lean
-- We need a structure as this is related to isDefEq problems of the form `e1.proj =?= e2.proj`.
structure Test where
x : Nat
-- We need a data structure with functions that are not meant for reduction purposes.
abbrev Cache := Std.HashMap Nat Test
def Cache.insert (cache : Cache) (key : Nat) (val : Test) : Cache :=
Std.HashMap.insert cache key val
def Cache.find? (cache : Cache) (key : Nat) : Option Test :=
cache[key]?
-- This function just contains a call to a function that we definitely do not want to reduce.
-- To illustrate that the problem is actually noticeable there are multiple implementations provided.
-- Each of these implementations does additional modifications on the cache before looking things up,
-- as one might expect in irl functions.
-- Each version has a lot of additional complexity from the type checkers POV.
def barImpl1 (cache : Cache) (key : Nat) : Test :=
match cache.find? key with
| some val => val
| none => ⟨0⟩
def barImpl2 (cache : Cache) (key : Nat) : Test :=
match (cache.insert key ⟨0⟩).find? key with
| some val => val
| none => ⟨0⟩
def barImpl3 (cache : Cache) (key : Nat) : Test :=
match ((cache.insert key ⟨0⟩).insert 0 ⟨0⟩).find? key with
| some val => val
| none => ⟨0⟩
def barImpl4 (cache : Cache) (key : Nat) : Test :=
match (((cache.insert key ⟨0⟩).insert 0 ⟨0⟩).insert key ⟨key⟩).find? key with
| some val => val
| none => ⟨0⟩
def bar := barImpl4
set_option maxHeartbeats 400 in
def test (c1 : Cache) (key : Nat) : Nat :=
go c1 key
where
go (c1 : Cache) (key : Nat) : Nat :=
let val : Test := bar c1 key
have : val.x = (bar c1 key).x := rfl
val.x
/--
error: (deterministic) timeout at `whnf`, maximum number of heartbeats (400) has been reached
Note: Use `set_option maxHeartbeats <num>` to set the limit.
Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
-/
#guard_msgs in
set_option backward.isDefEq.lazyWhnfCore false in
set_option maxHeartbeats 400 in
def test' (c1 : Cache) (key : Nat) : Nat :=
go c1 key
where
go (c1 : Cache) (key : Nat) : Nat :=
let val : Test := bar c1 key
have : val.x = (bar c1 key).x := rfl
val.x
def ack : Nat → Nat → Nat
| 0, y => y+1
| x+1, 0 => ack x 1
| x+1, y+1 => ack x (ack (x+1) y)
class Foo where
x : Nat
y : Nat
instance f (x : Nat) : Foo :=
{ x, y := ack 10 10 }
instance g (x : Nat) : Foo :=
{ x, y := ack 10 11 }
open Lean Meta
set_option maxHeartbeats 500 in
run_meta do
withLocalDeclD `x (mkConst ``Nat) fun x => do
let lhs := Expr.proj ``Foo 0 <| mkApp (mkConst ``f) x
let rhs := Expr.proj ``Foo 0 <| mkApp (mkConst ``g) x
assert! (← isDefEq lhs rhs)
run_meta do
withLocalDeclD `x (mkConst ``Nat) fun x => do
let lhs := Expr.proj ``Foo 0 <| mkApp (mkConst ``f) x
let rhs := Expr.proj ``Foo 0 <| mkApp (mkConst ``g) x
match Kernel.isDefEq (← getEnv) {} lhs rhs with
| .ok b => assert! b
| .error _ => throwError "failed"
example : (f x).1 = (g x).1 :=
rfl