This PR sets up the new integrated test/bench suite. It then migrates all benchmarks and some related tests to the new suite. There's also some documentation and some linting. For now, a lot of the old tests are left alone so this PR doesn't become even larger than it already is. Eventually, all tests should be migrated to the new suite though so there isn't a confusing mix of two systems.
103 lines
3 KiB
Text
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
|