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.
387 lines
7.5 KiB
Text
387 lines
7.5 KiB
Text
/-!
|
||
# Tests for structure instance notation
|
||
-/
|
||
|
||
-- Make sure defaults pretty print so we can see what they elaborate to.
|
||
set_option pp.structureInstances.defaults true
|
||
|
||
namespace Ex1
|
||
|
||
structure A where
|
||
(x : Nat)
|
||
|
||
structure B extends A where
|
||
(y : Nat := x + 2) (x := y + 1)
|
||
|
||
structure C extends B where
|
||
(z : Nat) (x := z + 10)
|
||
|
||
/-- info: { x := 1 + 1, y := 1 } : B -/
|
||
#guard_msgs in #check { y := 1 : B }
|
||
/-- info: { x := 1 + 10, y := 1 + 10 + 2, z := 1 } : C -/
|
||
#guard_msgs in #check { z := 1 : C }
|
||
/-! Make sure `z` is parsed as an abbreviation: -/
|
||
/-- info: fun z => { x := z + 10, y := z + 10 + 2, z := z } : Nat → C -/
|
||
#guard_msgs in #check fun z : Nat => { z : C }
|
||
|
||
def test1 : B where
|
||
y := 1
|
||
def test2 : C where
|
||
z := 1
|
||
|
||
end Ex1
|
||
|
||
namespace Ex2
|
||
|
||
structure A where
|
||
(x : Nat) (y : Nat)
|
||
|
||
structure B extends A where
|
||
(z : Nat := x + 1) (y := z + x)
|
||
|
||
/-- info: { x := 1, y := 1 + 1 + 1, z := 1 + 1 } : B -/
|
||
#guard_msgs in #check { x := 1 : B }
|
||
|
||
def test1 : B where
|
||
x := 1
|
||
|
||
end Ex2
|
||
|
||
namespace Ex3
|
||
|
||
structure A where
|
||
(x : Nat)
|
||
|
||
structure B extends A where
|
||
(y : Nat := x + 2) (x := y + 1)
|
||
|
||
structure C extends B where
|
||
(z : Nat := 2*y) (x := z + 2) (y := z + 3)
|
||
|
||
-- This first example does not work because the default values at `C` are the only ones considered.
|
||
/--
|
||
error: Fields missing: `y`, `z`
|
||
|
||
Hint: Add missing fields:
|
||
⏎
|
||
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲y̲ ̲:̲=̲ ̲_̲
|
||
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲z̲ ̲:̲=̲ ̲_̲
|
||
---
|
||
info: { x := 1, y := sorry, z := sorry } : C
|
||
-/
|
||
#guard_msgs in #check { x := 1 : C }
|
||
/-- info: { x := 2 * 1 + 2, y := 1, z := 2 * 1 } : C -/
|
||
#guard_msgs in #check { y := 1 : C }
|
||
/-- info: { x := 1 + 2, y := 1 + 3, z := 1 } : C -/
|
||
#guard_msgs in #check { z := 1 : C }
|
||
|
||
-- This first example does not work because the default values at `C` are the only ones considered.
|
||
/-- error: Fields missing: `y`, `z` -/
|
||
#guard_msgs in
|
||
def test1 : C where
|
||
x := 1
|
||
def test2 : C where
|
||
y := 1
|
||
def test3 : C where
|
||
z := 1
|
||
|
||
end Ex3
|
||
|
||
namespace Ex4
|
||
|
||
structure A where
|
||
(x : Nat)
|
||
|
||
structure B extends A where
|
||
(y : Nat := x + 1) (x := y + 1)
|
||
|
||
structure C extends B where
|
||
(z : Nat := 2*y) (x := z + 3)
|
||
|
||
/-- info: { x := 1, y := 1 + 1, z := 2 * (1 + 1) } : C -/
|
||
#guard_msgs in #check { x := 1 : C }
|
||
/-- info: { x := 2 * 1 + 3, y := 1, z := 2 * 1 } : C -/
|
||
#guard_msgs in #check { y := 1 : C }
|
||
/-- info: { x := 1 + 3, y := 1 + 3 + 1, z := 1 } : C -/
|
||
#guard_msgs in #check { z := 1 : C }
|
||
/-- info: { x := 2, y := 2 + 1, z := 1 } : C -/
|
||
#guard_msgs in #check { z := 1, x := 2 : C }
|
||
/-- info: { x := 1 + 1, y := 1 } : B -/
|
||
#guard_msgs in #check { y := 1 : B }
|
||
|
||
def test1 : C where
|
||
x := 1
|
||
def test2 : C where
|
||
y := 1
|
||
def test3 : C where
|
||
z := 1
|
||
def test4 : C where
|
||
z := 1
|
||
x := 2
|
||
def test5 : C where
|
||
y := 1
|
||
|
||
end Ex4
|
||
|
||
/-!
|
||
Binders example
|
||
-/
|
||
structure PosFun where
|
||
f : Nat → Nat
|
||
pos : ∀ n, 0 < f n
|
||
|
||
def p : PosFun :=
|
||
{ f n := n + 1
|
||
pos := by simp }
|
||
|
||
def p_where : PosFun where
|
||
f n := n + 1
|
||
pos := by simp
|
||
|
||
/-!
|
||
Equations
|
||
-/
|
||
def p' : PosFun :=
|
||
{ f
|
||
| 0 => 1
|
||
| n + 1 => n + 1
|
||
pos := by rintro (_|_) <;> simp }
|
||
|
||
def p'_where : PosFun where
|
||
f
|
||
| 0 => 1
|
||
| n + 1 => n + 1
|
||
pos := by rintro (_|_) <;> simp
|
||
|
||
/-!
|
||
Binders and type ascriptions
|
||
-/
|
||
namespace Ex5
|
||
|
||
structure A (α : Type) (β : Type) where
|
||
x : α
|
||
f : β → β
|
||
z : α
|
||
|
||
/-- info: fun z => { x := 1, f := fun n => n + 1, z := z } : Int → A Int Int -/
|
||
#guard_msgs in #check fun z => { x : Int := 1, f n : Int := n + 1, z : A _ _ }
|
||
|
||
def test1 (z : Int) : A Int Int where
|
||
x : Int := 1
|
||
f n : Int := n + 1
|
||
z
|
||
|
||
end Ex5
|
||
|
||
/-!
|
||
Default instances are applied before analyzing default values.
|
||
Without this, `α` would be reported as being a missing field.
|
||
-/
|
||
namespace Ex6
|
||
structure MyStruct where
|
||
{α : Type u}
|
||
{β : Type v}
|
||
a : α
|
||
b : β
|
||
|
||
/-- info: { α := Nat, β := Bool, a := 10, b := true } : MyStruct -/
|
||
#guard_msgs in #check { a := 10, b := true : MyStruct }
|
||
end Ex6
|
||
|
||
/-!
|
||
Make sure we have the Lean 3 behavior, where field projections are unfolded.
|
||
https://github.com/leanprover-community/mathlib4/issues/12129#issuecomment-2056134533
|
||
-/
|
||
namespace Mathlib12129
|
||
|
||
structure Foo where
|
||
toFun : Nat → Nat
|
||
|
||
structure Bar extends Foo where
|
||
prop : toFun 0 = 0
|
||
|
||
/-
|
||
Rather than `(fun x => x) 0 = 0` or `{ toFun := fun x => x }.toFun 0 = 0`
|
||
-/
|
||
/-- trace: ⊢ 0 = 0 -/
|
||
#guard_msgs in
|
||
def bar : Bar where
|
||
toFun x := x
|
||
prop := by
|
||
trace_state
|
||
rfl
|
||
|
||
end Mathlib12129
|
||
|
||
/-!
|
||
Explicit fields must be provided, even if they can be inferred.
|
||
-/
|
||
namespace Ex7
|
||
|
||
structure S where
|
||
n : Nat
|
||
m : Fin n
|
||
|
||
variable (x : Fin 3)
|
||
|
||
/--
|
||
error: Fields missing: `n`
|
||
|
||
Field `n` must be explicitly provided; its synthesized value is
|
||
3
|
||
|
||
Hint: Add missing fields:
|
||
⏎
|
||
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲n̲ ̲:̲=̲ ̲3̲
|
||
---
|
||
info: { n := 3, m := x } : S
|
||
-/
|
||
#guard_msgs in #check { m := x : S }
|
||
|
||
/-- info: { n := 3, m := x } : S -/
|
||
#guard_msgs in #check { n := _, m := x : S }
|
||
|
||
/-- info: { n := 3, m := x } : S -/
|
||
#guard_msgs in #check { m := x, .. : S }
|
||
|
||
/-- info: { n := 3, m := x } : S -/
|
||
#guard_msgs in #check { n := 3, m := x : S }
|
||
|
||
end Ex7
|
||
|
||
/-!
|
||
Diamond inheritance, acquire field values from parent classes.
|
||
https://github.com/leanprover/lean4/issues/6046
|
||
-/
|
||
namespace Issue6046
|
||
set_option structure.strictResolutionOrder true
|
||
|
||
class A
|
||
|
||
class B extends A where
|
||
b : Unit
|
||
|
||
structure B' where
|
||
b : Unit
|
||
|
||
class C extends B', B, A
|
||
|
||
instance : A where
|
||
|
||
instance : B where
|
||
b := ()
|
||
|
||
instance : C where
|
||
|
||
/--
|
||
info: @[implicit_reducible] def Issue6046.instC : C :=
|
||
{ b := B.b }
|
||
-/
|
||
#guard_msgs in #print Issue6046.instC
|
||
|
||
end Issue6046
|
||
|
||
/-!
|
||
Make sure parent fields still work if one parent depends on another.
|
||
-/
|
||
namespace Ex8
|
||
|
||
class A (α : Type) where
|
||
val : α → Nat
|
||
class B (α : Type) [A α] where
|
||
val' : α → Nat
|
||
h : ∃ x : α, A.val x = val' x
|
||
class C (α : Type) extends A α, B α
|
||
|
||
instance : A Nat where
|
||
val := id
|
||
instance : B Nat where
|
||
val' _ := 0
|
||
h := by exists 0
|
||
|
||
/-
|
||
This was "fields missing: 'val'', 'h'" at some point during testing.
|
||
To succeed, this relies on being able to compute the type of the `B` parent,
|
||
which depends on fields of the structure instance being elaborated.
|
||
-/
|
||
/-- info: { toA := instANat, toB := instBNat } : C Nat -/
|
||
#guard_msgs in #check { : C Nat }
|
||
|
||
end Ex8
|
||
|
||
/-!
|
||
Autoparams are elaborated eagerly. Here we see that `a` is printed before `b`.
|
||
-/
|
||
namespace Ex9
|
||
structure A where
|
||
n : Nat := by trace "a"; exact 1
|
||
m : Fin n
|
||
|
||
/--
|
||
trace: a
|
||
---
|
||
trace: b
|
||
-/
|
||
#guard_msgs in
|
||
example : A where
|
||
m := by trace "b"; exact 0
|
||
|
||
end Ex9
|
||
|
||
/-!
|
||
Issues with mixing optParams and autoParams.
|
||
https://github.com/leanprover/lean4/issues/6769
|
||
-/
|
||
namespace Ex6769_1
|
||
class Foo where
|
||
x : Nat := by fail
|
||
|
||
class Bar extends Foo where
|
||
x := 0
|
||
|
||
instance instBar : Bar where
|
||
|
||
/--
|
||
info: @[implicit_reducible] def Ex6769_1.instBar : Bar :=
|
||
{ x := 0 }
|
||
-/
|
||
#guard_msgs in #print instBar
|
||
end Ex6769_1
|
||
|
||
namespace Ex6769_2
|
||
class Foo where
|
||
x : Nat
|
||
hx : x = x
|
||
|
||
class Bar extends Foo where
|
||
hx' : x = x := by rfl
|
||
hx := hx'
|
||
|
||
instance instBar : Bar where
|
||
x := 0
|
||
|
||
/--
|
||
info: @[implicit_reducible] def Ex6769_2.instBar : Bar :=
|
||
{ x := 0, hx := Mathlib12129.bar._proof_1, hx' := Mathlib12129.bar._proof_1 }
|
||
-/
|
||
#guard_msgs in #print instBar
|
||
end Ex6769_2
|
||
|
||
namespace Ex6769_3
|
||
class Foo where
|
||
x : Nat
|
||
hx : x = x
|
||
|
||
class Bar extends Foo where
|
||
hx' : x = x := rfl
|
||
hx := hx'
|
||
|
||
instance instBar : Bar where
|
||
x := 0
|
||
|
||
/--
|
||
info: @[implicit_reducible] def Ex6769_3.instBar : Bar :=
|
||
{ x := 0, hx := Mathlib12129.bar._proof_1, hx' := Mathlib12129.bar._proof_1 }
|
||
-/
|
||
#guard_msgs in #print instBar
|
||
end Ex6769_3
|