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.
207 lines
5.9 KiB
Text
207 lines
5.9 KiB
Text
/-!
|
||
# Tests of elabAsElim elaborator and the `elab_as_elim` attribute
|
||
-/
|
||
|
||
-- For debugging:
|
||
-- set_option trace.Elab.app.elab_as_elim true
|
||
|
||
inductive Vec (α : Type u) : Nat → Type u
|
||
| nil : Vec α 0
|
||
| cons : α → Vec α n → Vec α (n+1)
|
||
|
||
def f1 (xs : Vec α n) : Nat :=
|
||
Vec.casesOn xs 0 fun _ _ => 1
|
||
|
||
/-! Under-applied eliminator, and expected type isn't a pi type. -/
|
||
/--
|
||
error: failed to elaborate eliminator, insufficient number of arguments, expected type:
|
||
Nat
|
||
-/
|
||
#guard_msgs in
|
||
def f2 (xs : Vec α n) : Nat :=
|
||
xs.casesOn 0
|
||
|
||
def f3 (x : Nat) : Nat → (Nat → Nat) → Nat :=
|
||
x.casesOn
|
||
|
||
/-! Under-applied eliminator, expected type's binders do not unify with remaining arguments. -/
|
||
/--
|
||
error: failed to elaborate eliminator, insufficient number of arguments, expected type:
|
||
(Nat → Nat) → Nat → Nat
|
||
-/
|
||
#guard_msgs in
|
||
def f3' (x : Nat) : (Nat → Nat) → Nat → Nat :=
|
||
x.casesOn
|
||
|
||
def f4 (xs : List Nat) : xs ≠ [] → xs.length > 0 :=
|
||
xs.casesOn (by intros; contradiction) (by intros; simp +arith)
|
||
|
||
def f5 (xs : List Nat) (h : xs ≠ []) : xs.length > 0 :=
|
||
xs.casesOn (by intros; contradiction) (by intros; simp +arith) h
|
||
|
||
def f6 (x : Nat) :=
|
||
2 * x.casesOn 0 id
|
||
|
||
example : f6 (x+1) = 2*x := rfl
|
||
|
||
/-- error: failed to elaborate eliminator, unused named arguments: [a] -/
|
||
#guard_msgs in
|
||
def f7 (xs : Vec α n) : Nat :=
|
||
xs.casesOn (a := 10) 0
|
||
|
||
def f8 (xs : List Nat) : xs ≠ [] → xs.length > 0 :=
|
||
@List.casesOn _ (fun xs => xs ≠ [] → xs.length > 0) xs (by dsimp; intros; contradiction) (by dsimp; intros; simp +arith)
|
||
|
||
def f5' (xs : List Nat) (h : xs ≠ []) : xs.length > 0 :=
|
||
xs.casesOn (fun h => absurd rfl h) (fun _ _ _ => Nat.zero_lt_succ ..) h
|
||
|
||
example (h₁ : a = b) (h₂ : b = c) : a = c :=
|
||
Eq.rec h₂ h₁.symm
|
||
|
||
@[elab_as_elim] theorem subst {p : (b : α) → a = b → Prop} (h₁ : a = b) (h₂ : p a rfl) : p b h₁ := by
|
||
cases h₁
|
||
assumption
|
||
|
||
example (h₁ : a = b) (h₂ : b = c) : a = c :=
|
||
subst h₁.symm h₂
|
||
|
||
theorem not_or_not : (¬p ∨ ¬q) → ¬(p ∧ q) := λ h ⟨hp, hq⟩ =>
|
||
h.rec (λ h1 => h1 hp) (λ h2 => h2 hq)
|
||
|
||
structure Point where
|
||
x : Nat
|
||
|
||
theorem PointExt_lean4 (p : Point) : forall (q : Point) (h1 : Point.x p = Point.x q), p = q :=
|
||
Point.recOn p <|
|
||
fun z1 q => Point.recOn q $
|
||
fun z2 (hA : Point.x (Point.mk z1) = Point.x (Point.mk z2)) => congrArg Point.mk hA
|
||
|
||
inductive pos_num : Type
|
||
| one : pos_num
|
||
| bit1 : pos_num → pos_num
|
||
| bit0 : pos_num → pos_num
|
||
|
||
inductive num : Type
|
||
| zero : num
|
||
| pos : pos_num → num
|
||
|
||
inductive znum : Type
|
||
| zero : znum
|
||
| pos : pos_num → znum
|
||
| neg : pos_num → znum
|
||
|
||
def pos_num.pred' : pos_num → num
|
||
| one => .zero
|
||
| bit0 n => num.pos (num.casesOn (pred' n) one bit1)
|
||
| bit1 n => num.pos (bit0 n)
|
||
|
||
protected def znum.bit1 : znum → znum
|
||
| zero => pos .one
|
||
| pos n => pos (pos_num.bit1 n)
|
||
| neg n => neg (num.casesOn (pos_num.pred' n) .one pos_num.bit1)
|
||
|
||
example (h : False) : a = c :=
|
||
h.rec
|
||
|
||
example (h : False) : a = c :=
|
||
h.elim
|
||
|
||
noncomputable def f : Nat → Nat :=
|
||
Nat.rec 0 (fun x _ => x)
|
||
|
||
example : ∀ x, x ≥ 0 :=
|
||
Nat.rec (Nat.le_refl 0) (fun _ ih => Nat.le_succ_of_le ih)
|
||
|
||
/-!
|
||
Tests of `@[elab_as_elim]` when the motive is not type correct.
|
||
-/
|
||
|
||
@[elab_as_elim]
|
||
def Foo.induction {P : (α : Type) → Prop} (α : Type) : P α := sorry
|
||
|
||
/--
|
||
error: failed to elaborate eliminator, motive is not type correct:
|
||
fun x => T = T
|
||
-/
|
||
#guard_msgs in
|
||
example {n : Type} {T : n} : T = T := Foo.induction n
|
||
|
||
/--
|
||
error: failed to elaborate eliminator, motive is not type correct:
|
||
fun x => T✝ = T✝
|
||
-/
|
||
#guard_msgs in
|
||
example {n : Type} : {T : n} → T = T := Foo.induction n
|
||
|
||
example {n : Type} : (T : n) → T = T := Foo.induction n
|
||
|
||
-- Disable implicit lambda
|
||
example {n : Type} : {T : n} → T = T := @(Foo.induction n)
|
||
|
||
/-!
|
||
A "motive is not type correct" regression test.
|
||
The `isEmptyElim` was failing due to being under-applied and the named `(α := α)` argument
|
||
having postponed elaboration. This fix is that `α` now elaborates eagerly.
|
||
-/
|
||
|
||
class IsEmpty (α : Sort u) : Prop where
|
||
protected false : α → False
|
||
|
||
@[elab_as_elim]
|
||
def isEmptyElim [IsEmpty α] {p : α → Sort _} (a : α) : p a :=
|
||
(IsEmpty.false a).elim
|
||
|
||
def Set (α : Type u) := α → Prop
|
||
def Set.univ {α : Type _} : Set α := fun _ => True
|
||
instance : Membership α (Set α) := ⟨fun s x => s x⟩
|
||
def Set.pi {α : ι → Type _} (s : Set ι) (t : (i : ι) → Set (α i)) : Set ((i : ι) → α i) := fun f => ∀ i ∈ s, f i ∈ t i
|
||
|
||
example {α : Type u} [IsEmpty α] {β : α → Type v} (x : (a : α) → β a) (s : (i : α) → Set (β i)) :
|
||
x ∈ Set.univ.pi s := isEmptyElim (α := α)
|
||
|
||
-- Simplified version:
|
||
example {α : Type _} [IsEmpty α] :
|
||
id (α → False) := isEmptyElim (α := α)
|
||
|
||
/-!
|
||
From mathlib, regression test. Need to eagerly elaborate the `n ≤ m` argument to deduce `m`
|
||
before computing the motive.
|
||
-/
|
||
|
||
@[elab_as_elim]
|
||
def leRecOn {C : Nat → Sort _} {n : Nat} : ∀ {m}, n ≤ m → (∀ {k}, C k → C (k + 1)) → C n → C m :=
|
||
sorry
|
||
|
||
theorem leRecOn_self {C : Nat → Sort _} {n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
|
||
(leRecOn n.le_refl next x : C n) = x :=
|
||
sorry
|
||
|
||
/-!
|
||
Issue https://github.com/leanprover/lean4/issues/4347
|
||
|
||
`False.rec` has `motive` as an explicit argument.
|
||
-/
|
||
|
||
example (h : False) : Nat := False.rec (fun _ => Nat) h
|
||
example (h : False) : Nat := False.rec _ h
|
||
example (h : False) : Nat := h.rec
|
||
example (h : False) : Nat := h.rec _
|
||
|
||
/-!
|
||
Check that the overapplied arguments given to the eliminator are not permuted.
|
||
In this example, `h0` and `h1` used to be reversed, leading to a kernel typechecking error.
|
||
-/
|
||
example (n : Nat) (h0 : n ≠ 0) (h1 : n ≠ 1) : n - 2 ≠ n - 1 :=
|
||
Nat.recOn n (by simp) (by rintro (_ | _) <;> simp) h0 h1
|
||
|
||
/-!
|
||
Check that eliminators need at least one discriminant
|
||
-/
|
||
|
||
/--
|
||
error: unexpected eliminator resulting type
|
||
p
|
||
-/
|
||
#guard_msgs in
|
||
@[elab_as_elim]
|
||
theorem mySillyEliminator {p : Prop} (h : p) : p := h
|