lean4-htt/tests/elab/elabAsElim.lean
Garmelon 08eb78a5b2
chore: switch to new test/bench suite (#12590)
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.
2026-02-25 13:51:53 +00:00

207 lines
5.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-!
# 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