mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-19 03:14:08 +00:00
Compare commits
19 Commits
array_for_
...
structInst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57cd1368c1 | ||
|
|
9a85433477 | ||
|
|
4616c0ac3e | ||
|
|
e55b681774 | ||
|
|
63132105ba | ||
|
|
350b36411c | ||
|
|
1c30c76e72 | ||
|
|
d5adadc00e | ||
|
|
f08805e5c4 | ||
|
|
256b49bda9 | ||
|
|
28cf146d00 | ||
|
|
970261b1e1 | ||
|
|
6b811f8c92 | ||
|
|
f721f94045 | ||
|
|
86524d5c23 | ||
|
|
f18d9e04bc | ||
|
|
fa33423c84 | ||
|
|
1315266dd3 | ||
|
|
b1e52f1475 |
2
.github/workflows/pr-body.yml
vendored
2
.github/workflows/pr-body.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Check PR body for changelog convention
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, edited, labeled, converted_to_draft, ready_for_review]
|
||||
|
||||
@@ -9,6 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check PR body
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
|
||||
@@ -1922,12 +1922,12 @@ represents an element of `Squash α` the same as `α` itself
|
||||
`Squash.lift` will extract a value in any subsingleton `β` from a function on `α`,
|
||||
while `Nonempty.rec` can only do the same when `β` is a proposition.
|
||||
-/
|
||||
def Squash (α : Type u) := Quot (fun (_ _ : α) => True)
|
||||
def Squash (α : Sort u) := Quot (fun (_ _ : α) => True)
|
||||
|
||||
/-- The canonical quotient map into `Squash α`. -/
|
||||
def Squash.mk {α : Type u} (x : α) : Squash α := Quot.mk _ x
|
||||
def Squash.mk {α : Sort u} (x : α) : Squash α := Quot.mk _ x
|
||||
|
||||
theorem Squash.ind {α : Type u} {motive : Squash α → Prop} (h : ∀ (a : α), motive (Squash.mk a)) : ∀ (q : Squash α), motive q :=
|
||||
theorem Squash.ind {α : Sort u} {motive : Squash α → Prop} (h : ∀ (a : α), motive (Squash.mk a)) : ∀ (q : Squash α), motive q :=
|
||||
Quot.ind h
|
||||
|
||||
/-- If `β` is a subsingleton, then a function `α → β` lifts to `Squash α → β`. -/
|
||||
|
||||
@@ -15,15 +15,6 @@ structure Subarray (α : Type u) where
|
||||
start_le_stop : start ≤ stop
|
||||
stop_le_array_size : stop ≤ array.size
|
||||
|
||||
@[deprecated Subarray.array (since := "2024-04-13")]
|
||||
abbrev Subarray.as (s : Subarray α) : Array α := s.array
|
||||
|
||||
@[deprecated Subarray.start_le_stop (since := "2024-04-13")]
|
||||
theorem Subarray.h₁ (s : Subarray α) : s.start ≤ s.stop := s.start_le_stop
|
||||
|
||||
@[deprecated Subarray.stop_le_array_size (since := "2024-04-13")]
|
||||
theorem Subarray.h₂ (s : Subarray α) : s.stop ≤ s.array.size := s.stop_le_array_size
|
||||
|
||||
namespace Subarray
|
||||
|
||||
def size (s : Subarray α) : Nat :=
|
||||
|
||||
@@ -29,9 +29,6 @@ section Nat
|
||||
|
||||
instance natCastInst : NatCast (BitVec w) := ⟨BitVec.ofNat w⟩
|
||||
|
||||
@[deprecated isLt (since := "2024-03-12")]
|
||||
theorem toNat_lt (x : BitVec n) : x.toNat < 2^n := x.isLt
|
||||
|
||||
/-- Theorem for normalizing the bit vector literal representation. -/
|
||||
-- TODO: This needs more usage data to assess which direction the simp should go.
|
||||
@[simp, bv_toNat] theorem ofNat_eq_ofNat : @OfNat.ofNat (BitVec n) i _ = .ofNat n i := rfl
|
||||
|
||||
@@ -642,7 +642,7 @@ theorem pred_add_one (i : Fin (n + 2)) (h : (i : Nat) < n + 1) :
|
||||
ext
|
||||
simp
|
||||
|
||||
@[simp] theorem subNat_one_succ (i : Fin (n + 1)) (h : 1 ≤ ↑i) : (subNat 1 i h).succ = i := by
|
||||
@[simp] theorem subNat_one_succ (i : Fin (n + 1)) (h : 1 ≤ (i : Nat)) : (subNat 1 i h).succ = i := by
|
||||
ext
|
||||
simp
|
||||
omega
|
||||
|
||||
@@ -52,25 +52,23 @@ def Poly.denote (ctx : Context) (p : Poly) : Nat :=
|
||||
| [] => 0
|
||||
| (k, v) :: p => Nat.add (Nat.mul k (v.denote ctx)) (denote ctx p)
|
||||
|
||||
def Poly.insertSorted (k : Nat) (v : Var) (p : Poly) : Poly :=
|
||||
def Poly.insert (k : Nat) (v : Var) (p : Poly) : Poly :=
|
||||
match p with
|
||||
| [] => [(k, v)]
|
||||
| (k', v') :: p => bif Nat.blt v v' then (k, v) :: (k', v') :: p else (k', v') :: insertSorted k v p
|
||||
| (k', v') :: p =>
|
||||
bif Nat.blt v v' then
|
||||
(k, v) :: (k', v') :: p
|
||||
else bif Nat.beq v v' then
|
||||
(k + k', v') :: p
|
||||
else
|
||||
(k', v') :: insert k v p
|
||||
|
||||
def Poly.sort (p : Poly) : Poly :=
|
||||
let rec go (p : Poly) (r : Poly) : Poly :=
|
||||
def Poly.norm (p : Poly) : Poly := go p []
|
||||
where
|
||||
go (p : Poly) (r : Poly) : Poly :=
|
||||
match p with
|
||||
| [] => r
|
||||
| (k, v) :: p => go p (r.insertSorted k v)
|
||||
go p []
|
||||
|
||||
def Poly.fuse (p : Poly) : Poly :=
|
||||
match p with
|
||||
| [] => []
|
||||
| (k, v) :: p =>
|
||||
match fuse p with
|
||||
| [] => [(k, v)]
|
||||
| (k', v') :: p' => bif v == v' then (Nat.add k k', v)::p' else (k, v) :: (k', v') :: p'
|
||||
| (k, v) :: p => go p (r.insert k v)
|
||||
|
||||
def Poly.mul (k : Nat) (p : Poly) : Poly :=
|
||||
bif k == 0 then
|
||||
@@ -146,15 +144,17 @@ def Poly.combineAux (fuel : Nat) (p₁ p₂ : Poly) : Poly :=
|
||||
def Poly.combine (p₁ p₂ : Poly) : Poly :=
|
||||
combineAux hugeFuel p₁ p₂
|
||||
|
||||
def Expr.toPoly : Expr → Poly
|
||||
| Expr.num k => bif k == 0 then [] else [ (k, fixedVar) ]
|
||||
| Expr.var i => [(1, i)]
|
||||
| Expr.add a b => a.toPoly ++ b.toPoly
|
||||
| Expr.mulL k a => a.toPoly.mul k
|
||||
| Expr.mulR a k => a.toPoly.mul k
|
||||
|
||||
def Poly.norm (p : Poly) : Poly :=
|
||||
p.sort.fuse
|
||||
def Expr.toPoly (e : Expr) :=
|
||||
go 1 e []
|
||||
where
|
||||
-- Implementation note: This assembles the result using difference lists
|
||||
-- to avoid `++` on lists.
|
||||
go (coeff : Nat) : Expr → (Poly → Poly)
|
||||
| Expr.num k => bif k == 0 then id else ((coeff * k, fixedVar) :: ·)
|
||||
| Expr.var i => ((coeff, i) :: ·)
|
||||
| Expr.add a b => go coeff a ∘ go coeff b
|
||||
| Expr.mulL k a
|
||||
| Expr.mulR a k => bif k == 0 then id else go (coeff * k) a
|
||||
|
||||
def Expr.toNormPoly (e : Expr) : Poly :=
|
||||
e.toPoly.norm
|
||||
@@ -201,7 +201,7 @@ def PolyCnstr.denote (ctx : Context) (c : PolyCnstr) : Prop :=
|
||||
Poly.denote_le ctx (c.lhs, c.rhs)
|
||||
|
||||
def PolyCnstr.norm (c : PolyCnstr) : PolyCnstr :=
|
||||
let (lhs, rhs) := Poly.cancel c.lhs.sort.fuse c.rhs.sort.fuse
|
||||
let (lhs, rhs) := Poly.cancel c.lhs.norm c.rhs.norm
|
||||
{ eq := c.eq, lhs, rhs }
|
||||
|
||||
def PolyCnstr.isUnsat (c : PolyCnstr) : Bool :=
|
||||
@@ -268,24 +268,32 @@ def PolyCnstr.toExpr (c : PolyCnstr) : ExprCnstr :=
|
||||
{ c with lhs := c.lhs.toExpr, rhs := c.rhs.toExpr }
|
||||
|
||||
attribute [local simp] Nat.add_comm Nat.add_assoc Nat.add_left_comm Nat.right_distrib Nat.left_distrib Nat.mul_assoc Nat.mul_comm
|
||||
attribute [local simp] Poly.denote Expr.denote Poly.insertSorted Poly.sort Poly.sort.go Poly.fuse Poly.cancelAux
|
||||
attribute [local simp] Poly.denote Expr.denote Poly.insert Poly.norm Poly.norm.go Poly.cancelAux
|
||||
attribute [local simp] Poly.mul Poly.mul.go
|
||||
|
||||
theorem Poly.denote_insertSorted (ctx : Context) (k : Nat) (v : Var) (p : Poly) : (p.insertSorted k v).denote ctx = p.denote ctx + k * v.denote ctx := by
|
||||
theorem Poly.denote_insert (ctx : Context) (k : Nat) (v : Var) (p : Poly) :
|
||||
(p.insert k v).denote ctx = p.denote ctx + k * v.denote ctx := by
|
||||
match p with
|
||||
| [] => simp
|
||||
| (k', v') :: p => by_cases h : Nat.blt v v' <;> simp [h, denote_insertSorted]
|
||||
| (k', v') :: p =>
|
||||
by_cases h₁ : Nat.blt v v'
|
||||
· simp [h₁]
|
||||
· by_cases h₂ : Nat.beq v v'
|
||||
· simp only [insert, h₁, h₂, cond_false, cond_true]
|
||||
simp [Nat.eq_of_beq_eq_true h₂]
|
||||
· simp only [insert, h₁, h₂, cond_false, cond_true]
|
||||
simp [denote_insert]
|
||||
|
||||
attribute [local simp] Poly.denote_insertSorted
|
||||
attribute [local simp] Poly.denote_insert
|
||||
|
||||
theorem Poly.denote_sort_go (ctx : Context) (p : Poly) (r : Poly) : (sort.go p r).denote ctx = p.denote ctx + r.denote ctx := by
|
||||
theorem Poly.denote_norm_go (ctx : Context) (p : Poly) (r : Poly) : (norm.go p r).denote ctx = p.denote ctx + r.denote ctx := by
|
||||
match p with
|
||||
| [] => simp
|
||||
| (k, v):: p => simp [denote_sort_go]
|
||||
| (k, v):: p => simp [denote_norm_go]
|
||||
|
||||
attribute [local simp] Poly.denote_sort_go
|
||||
attribute [local simp] Poly.denote_norm_go
|
||||
|
||||
theorem Poly.denote_sort (ctx : Context) (m : Poly) : m.sort.denote ctx = m.denote ctx := by
|
||||
theorem Poly.denote_sort (ctx : Context) (m : Poly) : m.norm.denote ctx = m.denote ctx := by
|
||||
simp
|
||||
|
||||
attribute [local simp] Poly.denote_sort
|
||||
@@ -316,18 +324,6 @@ theorem Poly.denote_reverse (ctx : Context) (p : Poly) : denote ctx (List.revers
|
||||
|
||||
attribute [local simp] Poly.denote_reverse
|
||||
|
||||
theorem Poly.denote_fuse (ctx : Context) (p : Poly) : p.fuse.denote ctx = p.denote ctx := by
|
||||
match p with
|
||||
| [] => rfl
|
||||
| (k, v) :: p =>
|
||||
have ih := denote_fuse ctx p
|
||||
simp
|
||||
split
|
||||
case _ h => simp [← ih, h]
|
||||
case _ k' v' p' h => by_cases he : v == v' <;> simp [he, ← ih, h]; rw [eq_of_beq he]
|
||||
|
||||
attribute [local simp] Poly.denote_fuse
|
||||
|
||||
theorem Poly.denote_mul (ctx : Context) (k : Nat) (p : Poly) : (p.mul k).denote ctx = k * p.denote ctx := by
|
||||
simp
|
||||
by_cases h : k == 0 <;> simp [h]; simp [eq_of_beq h]
|
||||
@@ -516,13 +512,25 @@ theorem Poly.denote_combine (ctx : Context) (p₁ p₂ : Poly) : (p₁.combine p
|
||||
|
||||
attribute [local simp] Poly.denote_combine
|
||||
|
||||
theorem Expr.denote_toPoly_go (ctx : Context) (e : Expr) :
|
||||
(toPoly.go k e p).denote ctx = k * e.denote ctx + p.denote ctx := by
|
||||
induction k, e using Expr.toPoly.go.induct generalizing p with
|
||||
| case1 k k' =>
|
||||
simp only [toPoly.go]
|
||||
by_cases h : k' == 0
|
||||
· simp [h, eq_of_beq h]
|
||||
· simp [h, Var.denote]
|
||||
| case2 k i => simp [toPoly.go]
|
||||
| case3 k a b iha ihb => simp [toPoly.go, iha, ihb]
|
||||
| case4 k k' a ih
|
||||
| case5 k a k' ih =>
|
||||
simp only [toPoly.go, denote, mul_eq]
|
||||
by_cases h : k' == 0
|
||||
· simp [h, eq_of_beq h]
|
||||
· simp [h, cond_false, ih, Nat.mul_assoc]
|
||||
|
||||
theorem Expr.denote_toPoly (ctx : Context) (e : Expr) : e.toPoly.denote ctx = e.denote ctx := by
|
||||
induction e with
|
||||
| num k => by_cases h : k == 0 <;> simp [toPoly, h, Var.denote]; simp [eq_of_beq h]
|
||||
| var i => simp [toPoly]
|
||||
| add a b iha ihb => simp [toPoly, iha, ihb]
|
||||
| mulL k a ih => simp [toPoly, ih, -Poly.mul]
|
||||
| mulR k a ih => simp [toPoly, ih, -Poly.mul]
|
||||
simp [toPoly, Expr.denote_toPoly_go]
|
||||
|
||||
attribute [local simp] Expr.denote_toPoly
|
||||
|
||||
@@ -554,8 +562,8 @@ theorem ExprCnstr.denote_toPoly (ctx : Context) (c : ExprCnstr) : c.toPoly.denot
|
||||
cases c; rename_i eq lhs rhs
|
||||
simp [ExprCnstr.denote, PolyCnstr.denote, ExprCnstr.toPoly];
|
||||
by_cases h : eq = true <;> simp [h]
|
||||
· simp [Poly.denote_eq, Expr.toPoly]
|
||||
· simp [Poly.denote_le, Expr.toPoly]
|
||||
· simp [Poly.denote_eq]
|
||||
· simp [Poly.denote_le]
|
||||
|
||||
attribute [local simp] ExprCnstr.denote_toPoly
|
||||
|
||||
|
||||
@@ -16,10 +16,6 @@ def getM [Alternative m] : Option α → m α
|
||||
| none => failure
|
||||
| some a => pure a
|
||||
|
||||
@[deprecated getM (since := "2024-04-17")]
|
||||
-- `[Monad m]` is not needed here.
|
||||
def toMonad [Monad m] [Alternative m] : Option α → m α := getM
|
||||
|
||||
/-- Returns `true` on `some x` and `false` on `none`. -/
|
||||
@[inline] def isSome : Option α → Bool
|
||||
| some _ => true
|
||||
@@ -28,8 +24,6 @@ def toMonad [Monad m] [Alternative m] : Option α → m α := getM
|
||||
@[simp] theorem isSome_none : @isSome α none = false := rfl
|
||||
@[simp] theorem isSome_some : isSome (some a) = true := rfl
|
||||
|
||||
@[deprecated isSome (since := "2024-04-17"), inline] def toBool : Option α → Bool := isSome
|
||||
|
||||
/-- Returns `true` on `none` and `false` on `some x`. -/
|
||||
@[inline] def isNone : Option α → Bool
|
||||
| some _ => false
|
||||
|
||||
@@ -148,6 +148,9 @@ instance : ShiftLeft Int8 := ⟨Int8.shiftLeft⟩
|
||||
instance : ShiftRight Int8 := ⟨Int8.shiftRight⟩
|
||||
instance : DecidableEq Int8 := Int8.decEq
|
||||
|
||||
@[extern "lean_bool_to_int8"]
|
||||
def Bool.toInt8 (b : Bool) : Int8 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_int8_dec_lt"]
|
||||
def Int8.decLt (a b : Int8) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec.slt b.toBitVec))
|
||||
@@ -249,6 +252,9 @@ instance : ShiftLeft Int16 := ⟨Int16.shiftLeft⟩
|
||||
instance : ShiftRight Int16 := ⟨Int16.shiftRight⟩
|
||||
instance : DecidableEq Int16 := Int16.decEq
|
||||
|
||||
@[extern "lean_bool_to_int16"]
|
||||
def Bool.toInt16 (b : Bool) : Int16 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_int16_dec_lt"]
|
||||
def Int16.decLt (a b : Int16) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec.slt b.toBitVec))
|
||||
@@ -354,6 +360,9 @@ instance : ShiftLeft Int32 := ⟨Int32.shiftLeft⟩
|
||||
instance : ShiftRight Int32 := ⟨Int32.shiftRight⟩
|
||||
instance : DecidableEq Int32 := Int32.decEq
|
||||
|
||||
@[extern "lean_bool_to_int32"]
|
||||
def Bool.toInt32 (b : Bool) : Int32 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_int32_dec_lt"]
|
||||
def Int32.decLt (a b : Int32) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec.slt b.toBitVec))
|
||||
@@ -463,6 +472,9 @@ instance : ShiftLeft Int64 := ⟨Int64.shiftLeft⟩
|
||||
instance : ShiftRight Int64 := ⟨Int64.shiftRight⟩
|
||||
instance : DecidableEq Int64 := Int64.decEq
|
||||
|
||||
@[extern "lean_bool_to_int64"]
|
||||
def Bool.toInt64 (b : Bool) : Int64 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_int64_dec_lt"]
|
||||
def Int64.decLt (a b : Int64) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec.slt b.toBitVec))
|
||||
@@ -574,6 +586,9 @@ instance : ShiftLeft ISize := ⟨ISize.shiftLeft⟩
|
||||
instance : ShiftRight ISize := ⟨ISize.shiftRight⟩
|
||||
instance : DecidableEq ISize := ISize.decEq
|
||||
|
||||
@[extern "lean_bool_to_isize"]
|
||||
def Bool.toISize (b : Bool) : ISize := if b then 1 else 0
|
||||
|
||||
@[extern "lean_isize_dec_lt"]
|
||||
def ISize.decLt (a b : ISize) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec.slt b.toBitVec))
|
||||
|
||||
@@ -514,9 +514,6 @@ instance : Inhabited String := ⟨""⟩
|
||||
|
||||
instance : Append String := ⟨String.append⟩
|
||||
|
||||
@[deprecated push (since := "2024-04-06")]
|
||||
def str : String → Char → String := push
|
||||
|
||||
@[inline] def pushn (s : String) (c : Char) (n : Nat) : String :=
|
||||
n.repeat (fun s => s.push c) s
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ instance : Xor UInt8 := ⟨UInt8.xor⟩
|
||||
instance : ShiftLeft UInt8 := ⟨UInt8.shiftLeft⟩
|
||||
instance : ShiftRight UInt8 := ⟨UInt8.shiftRight⟩
|
||||
|
||||
@[extern "lean_bool_to_uint8"]
|
||||
def Bool.toUInt8 (b : Bool) : UInt8 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_uint8_dec_lt"]
|
||||
def UInt8.decLt (a b : UInt8) : Decidable (a < b) :=
|
||||
inferInstanceAs (Decidable (a.toBitVec < b.toBitVec))
|
||||
@@ -116,6 +119,9 @@ instance : Xor UInt16 := ⟨UInt16.xor⟩
|
||||
instance : ShiftLeft UInt16 := ⟨UInt16.shiftLeft⟩
|
||||
instance : ShiftRight UInt16 := ⟨UInt16.shiftRight⟩
|
||||
|
||||
@[extern "lean_bool_to_uint16"]
|
||||
def Bool.toUInt16 (b : Bool) : UInt16 := if b then 1 else 0
|
||||
|
||||
set_option bootstrap.genMatcherCode false in
|
||||
@[extern "lean_uint16_dec_lt"]
|
||||
def UInt16.decLt (a b : UInt16) : Decidable (a < b) :=
|
||||
@@ -174,6 +180,9 @@ instance : Xor UInt32 := ⟨UInt32.xor⟩
|
||||
instance : ShiftLeft UInt32 := ⟨UInt32.shiftLeft⟩
|
||||
instance : ShiftRight UInt32 := ⟨UInt32.shiftRight⟩
|
||||
|
||||
@[extern "lean_bool_to_uint32"]
|
||||
def Bool.toUInt32 (b : Bool) : UInt32 := if b then 1 else 0
|
||||
|
||||
@[extern "lean_uint64_add"]
|
||||
def UInt64.add (a b : UInt64) : UInt64 := ⟨a.toBitVec + b.toBitVec⟩
|
||||
@[extern "lean_uint64_sub"]
|
||||
@@ -278,5 +287,8 @@ instance : Xor USize := ⟨USize.xor⟩
|
||||
instance : ShiftLeft USize := ⟨USize.shiftLeft⟩
|
||||
instance : ShiftRight USize := ⟨USize.shiftRight⟩
|
||||
|
||||
@[extern "lean_bool_to_usize"]
|
||||
def Bool.toUSize (b : Bool) : USize := if b then 1 else 0
|
||||
|
||||
instance : Max USize := maxOfLe
|
||||
instance : Min USize := minOfLe
|
||||
|
||||
@@ -466,7 +466,7 @@ hypotheses or the goal. It can have one of the forms:
|
||||
* `at h₁ h₂ ⊢`: target the hypotheses `h₁` and `h₂`, and the goal
|
||||
* `at *`: target all hypotheses and the goal
|
||||
-/
|
||||
syntax location := withPosition(" at" (locationWildcard <|> locationHyp))
|
||||
syntax location := withPosition(ppGroup(" at" (locationWildcard <|> locationHyp)))
|
||||
|
||||
/--
|
||||
* `change tgt'` will change the goal from `tgt` to `tgt'`,
|
||||
|
||||
@@ -33,6 +33,16 @@ def find? (m : NameMap α) (n : Name) : Option α := RBMap.find? m n
|
||||
instance : ForIn m (NameMap α) (Name × α) :=
|
||||
inferInstanceAs (ForIn _ (RBMap ..) ..)
|
||||
|
||||
/-- `filter f m` returns the `NameMap` consisting of all
|
||||
"`key`/`val`"-pairs in `m` where `f key val` returns `true`. -/
|
||||
def filter (f : Name → α → Bool) (m : NameMap α) : NameMap α := RBMap.filter f m
|
||||
|
||||
/-- `filterMap f m` filters an `NameMap` and simultaneously modifies the filtered values.
|
||||
|
||||
It takes a function `f : Name → α → Option β` and applies `f name` to the value with key `name`.
|
||||
The resulting entries with non-`none` value are collected to form the output `NameMap`. -/
|
||||
def filterMap (f : Name → α → Option β) (m : NameMap α) : NameMap β := RBMap.filterMap f m
|
||||
|
||||
end NameMap
|
||||
|
||||
def NameSet := RBTree Name Name.quickCmp
|
||||
@@ -53,6 +63,9 @@ def append (s t : NameSet) : NameSet :=
|
||||
instance : Append NameSet where
|
||||
append := NameSet.append
|
||||
|
||||
/-- `filter f s` returns the `NameSet` consisting of all `x` in `s` where `f x` returns `true`. -/
|
||||
def filter (f : Name → Bool) (s : NameSet) : NameSet := RBTree.filter f s
|
||||
|
||||
end NameSet
|
||||
|
||||
def NameSSet := SSet Name
|
||||
@@ -73,6 +86,9 @@ instance : EmptyCollection NameHashSet := ⟨empty⟩
|
||||
instance : Inhabited NameHashSet := ⟨{}⟩
|
||||
def insert (s : NameHashSet) (n : Name) := Std.HashSet.insert s n
|
||||
def contains (s : NameHashSet) (n : Name) : Bool := Std.HashSet.contains s n
|
||||
|
||||
/-- `filter f s` returns the `NameHashSet` consisting of all `x` in `s` where `f x` returns `true`. -/
|
||||
def filter (f : Name → Bool) (s : NameHashSet) : NameHashSet := Std.HashSet.filter f s
|
||||
end NameHashSet
|
||||
|
||||
def MacroScopesView.isPrefixOf (v₁ v₂ : MacroScopesView) : Bool :=
|
||||
|
||||
@@ -404,6 +404,24 @@ def intersectBy {γ : Type v₁} {δ : Type v₂} (mergeFn : α → β → γ
|
||||
| some b₂ => acc.insert a <| mergeFn a b₁ b₂
|
||||
| none => acc
|
||||
|
||||
/--
|
||||
`filter f m` returns the `RBMap` consisting of all
|
||||
"`key`/`val`"-pairs in `m` where `f key val` returns `true`.
|
||||
-/
|
||||
def filter (f : α → β → Bool) (m : RBMap α β cmp) : RBMap α β cmp :=
|
||||
m.fold (fun r k v => if f k v then r.insert k v else r) {}
|
||||
|
||||
/--
|
||||
`filterMap f m` filters an `RBMap` and simultaneously modifies the filtered values.
|
||||
|
||||
It takes a function `f : α → β → Option γ` and applies `f k v` to the value with key `k`.
|
||||
The resulting entries with non-`none` value are collected to form the output `RBMap`.
|
||||
-/
|
||||
def filterMap (f : α → β → Option γ) (m : RBMap α β cmp) : RBMap α γ cmp :=
|
||||
m.fold (fun r k v => match f k v with
|
||||
| none => r
|
||||
| some b => r.insert k b) {}
|
||||
|
||||
end RBMap
|
||||
|
||||
def rbmapOf {α : Type u} {β : Type v} (l : List (α × β)) (cmp : α → α → Ordering) : RBMap α β cmp :=
|
||||
|
||||
@@ -114,6 +114,13 @@ def union (t₁ t₂ : RBTree α cmp) : RBTree α cmp :=
|
||||
def diff (t₁ t₂ : RBTree α cmp) : RBTree α cmp :=
|
||||
t₂.fold .erase t₁
|
||||
|
||||
/--
|
||||
`filter f m` returns the `RBTree` consisting of all
|
||||
`x` in `m` where `f x` returns `true`.
|
||||
-/
|
||||
def filter (f : α → Bool) (m : RBTree α cmp) : RBTree α cmp :=
|
||||
RBMap.filter (fun a _ => f a) m
|
||||
|
||||
end RBTree
|
||||
|
||||
def rbtreeOf {α : Type u} (l : List α) (cmp : α → α → Ordering) : RBTree α cmp :=
|
||||
|
||||
@@ -214,7 +214,7 @@ private def addTraceAsMessagesCore (ctx : Context) (log : MessageLog) (traceStat
|
||||
let mut log := log
|
||||
let traces' := traces.toArray.qsort fun ((a, _), _) ((b, _), _) => a < b
|
||||
for ((pos, endPos), traceMsg) in traces' do
|
||||
let data := .tagged `_traceMsg <| .joinSep traceMsg.toList "\n"
|
||||
let data := .tagged `trace <| .joinSep traceMsg.toList "\n"
|
||||
log := log.add <| mkMessageCore ctx.fileName ctx.fileMap data .information pos endPos
|
||||
return log
|
||||
|
||||
|
||||
@@ -50,7 +50,9 @@ private partial def mkProof (declName : Name) (type : Expr) : MetaM Expr := do
|
||||
go mvarId
|
||||
else if let some mvarId ← whnfReducibleLHS? mvarId then
|
||||
go mvarId
|
||||
else match (← simpTargetStar mvarId { config.dsimp := false } (simprocs := {})).1 with
|
||||
else
|
||||
let ctx ← Simp.mkContext (config := { dsimp := false })
|
||||
match (← simpTargetStar mvarId ctx (simprocs := {})).1 with
|
||||
| TacticResultCNM.closed => return ()
|
||||
| TacticResultCNM.modified mvarId => go mvarId
|
||||
| TacticResultCNM.noChange =>
|
||||
|
||||
@@ -45,7 +45,9 @@ where
|
||||
go mvarId
|
||||
else if let some mvarId ← simpIf? mvarId then
|
||||
go mvarId
|
||||
else match (← simpTargetStar mvarId {} (simprocs := {})).1 with
|
||||
else
|
||||
let ctx ← Simp.mkContext
|
||||
match (← simpTargetStar mvarId ctx (simprocs := {})).1 with
|
||||
| TacticResultCNM.closed => return ()
|
||||
| TacticResultCNM.modified mvarId => go mvarId
|
||||
| TacticResultCNM.noChange =>
|
||||
|
||||
@@ -57,7 +57,9 @@ private partial def mkProof (declName : Name) (type : Expr) : MetaM Expr := do
|
||||
go mvarId
|
||||
else if let some mvarId ← whnfReducibleLHS? mvarId then
|
||||
go mvarId
|
||||
else match (← simpTargetStar mvarId { config.dsimp := false } (simprocs := {})).1 with
|
||||
else
|
||||
let ctx ← Simp.mkContext (config := { dsimp := false })
|
||||
match (← simpTargetStar mvarId ctx (simprocs := {})).1 with
|
||||
| TacticResultCNM.closed => return ()
|
||||
| TacticResultCNM.modified mvarId => go mvarId
|
||||
| TacticResultCNM.noChange =>
|
||||
|
||||
@@ -227,7 +227,7 @@ def mkFix (preDef : PreDefinition) (prefixArgs : Array Expr) (argsPacker : ArgsP
|
||||
-- decreasing goals when the function has only one non fixed argument.
|
||||
-- This renaming is irrelevant if the function has multiple non fixed arguments. See `process*` functions above.
|
||||
let lctx := (← getLCtx).setUserName x.fvarId! varName
|
||||
withTheReader Meta.Context (fun ctx => { ctx with lctx }) do
|
||||
withLCtx' lctx do
|
||||
let F := xs[1]!
|
||||
let val := preDef.value.beta (prefixArgs.push x)
|
||||
let val ← processSumCasesOn x F val fun x F val => do
|
||||
|
||||
@@ -166,7 +166,7 @@ def mayOmitSizeOf (is_mutual : Bool) (args : Array Expr) (x : Expr) : MetaM Bool
|
||||
def withUserNames {α} (xs : Array Expr) (ns : Array Name) (k : MetaM α) : MetaM α := do
|
||||
let mut lctx ← getLCtx
|
||||
for x in xs, n in ns do lctx := lctx.setUserName x.fvarId! n
|
||||
withTheReader Meta.Context (fun ctx => { ctx with lctx }) k
|
||||
withLCtx' lctx k
|
||||
|
||||
/-- Create one measure for each (eligible) parameter of the given predefintion. -/
|
||||
def simpleMeasures (preDefs : Array PreDefinition) (fixedPrefixSize : Nat)
|
||||
|
||||
@@ -900,8 +900,16 @@ partial def tryToSynthesizeDefault (structs : Array Struct) (allStructNames : Ar
|
||||
| none =>
|
||||
let mvarDecl ← getMVarDecl mvarId
|
||||
let val ← ensureHasType mvarDecl.type val
|
||||
mvarId.assign val
|
||||
return true
|
||||
/-
|
||||
We must use `checkedAssign` here to ensure we do not create a cyclic
|
||||
assignment. See #3150.
|
||||
This can happen when there are holes in the the fields the default value
|
||||
depends on.
|
||||
Possible improvement: create a new `_` instead of returning `false` when
|
||||
`checkedAssign` fails. Reason: the field will not be needed after the
|
||||
other `_` are resolved by the user.
|
||||
-/
|
||||
mvarId.checkedAssign val
|
||||
| _ => loop (i+1) dist
|
||||
else
|
||||
return false
|
||||
|
||||
@@ -198,11 +198,10 @@ def rewriteRulesPass (maxSteps : Nat) : Pass where
|
||||
let sevalThms ← getSEvalTheorems
|
||||
let sevalSimprocs ← Simp.getSEvalSimprocs
|
||||
|
||||
let simpCtx : Simp.Context := {
|
||||
config := { failIfUnchanged := false, zetaDelta := true, maxSteps }
|
||||
simpTheorems := #[bvThms, sevalThms]
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
}
|
||||
let simpCtx ← Simp.mkContext
|
||||
(config := { failIfUnchanged := false, zetaDelta := true, maxSteps })
|
||||
(simpTheorems := #[bvThms, sevalThms])
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
|
||||
let hyps ← goal.getNondepPropHyps
|
||||
let ⟨result?, _⟩ ← simpGoal goal
|
||||
@@ -283,11 +282,10 @@ def embeddedConstraintPass (maxSteps : Nat) : Pass where
|
||||
|
||||
let goal ← goal.tryClearMany duplicates
|
||||
|
||||
let simpCtx : Simp.Context := {
|
||||
config := { failIfUnchanged := false, maxSteps }
|
||||
simpTheorems := relevantHyps
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
}
|
||||
let simpCtx ← Simp.mkContext
|
||||
(config := { failIfUnchanged := false, maxSteps })
|
||||
(simpTheorems := relevantHyps)
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
|
||||
let ⟨result?, _⟩ ← simpGoal goal (ctx := simpCtx) (fvarIdsToSimp := ← goal.getNondepPropHyps)
|
||||
let some (_, newGoal) := result? | return none
|
||||
|
||||
@@ -12,11 +12,10 @@ namespace Lean.Elab.Tactic.Conv
|
||||
open Meta
|
||||
|
||||
private def getContext : MetaM Simp.Context := do
|
||||
return {
|
||||
simpTheorems := {}
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := Simp.neutralConfig
|
||||
}
|
||||
Simp.mkContext
|
||||
(simpTheorems := {})
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := Simp.neutralConfig)
|
||||
|
||||
partial def matchPattern? (pattern : AbstractMVarsResult) (e : Expr) : MetaM (Option (Expr × Array Expr)) :=
|
||||
withNewMCtxDepth do
|
||||
@@ -126,7 +125,7 @@ private def pre (pattern : AbstractMVarsResult) (state : IO.Ref PatternMatchStat
|
||||
pure (.occs #[] 0 ids.toList)
|
||||
| _ => throwUnsupportedSyntax
|
||||
let state ← IO.mkRef occs
|
||||
let ctx := { ← getContext with config.memoize := occs matches .all _ }
|
||||
let ctx := (← getContext).setMemoize (occs matches .all _)
|
||||
let (result, _) ← Simp.main lhs ctx (methods := { pre := pre patternA state })
|
||||
let subgoals ← match ← state.get with
|
||||
| .all #[] | .occs _ 0 _ =>
|
||||
|
||||
@@ -28,8 +28,10 @@ def proveEqUsing (s : SimpTheorems) (a b : Expr) : MetaM (Option Simp.Result) :=
|
||||
unless ← isDefEq a'.expr b'.expr do return none
|
||||
a'.mkEqTrans (← b'.mkEqSymm b)
|
||||
withReducible do
|
||||
(go (← Simp.mkDefaultMethods).toMethodsRef
|
||||
{ simpTheorems := #[s], congrTheorems := ← Meta.getSimpCongrTheorems }).run' {}
|
||||
let ctx ← Simp.mkContext
|
||||
(simpTheorems := #[s])
|
||||
(congrTheorems := ← Meta.getSimpCongrTheorems)
|
||||
(go (← Simp.mkDefaultMethods).toMethodsRef ctx).run' {}
|
||||
|
||||
/-- Proves `a = b` by simplifying using move and squash lemmas. -/
|
||||
def proveEqUsingDown (a b : Expr) : MetaM (Option Simp.Result) := do
|
||||
@@ -191,19 +193,25 @@ def derive (e : Expr) : MetaM Simp.Result := do
|
||||
-- step 1: pre-processing of numerals
|
||||
let r ← withTrace "pre-processing numerals" do
|
||||
let post e := return Simp.Step.done (← try numeralToCoe e catch _ => pure {expr := e})
|
||||
r.mkEqTrans (← Simp.main r.expr { config, congrTheorems } (methods := { post })).1
|
||||
let ctx ← Simp.mkContext (config := config) (congrTheorems := congrTheorems)
|
||||
r.mkEqTrans (← Simp.main r.expr ctx (methods := { post })).1
|
||||
|
||||
-- step 2: casts are moved upwards and eliminated
|
||||
let r ← withTrace "moving upward, splitting and eliminating" do
|
||||
let post := upwardAndElim (← normCastExt.up.getTheorems)
|
||||
r.mkEqTrans (← Simp.main r.expr { config, congrTheorems } (methods := { post })).1
|
||||
let ctx ← Simp.mkContext (config := config) (congrTheorems := congrTheorems)
|
||||
r.mkEqTrans (← Simp.main r.expr ctx (methods := { post })).1
|
||||
|
||||
let simprocs ← ({} : Simp.SimprocsArray).add `reduceCtorEq false
|
||||
|
||||
-- step 3: casts are squashed
|
||||
let r ← withTrace "squashing" do
|
||||
let simpTheorems := #[← normCastExt.squash.getTheorems]
|
||||
r.mkEqTrans (← simp r.expr { simpTheorems, config, congrTheorems } simprocs).1
|
||||
let ctx ← Simp.mkContext
|
||||
(config := config)
|
||||
(simpTheorems := simpTheorems)
|
||||
(congrTheorems := congrTheorems)
|
||||
r.mkEqTrans (← simp r.expr ctx simprocs).1
|
||||
|
||||
return r
|
||||
|
||||
@@ -263,7 +271,7 @@ def evalConvNormCast : Tactic :=
|
||||
def evalPushCast : Tactic := fun stx => do
|
||||
let { ctx, simprocs, dischargeWrapper } ← withMainContext do
|
||||
mkSimpContext (simpTheorems := pushCastExt.getTheorems) stx (eraseLocal := false)
|
||||
let ctx := { ctx with config := { ctx.config with failIfUnchanged := false } }
|
||||
let ctx := ctx.setFailIfUnchanged false
|
||||
dischargeWrapper.with fun discharge? =>
|
||||
discard <| simpLocation ctx simprocs discharge? (expandOptLocation stx[5])
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ Authors: Kim Morrison
|
||||
prelude
|
||||
import Lean.Elab.Tactic.Omega.Core
|
||||
import Lean.Elab.Tactic.FalseOrByContra
|
||||
import Lean.Meta.Tactic.Cases
|
||||
import Lean.Elab.Tactic.Config
|
||||
|
||||
/-!
|
||||
@@ -520,23 +519,6 @@ partial def processFacts (p : MetaProblem) : OmegaM (MetaProblem × Nat) := do
|
||||
|
||||
end MetaProblem
|
||||
|
||||
/--
|
||||
Given `p : P ∨ Q` (or any inductive type with two one-argument constructors),
|
||||
split the goal into two subgoals:
|
||||
one containing the hypothesis `h : P` and another containing `h : Q`.
|
||||
-/
|
||||
def cases₂ (mvarId : MVarId) (p : Expr) (hName : Name := `h) :
|
||||
MetaM ((MVarId × FVarId) × (MVarId × FVarId)) := do
|
||||
let mvarId ← mvarId.assert `hByCases (← inferType p) p
|
||||
let (fvarId, mvarId) ← mvarId.intro1
|
||||
let #[s₁, s₂] ← mvarId.cases fvarId #[{ varNames := [hName] }, { varNames := [hName] }] |
|
||||
throwError "'cases' tactic failed, unexpected number of subgoals"
|
||||
let #[Expr.fvar f₁ ..] ← pure s₁.fields
|
||||
| throwError "'cases' tactic failed, unexpected new hypothesis"
|
||||
let #[Expr.fvar f₂ ..] ← pure s₂.fields
|
||||
| throwError "'cases' tactic failed, unexpected new hypothesis"
|
||||
return ((s₁.mvarId, f₁), (s₂.mvarId, f₂))
|
||||
|
||||
/--
|
||||
Helpful error message when omega cannot find a solution
|
||||
-/
|
||||
@@ -628,33 +610,36 @@ mutual
|
||||
Split a disjunction in a `MetaProblem`, and if we find a new usable fact
|
||||
call `omegaImpl` in both branches.
|
||||
-/
|
||||
partial def splitDisjunction (m : MetaProblem) (g : MVarId) : OmegaM Unit := g.withContext do
|
||||
partial def splitDisjunction (m : MetaProblem) : OmegaM Expr := do
|
||||
match m.disjunctions with
|
||||
| [] => throwError "omega could not prove the goal:\n{← formatErrorMessage m.problem}"
|
||||
| h :: t =>
|
||||
trace[omega] "Case splitting on {← inferType h}"
|
||||
let ctx ← getMCtx
|
||||
let (⟨g₁, h₁⟩, ⟨g₂, h₂⟩) ← cases₂ g h
|
||||
trace[omega] "Adding facts:\n{← g₁.withContext <| inferType (.fvar h₁)}"
|
||||
let m₁ := { m with facts := [.fvar h₁], disjunctions := t }
|
||||
let r ← withoutModifyingState do
|
||||
let (m₁, n) ← g₁.withContext m₁.processFacts
|
||||
| h :: t => do
|
||||
let hType ← whnfD (← inferType h)
|
||||
trace[omega] "Case splitting on {hType}"
|
||||
let_expr Or hType₁ hType₂ := hType | throwError "Unexpected disjunction {hType}"
|
||||
let p?₁ ← withoutModifyingState do withLocalDeclD `h₁ hType₁ fun h₁ => do
|
||||
withTraceNode `omega (msg := fun _ => do pure m!"Assuming fact:{indentExpr hType₁}") do
|
||||
let m₁ := { m with facts := [h₁], disjunctions := t }
|
||||
let (m₁, n) ← m₁.processFacts
|
||||
if 0 < n then
|
||||
omegaImpl m₁ g₁
|
||||
pure true
|
||||
let p₁ ← omegaImpl m₁
|
||||
let p₁ ← mkLambdaFVars #[h₁] p₁
|
||||
return some p₁
|
||||
else
|
||||
pure false
|
||||
if r then
|
||||
trace[omega] "Adding facts:\n{← g₂.withContext <| inferType (.fvar h₂)}"
|
||||
let m₂ := { m with facts := [.fvar h₂], disjunctions := t }
|
||||
omegaImpl m₂ g₂
|
||||
return none
|
||||
if let some p₁ := p?₁ then
|
||||
withLocalDeclD `h₂ hType₂ fun h₂ => do
|
||||
withTraceNode `omega (msg := fun _ => do pure m!"Assuming fact:{indentExpr hType₂}") do
|
||||
let m₂ := { m with facts := [h₂], disjunctions := t }
|
||||
let p₂ ← omegaImpl m₂
|
||||
let p₂ ← mkLambdaFVars #[h₂] p₂
|
||||
return mkApp6 (mkConst ``Or.elim) hType₁ hType₂ (mkConst ``False) h p₁ p₂
|
||||
else
|
||||
trace[omega] "No new facts found."
|
||||
setMCtx ctx
|
||||
splitDisjunction { m with disjunctions := t } g
|
||||
splitDisjunction { m with disjunctions := t }
|
||||
|
||||
/-- Implementation of the `omega` algorithm, and handling disjunctions. -/
|
||||
partial def omegaImpl (m : MetaProblem) (g : MVarId) : OmegaM Unit := g.withContext do
|
||||
partial def omegaImpl (m : MetaProblem) : OmegaM Expr := do
|
||||
let (m, _) ← m.processFacts
|
||||
guard m.facts.isEmpty
|
||||
let p := m.problem
|
||||
@@ -663,12 +648,12 @@ partial def omegaImpl (m : MetaProblem) (g : MVarId) : OmegaM Unit := g.withCont
|
||||
trace[omega] "After elimination:\nAtoms: {← atomsList}\n{p'}"
|
||||
match p'.possible, p'.proveFalse?, p'.proveFalse?_spec with
|
||||
| true, _, _ =>
|
||||
splitDisjunction m g
|
||||
splitDisjunction m
|
||||
| false, .some prf, _ =>
|
||||
trace[omega] "Justification:\n{p'.explanation?.get}"
|
||||
let prf ← instantiateMVars (← prf)
|
||||
trace[omega] "omega found a contradiction, proving {← inferType prf}"
|
||||
g.assign prf
|
||||
return prf
|
||||
|
||||
end
|
||||
|
||||
@@ -677,7 +662,9 @@ Given a collection of facts, try prove `False` using the omega algorithm,
|
||||
and close the goal using that.
|
||||
-/
|
||||
def omega (facts : List Expr) (g : MVarId) (cfg : OmegaConfig := {}) : MetaM Unit :=
|
||||
OmegaM.run (omegaImpl { facts } g) cfg
|
||||
g.withContext do
|
||||
let prf ← OmegaM.run (omegaImpl { facts }) cfg
|
||||
g.assign prf
|
||||
|
||||
open Lean Elab Tactic Parser.Tactic
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ def elabSimpArgs (stx : Syntax) (ctx : Simp.Context) (simprocs : Simp.SimprocsAr
|
||||
logException ex
|
||||
else
|
||||
throw ex
|
||||
return { ctx := { ctx with simpTheorems := thmsArray.set! 0 thms }, simprocs, starArg }
|
||||
return { ctx := ctx.setSimpTheorems (thmsArray.set! 0 thms), simprocs, starArg }
|
||||
-- If recovery is disabled, then we want simp argument elaboration failures to be exceptions.
|
||||
-- This affects `addSimpTheorem`.
|
||||
if (← read).recover then
|
||||
@@ -311,10 +311,11 @@ def mkSimpContext (stx : Syntax) (eraseLocal : Bool) (kind := SimpKind.simp)
|
||||
simpTheorems
|
||||
let simprocs ← if simpOnly then pure {} else Simp.getSimprocs
|
||||
let congrTheorems ← getSimpCongrTheorems
|
||||
let r ← elabSimpArgs stx[4] (eraseLocal := eraseLocal) (kind := kind) (simprocs := #[simprocs]) {
|
||||
config := (← elabSimpConfig stx[1] (kind := kind))
|
||||
simpTheorems := #[simpTheorems], congrTheorems
|
||||
}
|
||||
let ctx ← Simp.mkContext
|
||||
(config := (← elabSimpConfig stx[1] (kind := kind)))
|
||||
(simpTheorems := #[simpTheorems])
|
||||
congrTheorems
|
||||
let r ← elabSimpArgs stx[4] (eraseLocal := eraseLocal) (kind := kind) (simprocs := #[simprocs]) ctx
|
||||
if !r.starArg || ignoreStarArg then
|
||||
return { r with dischargeWrapper }
|
||||
else
|
||||
@@ -329,7 +330,7 @@ def mkSimpContext (stx : Syntax) (eraseLocal : Bool) (kind := SimpKind.simp)
|
||||
for h in hs do
|
||||
unless simpTheorems.isErased (.fvar h) do
|
||||
simpTheorems ← simpTheorems.addTheorem (.fvar h) (← h.getDecl).toExpr
|
||||
let ctx := { ctx with simpTheorems }
|
||||
let ctx := ctx.setSimpTheorems simpTheorems
|
||||
return { ctx, simprocs, dischargeWrapper }
|
||||
|
||||
register_builtin_option tactic.simp.trace : Bool := {
|
||||
|
||||
@@ -36,9 +36,9 @@ deriving instance Repr for UseImplicitLambdaResult
|
||||
let stx ← `(tactic| simp $cfg:optConfig $(disch)? $[only%$only]? $[[$args,*]]?)
|
||||
let { ctx, simprocs, dischargeWrapper } ←
|
||||
withMainContext <| mkSimpContext stx (eraseLocal := false)
|
||||
let ctx := if unfold.isSome then { ctx with config.autoUnfold := true } else ctx
|
||||
let ctx := if unfold.isSome then ctx.setAutoUnfold else ctx
|
||||
-- TODO: have `simpa` fail if it doesn't use `simp`.
|
||||
let ctx := { ctx with config := { ctx.config with failIfUnchanged := false } }
|
||||
let ctx := ctx.setFailIfUnchanged false
|
||||
dischargeWrapper.with fun discharge? => do
|
||||
let (some (_, g), stats) ← simpGoal (← getMainGoal) ctx (simprocs := simprocs)
|
||||
(simplifyTarget := true) (discharge? := discharge?)
|
||||
|
||||
@@ -116,7 +116,7 @@ variable (p : Name → Bool) in
|
||||
/-- Returns true when the message contains a `MessageData.tagged tag ..` constructor where `p tag`
|
||||
is true.
|
||||
|
||||
This does not descend into lazily generated subtress (`.ofLazy`); message tags
|
||||
This does not descend into lazily generated subtrees (`.ofLazy`); message tags
|
||||
of interest (like those added by `logLinter`) are expected to be near the root
|
||||
of the `MessageData`, and not hidden inside `.ofLazy`.
|
||||
-/
|
||||
@@ -130,6 +130,19 @@ partial def hasTag : MessageData → Bool
|
||||
| trace data msg msgs => p data.cls || hasTag msg || msgs.any hasTag
|
||||
| _ => false
|
||||
|
||||
/--
|
||||
Returns the top-level tag of the message.
|
||||
If none, returns `Name.anonymous`.
|
||||
|
||||
This does not descend into message subtrees (e.g., `.compose`, `.ofLazy`).
|
||||
The message kind is expected to describe the whole message.
|
||||
-/
|
||||
def kind : MessageData → Name
|
||||
| withContext _ msg => kind msg
|
||||
| withNamingContext _ msg => kind msg
|
||||
| tagged n _ => n
|
||||
| _ => .anonymous
|
||||
|
||||
/-- An empty message. -/
|
||||
def nil : MessageData :=
|
||||
ofFormat Format.nil
|
||||
@@ -315,7 +328,7 @@ structure BaseMessage (α : Type u) where
|
||||
endPos : Option Position := none
|
||||
/-- If `true`, report range as given; see `msgToInteractiveDiagnostic`. -/
|
||||
keepFullRange : Bool := false
|
||||
severity : MessageSeverity := MessageSeverity.error
|
||||
severity : MessageSeverity := .error
|
||||
caption : String := ""
|
||||
/-- The content of the message. -/
|
||||
data : α
|
||||
@@ -328,7 +341,10 @@ abbrev Message := BaseMessage MessageData
|
||||
/-- A `SerialMessage` is a `Message` whose `MessageData` has been eagerly
|
||||
serialized and is thus appropriate for use in pure contexts where the effectful
|
||||
`MessageData.toString` cannot be used. -/
|
||||
abbrev SerialMessage := BaseMessage String
|
||||
structure SerialMessage extends BaseMessage String where
|
||||
/-- The message kind (i.e., the top-level tag). -/
|
||||
kind : Name
|
||||
deriving ToJson, FromJson
|
||||
|
||||
namespace SerialMessage
|
||||
|
||||
@@ -354,8 +370,12 @@ end SerialMessage
|
||||
|
||||
namespace Message
|
||||
|
||||
@[inherit_doc MessageData.kind] abbrev kind (msg : Message) :=
|
||||
msg.data.kind
|
||||
|
||||
/-- Serializes the message, converting its data into a string and saving its kind. -/
|
||||
@[inline] def serialize (msg : Message) : IO SerialMessage := do
|
||||
return {msg with data := ← msg.data.toString}
|
||||
return {msg with kind := msg.kind, data := ← msg.data.toString}
|
||||
|
||||
protected def toString (msg : Message) (includeEndPos := false) : IO String := do
|
||||
-- Remark: The inline here avoids a new message allocation when `msg` is shared
|
||||
|
||||
@@ -332,7 +332,7 @@ register_builtin_option maxSynthPendingDepth : Nat := {
|
||||
Contextual information for the `MetaM` monad.
|
||||
-/
|
||||
structure Context where
|
||||
config : Config := {}
|
||||
private config : Config := {}
|
||||
/-- Local context -/
|
||||
lctx : LocalContext := {}
|
||||
/-- Local instances in `lctx`. -/
|
||||
@@ -943,6 +943,15 @@ def elimMVarDeps (xs : Array Expr) (e : Expr) (preserveOrder : Bool := false) :
|
||||
@[inline] def withConfig (f : Config → Config) : n α → n α :=
|
||||
mapMetaM <| withReader (fun ctx => { ctx with config := f ctx.config })
|
||||
|
||||
@[inline] def withCanUnfoldPred (p : Config → ConstantInfo → CoreM Bool) : n α → n α :=
|
||||
mapMetaM <| withReader (fun ctx => { ctx with canUnfold? := p })
|
||||
|
||||
@[inline] def withIncSynthPending : n α → n α :=
|
||||
mapMetaM <| withReader (fun ctx => { ctx with synthPendingDepth := ctx.synthPendingDepth + 1 })
|
||||
|
||||
@[inline] def withInTypeClassResolution : n α → n α :=
|
||||
mapMetaM <| withReader (fun ctx => { ctx with inTypeClassResolution := true })
|
||||
|
||||
/--
|
||||
Executes `x` tracking zetaDelta reductions `Config.trackZetaDelta := true`
|
||||
-/
|
||||
@@ -1422,6 +1431,14 @@ def withLocalDecl (name : Name) (bi : BinderInfo) (type : Expr) (k : Expr → n
|
||||
def withLocalDeclD (name : Name) (type : Expr) (k : Expr → n α) : n α :=
|
||||
withLocalDecl name BinderInfo.default type k
|
||||
|
||||
/--
|
||||
Similar to `withLocalDecl`, but it does **not** check whether the new variable is a local instance or not.
|
||||
-/
|
||||
def withLocalDeclNoLocalInstanceUpdate (name : Name) (bi : BinderInfo) (type : Expr) (x : Expr → MetaM α) : MetaM α := do
|
||||
let fvarId ← mkFreshFVarId
|
||||
withReader (fun ctx => { ctx with lctx := ctx.lctx.mkLocalDecl fvarId name type bi }) do
|
||||
x (mkFVar fvarId)
|
||||
|
||||
/-- Append an array of free variables `xs` to the local context and execute `k xs`.
|
||||
`declInfos` takes the form of an array consisting of:
|
||||
- the name of the variable
|
||||
@@ -1538,11 +1555,11 @@ def withReplaceFVarId {α} (fvarId : FVarId) (e : Expr) : MetaM α → MetaM α
|
||||
localInstances := ctx.localInstances.erase fvarId }
|
||||
|
||||
/--
|
||||
`withNewMCtxDepth k` executes `k` with a higher metavariable context depth,
|
||||
where metavariables created outside the `withNewMCtxDepth` (with a lower depth) cannot be assigned.
|
||||
If `allowLevelAssignments` is set to true, then the level metavariable depth
|
||||
is not increased, and level metavariables from the outer scope can be
|
||||
assigned. (This is used by TC synthesis.)
|
||||
`withNewMCtxDepth k` executes `k` with a higher metavariable context depth,
|
||||
where metavariables created outside the `withNewMCtxDepth` (with a lower depth) cannot be assigned.
|
||||
If `allowLevelAssignments` is set to true, then the level metavariable depth
|
||||
is not increased, and level metavariables from the outer scope can be
|
||||
assigned. (This is used by TC synthesis.)
|
||||
-/
|
||||
def withNewMCtxDepth (k : n α) (allowLevelAssignments := false) : n α :=
|
||||
mapMetaM (withNewMCtxDepthImp allowLevelAssignments) k
|
||||
@@ -1552,13 +1569,20 @@ private def withLocalContextImp (lctx : LocalContext) (localInsts : LocalInstanc
|
||||
x
|
||||
|
||||
/--
|
||||
`withLCtx lctx localInsts k` replaces the local context and local instances, and then executes `k`.
|
||||
The local context and instances are restored after executing `k`.
|
||||
This method assumes that the local instances in `localInsts` are in the local context `lctx`.
|
||||
`withLCtx lctx localInsts k` replaces the local context and local instances, and then executes `k`.
|
||||
The local context and instances are restored after executing `k`.
|
||||
This method assumes that the local instances in `localInsts` are in the local context `lctx`.
|
||||
-/
|
||||
def withLCtx (lctx : LocalContext) (localInsts : LocalInstances) : n α → n α :=
|
||||
mapMetaM <| withLocalContextImp lctx localInsts
|
||||
|
||||
/--
|
||||
Simpler version of `withLCtx` which just updates the local context. It is the resposability of the
|
||||
caller ensure the local instances are also properly updated.
|
||||
-/
|
||||
def withLCtx' (lctx : LocalContext) : n α → n α :=
|
||||
mapMetaM <| withReader (fun ctx => { ctx with lctx })
|
||||
|
||||
/--
|
||||
Runs `k` in a local environment with the `fvarIds` erased.
|
||||
-/
|
||||
|
||||
@@ -157,9 +157,11 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
|
||||
let eType ← instantiateMVars (← inferType e)
|
||||
let some (n, β) ← isTypeApp? expectedType | return none
|
||||
let some (m, α) ← isTypeApp? eType | return none
|
||||
-- Need to save and restore the state in case `m` and `n` are defeq but not monads to prevent this procedure from having side effects.
|
||||
let saved ← saveState
|
||||
if (← isDefEq m n) then
|
||||
let some monadInst ← isMonad? n | return none
|
||||
try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => return none
|
||||
let some monadInst ← isMonad? n | restoreState saved; return none
|
||||
try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => restoreState saved; return none
|
||||
else if autoLift.get (← getOptions) then
|
||||
try
|
||||
-- Construct lift from `m` to `n`
|
||||
|
||||
@@ -553,8 +553,8 @@ private def getKeyArgs (e : Expr) (isMatch root : Bool) (config : WhnfCoreConfig
|
||||
if isMatch then
|
||||
return (.other, #[])
|
||||
else do
|
||||
let ctx ← read
|
||||
if ctx.config.isDefEqStuckEx then
|
||||
let cfg ← getConfig
|
||||
if cfg.isDefEqStuckEx then
|
||||
/-
|
||||
When the configuration flag `isDefEqStuckEx` is set to true,
|
||||
we want `isDefEq` to throw an exception whenever it tries to assign
|
||||
|
||||
@@ -364,7 +364,7 @@ private partial def isDefEqBindingAux (lctx : LocalContext) (fvars : Array Expr)
|
||||
| Expr.forallE n d₁ b₁ _, Expr.forallE _ d₂ b₂ _ => process n d₁ d₂ b₁ b₂
|
||||
| Expr.lam n d₁ b₁ _, Expr.lam _ d₂ b₂ _ => process n d₁ d₂ b₁ b₂
|
||||
| _, _ =>
|
||||
withReader (fun ctx => { ctx with lctx := lctx }) do
|
||||
withLCtx' lctx do
|
||||
isDefEqBindingDomain fvars ds₂ do
|
||||
Meta.isExprDefEqAux (e₁.instantiateRev fvars) (e₂.instantiateRev fvars)
|
||||
|
||||
@@ -758,8 +758,8 @@ mutual
|
||||
if mvarDecl.depth != (← getMCtx).depth || mvarDecl.kind.isSyntheticOpaque then
|
||||
traceM `Meta.isDefEq.assign.readOnlyMVarWithBiggerLCtx <| addAssignmentInfo (mkMVar mvarId)
|
||||
throwCheckAssignmentFailure
|
||||
let ctxMeta ← readThe Meta.Context
|
||||
unless ctxMeta.config.ctxApprox && ctx.mvarDecl.lctx.isSubPrefixOf mvarDecl.lctx do
|
||||
let cfg ← getConfig
|
||||
unless cfg.ctxApprox && ctx.mvarDecl.lctx.isSubPrefixOf mvarDecl.lctx do
|
||||
traceM `Meta.isDefEq.assign.readOnlyMVarWithBiggerLCtx <| addAssignmentInfo (mkMVar mvarId)
|
||||
throwCheckAssignmentFailure
|
||||
/- Create an auxiliary metavariable with a smaller context and "checked" type.
|
||||
@@ -814,8 +814,8 @@ mutual
|
||||
|
||||
partial def checkApp (e : Expr) : CheckAssignmentM Expr :=
|
||||
e.withApp fun f args => do
|
||||
let ctxMeta ← readThe Meta.Context
|
||||
if f.isMVar && ctxMeta.config.ctxApprox && args.all Expr.isFVar then
|
||||
let cfg ← getConfig
|
||||
if f.isMVar && cfg.ctxApprox && args.all Expr.isFVar then
|
||||
let f ← check f
|
||||
catchInternalId outOfScopeExceptionId
|
||||
(do
|
||||
@@ -1794,8 +1794,8 @@ private partial def isDefEqQuickOther (t s : Expr) : MetaM LBool := do
|
||||
| LBool.true => return LBool.true
|
||||
| LBool.false => return LBool.false
|
||||
| _ =>
|
||||
let ctx ← read
|
||||
if ctx.config.isDefEqStuckEx then do
|
||||
let cfg ← getConfig
|
||||
if cfg.isDefEqStuckEx then do
|
||||
trace[Meta.isDefEq.stuck] "{t} =?= {s}"
|
||||
Meta.throwIsDefEqStuck
|
||||
else
|
||||
@@ -1834,7 +1834,7 @@ end
|
||||
let e ← instantiateMVars e
|
||||
successK e
|
||||
else
|
||||
if (← read).config.isDefEqStuckEx then
|
||||
if (← getConfig).isDefEqStuckEx then
|
||||
/-
|
||||
When `isDefEqStuckEx := true` and `mvar` was created in a previous level,
|
||||
we should throw an exception. See issue #2736 for a situation where this can happen.
|
||||
|
||||
@@ -22,10 +22,11 @@ private def canUnfoldDefault (cfg : Config) (info : ConstantInfo) : CoreM Bool :
|
||||
|
||||
def canUnfold (info : ConstantInfo) : MetaM Bool := do
|
||||
let ctx ← read
|
||||
let cfg ← getConfig
|
||||
if let some f := ctx.canUnfold? then
|
||||
f ctx.config info
|
||||
f cfg info
|
||||
else
|
||||
canUnfoldDefault ctx.config info
|
||||
canUnfoldDefault cfg info
|
||||
|
||||
/--
|
||||
Look up a constant name, returning the `ConstantInfo`
|
||||
|
||||
@@ -382,11 +382,6 @@ def isType (e : Expr) : MetaM Bool := do
|
||||
| .sort .. => return true
|
||||
| _ => return false
|
||||
|
||||
@[inline] private def withLocalDecl' {α} (name : Name) (bi : BinderInfo) (type : Expr) (x : Expr → MetaM α) : MetaM α := do
|
||||
let fvarId ← mkFreshFVarId
|
||||
withReader (fun ctx => { ctx with lctx := ctx.lctx.mkLocalDecl fvarId name type bi }) do
|
||||
x (mkFVar fvarId)
|
||||
|
||||
def typeFormerTypeLevelQuick : Expr → Option Level
|
||||
| .forallE _ _ b _ => typeFormerTypeLevelQuick b
|
||||
| .sort l => some l
|
||||
@@ -403,7 +398,7 @@ where
|
||||
go (type : Expr) (xs : Array Expr) : MetaM (Option Level) := do
|
||||
match type with
|
||||
| .sort l => return some l
|
||||
| .forallE n d b c => withLocalDecl' n c (d.instantiateRev xs) fun x => go b (xs.push x)
|
||||
| .forallE n d b c => withLocalDeclNoLocalInstanceUpdate n c (d.instantiateRev xs) fun x => go b (xs.push x)
|
||||
| _ =>
|
||||
let type ← whnfD (type.instantiateRev xs)
|
||||
match type with
|
||||
|
||||
@@ -222,8 +222,8 @@ private def getKeyArgs (e : Expr) (isMatch root : Bool) (config : WhnfCoreConfig
|
||||
if isMatch then
|
||||
return (.other, #[])
|
||||
else do
|
||||
let ctx ← read
|
||||
if ctx.config.isDefEqStuckEx then
|
||||
let cfg ← getConfig
|
||||
if cfg.isDefEqStuckEx then
|
||||
/-
|
||||
When the configuration flag `isDefEqStuckEx` is set to true,
|
||||
we want `isDefEq` to throw an exception whenever it tries to assign
|
||||
|
||||
@@ -149,8 +149,8 @@ mutual
|
||||
if r != LBool.undef then
|
||||
return r == LBool.true
|
||||
else if !(← hasAssignableLevelMVar lhs <||> hasAssignableLevelMVar rhs) then
|
||||
let ctx ← read
|
||||
if ctx.config.isDefEqStuckEx && (lhs.isMVar || rhs.isMVar) then do
|
||||
let cfg ← getConfig
|
||||
if cfg.isDefEqStuckEx && (lhs.isMVar || rhs.isMVar) then do
|
||||
trace[Meta.isLevelDefEq.stuck] "{lhs} =?= {rhs}"
|
||||
Meta.throwIsDefEqStuck
|
||||
else
|
||||
|
||||
@@ -162,7 +162,7 @@ def refineThrough? (matcherApp : MatcherApp) (e : Expr) :
|
||||
private def withUserNamesImpl {α} (fvars : Array Expr) (names : Array Name) (k : MetaM α) : MetaM α := do
|
||||
let lctx := (Array.zip fvars names).foldl (init := ← (getLCtx)) fun lctx (fvar, name) =>
|
||||
lctx.setUserName fvar.fvarId! name
|
||||
withTheReader Meta.Context (fun ctx => { ctx with lctx }) k
|
||||
withLCtx' lctx k
|
||||
|
||||
/--
|
||||
Sets the user name of the FVars in the local context according to the given array of names.
|
||||
|
||||
@@ -782,7 +782,7 @@ def synthInstance? (type : Expr) (maxResultSize? : Option Nat := none) : MetaM (
|
||||
(return m!"{exceptOptionEmoji ·} {← instantiateMVars type}") do
|
||||
withConfig (fun config => { config with isDefEqStuckEx := true, transparency := TransparencyMode.instances,
|
||||
foApprox := true, ctxApprox := true, constApprox := false, univApprox := false }) do
|
||||
withReader (fun ctx => { ctx with inTypeClassResolution := true }) do
|
||||
withInTypeClassResolution do
|
||||
let localInsts ← getLocalInstances
|
||||
let type ← instantiateMVars type
|
||||
let type ← preprocess type
|
||||
@@ -839,7 +839,7 @@ private def synthPendingImp (mvarId : MVarId) : MetaM Bool := withIncRecDepth <|
|
||||
recordSynthPendingFailure mvarDecl.type
|
||||
return false
|
||||
else
|
||||
withReader (fun ctx => { ctx with synthPendingDepth := ctx.synthPendingDepth + 1 }) do
|
||||
withIncSynthPending do
|
||||
trace[Meta.synthPending] "synthPending {mkMVar mvarId}"
|
||||
let val? ← catchInternalId isDefEqStuckExceptionId (synthInstance? mvarDecl.type (maxResultSize? := none)) (fun _ => pure none)
|
||||
match val? with
|
||||
|
||||
@@ -188,12 +188,10 @@ def post (e : Expr) : SimpM Simp.Step := do
|
||||
| e, _ => return Simp.Step.done { expr := e }
|
||||
|
||||
def rewriteUnnormalized (mvarId : MVarId) : MetaM MVarId := do
|
||||
let simpCtx :=
|
||||
{
|
||||
simpTheorems := {}
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := Simp.neutralConfig
|
||||
}
|
||||
let simpCtx ← Simp.mkContext
|
||||
(simpTheorems := {})
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := Simp.neutralConfig)
|
||||
let tgt ← instantiateMVars (← mvarId.getType)
|
||||
let (res, _) ← Simp.main tgt simpCtx (methods := { post })
|
||||
applySimpResultToTarget mvarId tgt res
|
||||
@@ -207,12 +205,10 @@ def rewriteUnnormalizedRefl (goal : MVarId) : MetaM Unit := do
|
||||
|
||||
def acNfHypMeta (goal : MVarId) (fvarId : FVarId) : MetaM (Option MVarId) := do
|
||||
goal.withContext do
|
||||
let simpCtx :=
|
||||
{
|
||||
simpTheorems := {}
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := Simp.neutralConfig
|
||||
}
|
||||
let simpCtx ← Simp.mkContext
|
||||
(simpTheorems := {})
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := Simp.neutralConfig)
|
||||
let tgt ← instantiateMVars (← fvarId.getType)
|
||||
let (res, _) ← Simp.main tgt simpCtx (methods := { post })
|
||||
return (← applySimpResultToLocalDecl goal fvarId res false).map (·.snd)
|
||||
|
||||
@@ -38,7 +38,10 @@ where
|
||||
let sizeOfEq ← mkLT sizeOf_lhs sizeOf_rhs
|
||||
let hlt ← mkFreshExprSyntheticOpaqueMVar sizeOfEq
|
||||
-- TODO: we only need the `sizeOf` simp theorems
|
||||
match (← simpTarget hlt.mvarId! { config.arith := true, simpTheorems := #[ (← getSimpTheorems) ] } {}).1 with
|
||||
let ctx ← Simp.mkContext
|
||||
(config := { arith := true })
|
||||
(simpTheorems := #[ (← getSimpTheorems) ])
|
||||
match (← simpTarget hlt.mvarId! ctx {}).1 with
|
||||
| some _ => return false
|
||||
| none =>
|
||||
let heq ← mkCongrArg sizeOf_lhs.appFn! (← mkEqSymm h)
|
||||
|
||||
@@ -254,10 +254,6 @@ Apply `And.intro` as much as possible to goal `mvarId`.
|
||||
abbrev splitAnd (mvarId : MVarId) : MetaM (List MVarId) :=
|
||||
splitAndCore mvarId
|
||||
|
||||
@[deprecated splitAnd (since := "2024-03-17")]
|
||||
def _root_.Lean.Meta.splitAnd (mvarId : MVarId) : MetaM (List MVarId) :=
|
||||
mvarId.splitAnd
|
||||
|
||||
def exfalso (mvarId : MVarId) : MetaM MVarId :=
|
||||
mvarId.withContext do
|
||||
mvarId.checkNotAssigned `exfalso
|
||||
|
||||
@@ -38,11 +38,10 @@ abbrev PreM := ReaderT Context $ StateRefT State GrindM
|
||||
def PreM.run (x : PreM α) : GrindM α := do
|
||||
let thms ← grindNormExt.getTheorems
|
||||
let simprocs := #[(← grindNormSimprocExt.getSimprocs)]
|
||||
let simp : Simp.Context := {
|
||||
config := { arith := true }
|
||||
simpTheorems := #[thms]
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
}
|
||||
let simp ← Simp.mkContext
|
||||
(config := { arith := true })
|
||||
(simpTheorems := #[thms])
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
x { simp, simprocs } |>.run' {}
|
||||
|
||||
def simp (_goal : Goal) (e : Expr) : PreM Simp.Result := do
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Lean.Meta
|
||||
match i, type with
|
||||
| 0, type =>
|
||||
let type := type.instantiateRevRange j fvars.size fvars
|
||||
withReader (fun ctx => { ctx with lctx := lctx }) do
|
||||
withLCtx' lctx do
|
||||
withNewLocalInstances fvars j do
|
||||
let tag ← mvarId.getTag
|
||||
let type := type.headBeta
|
||||
@@ -57,7 +57,7 @@ namespace Lean.Meta
|
||||
loop i lctx fvars j s body
|
||||
else
|
||||
let type := type.instantiateRevRange j fvars.size fvars
|
||||
withReader (fun ctx => { ctx with lctx := lctx }) do
|
||||
withLCtx' lctx do
|
||||
withNewLocalInstances fvars j do
|
||||
/- We used to use just `whnf`, but it produces counterintuitive behavior if
|
||||
- `type` is a metavariable `?m` such that `?m := let x := v; b`, or
|
||||
|
||||
@@ -60,9 +60,6 @@ private def addImport (name : Name) (constInfo : ConstantInfo) :
|
||||
pure a
|
||||
| _ => return #[]
|
||||
|
||||
/-- Configuration for `DiscrTree`. -/
|
||||
def discrTreeConfig : WhnfCoreConfig := {}
|
||||
|
||||
/-- Select `=` and `↔` local hypotheses. -/
|
||||
def localHypotheses (except : List FVarId := []) : MetaM (Array (Expr × Bool × Nat)) := do
|
||||
let r ← getLocalHyps
|
||||
|
||||
@@ -73,7 +73,10 @@ def getSimpTheorems : CoreM SimpTheorems :=
|
||||
def getSEvalTheorems : CoreM SimpTheorems :=
|
||||
sevalSimpExtension.getTheorems
|
||||
|
||||
def Simp.Context.mkDefault : MetaM Context :=
|
||||
return { config := {}, simpTheorems := #[(← Meta.getSimpTheorems)], congrTheorems := (← Meta.getSimpCongrTheorems) }
|
||||
def Simp.Context.mkDefault : MetaM Context := do
|
||||
mkContext
|
||||
(config := {})
|
||||
(simpTheorems := #[(← Meta.getSimpTheorems)])
|
||||
(congrTheorems := (← Meta.getSimpCongrTheorems))
|
||||
|
||||
end Lean.Meta
|
||||
|
||||
@@ -20,18 +20,6 @@ builtin_initialize congrHypothesisExceptionId : InternalExceptionId ←
|
||||
def throwCongrHypothesisFailed : MetaM α :=
|
||||
throw <| Exception.internal congrHypothesisExceptionId
|
||||
|
||||
/--
|
||||
Helper method for bootstrapping purposes. It disables `arith` if support theorems have not been defined yet.
|
||||
-/
|
||||
def Config.updateArith (c : Config) : CoreM Config := do
|
||||
if c.arith then
|
||||
if (← getEnv).contains ``Nat.Linear.ExprCnstr.eq_of_toNormPoly_eq then
|
||||
return c
|
||||
else
|
||||
return { c with arith := false }
|
||||
else
|
||||
return c
|
||||
|
||||
/-- Return true if `e` is of the form `ofNat n` where `n` is a kernel Nat literal -/
|
||||
def isOfNatNatLit (e : Expr) : Bool :=
|
||||
e.isAppOf ``OfNat.ofNat && e.getAppNumArgs >= 3 && (e.getArg! 1).isRawNatLit
|
||||
@@ -256,7 +244,7 @@ def withNewLemmas {α} (xs : Array Expr) (f : SimpM α) : SimpM α := do
|
||||
s ← s.addTheorem (.fvar x.fvarId!) x
|
||||
updated := true
|
||||
if updated then
|
||||
withTheReader Context (fun ctx => { ctx with simpTheorems := s }) f
|
||||
withSimpTheorems s f
|
||||
else
|
||||
f
|
||||
else if (← getMethods).wellBehavedDischarge then
|
||||
@@ -463,7 +451,7 @@ private partial def dsimpImpl (e : Expr) : SimpM Expr := do
|
||||
let m ← getMethods
|
||||
let pre := m.dpre >> doNotVisitOfNat >> doNotVisitOfScientific >> doNotVisitCharLit
|
||||
let post := m.dpost >> dsimpReduce
|
||||
withTheReader Simp.Context (fun ctx => { ctx with inDSimp := true }) do
|
||||
withInDSimp do
|
||||
transform (usedLetOnly := cfg.zeta) e (pre := pre) (post := post)
|
||||
|
||||
def visitFn (e : Expr) : SimpM Result := do
|
||||
@@ -658,11 +646,12 @@ where
|
||||
trace[Meta.Tactic.simp.heads] "{repr e.toHeadIndex}"
|
||||
simpLoop e
|
||||
|
||||
-- TODO: delete
|
||||
@[inline] def withSimpContext (ctx : Context) (x : MetaM α) : MetaM α :=
|
||||
withConfig (fun c => { c with etaStruct := ctx.config.etaStruct }) <| withReducible x
|
||||
|
||||
def main (e : Expr) (ctx : Context) (stats : Stats := {}) (methods : Methods := {}) : MetaM (Result × Stats) := do
|
||||
let ctx := { ctx with config := (← ctx.config.updateArith), lctxInitIndices := (← getLCtx).numIndices }
|
||||
let ctx ← ctx.setLctxInitIndices
|
||||
withSimpContext ctx do
|
||||
let (r, s) ← go e methods.toMethodsRef ctx |>.run { stats with }
|
||||
trace[Meta.Tactic.simp.numSteps] "{s.numSteps}"
|
||||
@@ -810,7 +799,7 @@ def simpGoal (mvarId : MVarId) (ctx : Simp.Context) (simprocs : SimprocsArray :=
|
||||
for fvarId in fvarIdsToSimp do
|
||||
let localDecl ← fvarId.getDecl
|
||||
let type ← instantiateMVars localDecl.type
|
||||
let ctx := { ctx with simpTheorems := ctx.simpTheorems.eraseTheorem (.fvar localDecl.fvarId) }
|
||||
let ctx := ctx.setSimpTheorems <| ctx.simpTheorems.eraseTheorem (.fvar localDecl.fvarId)
|
||||
let (r, stats') ← simp type ctx simprocs discharge? stats
|
||||
stats := stats'
|
||||
match r.proof? with
|
||||
@@ -844,7 +833,7 @@ def simpTargetStar (mvarId : MVarId) (ctx : Simp.Context) (simprocs : SimprocsAr
|
||||
let localDecl ← h.getDecl
|
||||
let proof := localDecl.toExpr
|
||||
let simpTheorems ← ctx.simpTheorems.addTheorem (.fvar h) proof
|
||||
ctx := { ctx with simpTheorems }
|
||||
ctx := ctx.setSimpTheorems simpTheorems
|
||||
match (← simpTarget mvarId ctx simprocs discharge? (stats := stats)) with
|
||||
| (none, stats) => return (TacticResultCNM.closed, stats)
|
||||
| (some mvarId', stats') =>
|
||||
|
||||
@@ -41,7 +41,7 @@ def discharge?' (thmId : Origin) (x : Expr) (type : Expr) : SimpM Bool := do
|
||||
let ctx ← getContext
|
||||
if ctx.dischargeDepth >= ctx.maxDischargeDepth then
|
||||
return .maxDepth
|
||||
else withTheReader Context (fun ctx => { ctx with dischargeDepth := ctx.dischargeDepth + 1 }) do
|
||||
else withIncDischargeDepth do
|
||||
-- We save the state, so that `UsedTheorems` does not accumulate
|
||||
-- `simp` lemmas used during unsuccessful discharging.
|
||||
-- We use `withPreservedCache` to ensure the cache is restored after `discharge?`
|
||||
@@ -446,10 +446,13 @@ def mkSEvalMethods : CoreM Methods := do
|
||||
wellBehavedDischarge := true
|
||||
}
|
||||
|
||||
def mkSEvalContext : CoreM Context := do
|
||||
def mkSEvalContext : MetaM Context := do
|
||||
let s ← getSEvalTheorems
|
||||
let c ← Meta.getSimpCongrTheorems
|
||||
return { simpTheorems := #[s], congrTheorems := c, config := { ground := true } }
|
||||
mkContext
|
||||
(simpTheorems := #[s])
|
||||
(congrTheorems := c)
|
||||
(config := { ground := true })
|
||||
|
||||
/--
|
||||
Invoke ground/symbolic evaluator from `simp`.
|
||||
@@ -552,7 +555,7 @@ private def dischargeUsingAssumption? (e : Expr) : SimpM (Option Expr) := do
|
||||
partial def dischargeEqnThmHypothesis? (e : Expr) : MetaM (Option Expr) := do
|
||||
assert! isEqnThmHypothesis e
|
||||
let mvar ← mkFreshExprSyntheticOpaqueMVar e
|
||||
withReader (fun ctx => { ctx with canUnfold? := canUnfoldAtMatcher }) do
|
||||
withCanUnfoldPred canUnfoldAtMatcher do
|
||||
if let .none ← go? mvar.mvarId! then
|
||||
instantiateMVars mvar
|
||||
else
|
||||
|
||||
@@ -43,7 +43,7 @@ private def initEntries : M Unit := do
|
||||
let localDecl ← h.getDecl
|
||||
let proof := localDecl.toExpr
|
||||
simpThms ← simpThms.addTheorem (.fvar h) proof
|
||||
modify fun s => { s with ctx.simpTheorems := simpThms }
|
||||
modify fun s => { s with ctx := s.ctx.setSimpTheorems simpThms }
|
||||
if hsNonDeps.contains h then
|
||||
-- We only simplify nondependent hypotheses
|
||||
let type ← instantiateMVars localDecl.type
|
||||
@@ -62,7 +62,7 @@ private partial def loop : M Bool := do
|
||||
let ctx := (← get).ctx
|
||||
-- We disable the current entry to prevent it to be simplified to `True`
|
||||
let simpThmsWithoutEntry := (← getSimpTheorems).eraseTheorem entry.id
|
||||
let ctx := { ctx with simpTheorems := simpThmsWithoutEntry }
|
||||
let ctx := ctx.setSimpTheorems simpThmsWithoutEntry
|
||||
let (r, stats) ← simpStep (← get).mvarId entry.proof entry.type ctx simprocs (stats := { (← get) with })
|
||||
modify fun s => { s with usedTheorems := stats.usedTheorems, diag := stats.diag }
|
||||
match r with
|
||||
@@ -98,7 +98,7 @@ private partial def loop : M Bool := do
|
||||
simpThmsNew ← simpThmsNew.addTheorem (.other idNew) (← mkExpectedTypeHint proofNew typeNew)
|
||||
modify fun s => { s with
|
||||
modified := true
|
||||
ctx.simpTheorems := simpThmsNew
|
||||
ctx := ctx.setSimpTheorems simpThmsNew
|
||||
entries[i] := { entry with type := typeNew, proof := proofNew, id := .other idNew }
|
||||
}
|
||||
-- simplify target
|
||||
|
||||
@@ -52,6 +52,7 @@ abbrev Cache := SExprMap Result
|
||||
abbrev CongrCache := ExprMap (Option CongrTheorem)
|
||||
|
||||
structure Context where
|
||||
private mk ::
|
||||
config : Config := {}
|
||||
/-- `maxDischargeDepth` from `config` as an `UInt32`. -/
|
||||
maxDischargeDepth : UInt32 := UInt32.ofNatTruncate config.maxDischargeDepth
|
||||
@@ -103,6 +104,41 @@ structure Context where
|
||||
inDSimp : Bool := false
|
||||
deriving Inhabited
|
||||
|
||||
/--
|
||||
Helper method for bootstrapping purposes.
|
||||
It disables `arith` if support theorems have not been defined yet.
|
||||
-/
|
||||
private def updateArith (c : Config) : CoreM Config := do
|
||||
if c.arith then
|
||||
if (← getEnv).contains ``Nat.Linear.ExprCnstr.eq_of_toNormPoly_eq then
|
||||
return c
|
||||
else
|
||||
return { c with arith := false }
|
||||
else
|
||||
return c
|
||||
|
||||
def mkContext (config : Config := {}) (simpTheorems : SimpTheoremsArray := {}) (congrTheorems : SimpCongrTheorems := {}) : MetaM Context := do
|
||||
let config ← updateArith config
|
||||
return { config, simpTheorems, congrTheorems }
|
||||
|
||||
def Context.setConfig (context : Context) (config : Config) : Context :=
|
||||
{ context with config }
|
||||
|
||||
def Context.setSimpTheorems (c : Context) (simpTheorems : SimpTheoremsArray) : Context :=
|
||||
{ c with simpTheorems }
|
||||
|
||||
def Context.setLctxInitIndices (c : Context) : MetaM Context :=
|
||||
return { c with lctxInitIndices := (← getLCtx).numIndices }
|
||||
|
||||
def Context.setAutoUnfold (c : Context) : Context :=
|
||||
{ c with config.autoUnfold := true }
|
||||
|
||||
def Context.setFailIfUnchanged (c : Context) (flag : Bool) : Context :=
|
||||
{ c with config.failIfUnchanged := flag }
|
||||
|
||||
def Context.setMemoize (c : Context) (flag : Bool) : Context :=
|
||||
{ c with config.memoize := flag }
|
||||
|
||||
def Context.isDeclToUnfold (ctx : Context) (declName : Name) : Bool :=
|
||||
ctx.simpTheorems.isDeclToUnfold declName
|
||||
|
||||
@@ -158,6 +194,15 @@ instance : Nonempty MethodsRef := MethodsRefPointed.property
|
||||
|
||||
abbrev SimpM := ReaderT MethodsRef $ ReaderT Context $ StateRefT State MetaM
|
||||
|
||||
@[inline] def withIncDischargeDepth : SimpM α → SimpM α :=
|
||||
withTheReader Context (fun ctx => { ctx with dischargeDepth := ctx.dischargeDepth + 1 })
|
||||
|
||||
@[inline] def withSimpTheorems (s : SimpTheoremsArray) : SimpM α → SimpM α :=
|
||||
withTheReader Context (fun ctx => { ctx with simpTheorems := s })
|
||||
|
||||
@[inline] def withInDSimp : SimpM α → SimpM α :=
|
||||
withTheReader Context (fun ctx => { ctx with inDSimp := true })
|
||||
|
||||
@[extern "lean_simp"]
|
||||
opaque simp (e : Expr) : SimpM Result
|
||||
|
||||
|
||||
@@ -13,12 +13,11 @@ import Lean.Meta.Tactic.Generalize
|
||||
namespace Lean.Meta
|
||||
namespace Split
|
||||
|
||||
def getSimpMatchContext : MetaM Simp.Context :=
|
||||
return {
|
||||
simpTheorems := {}
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := { Simp.neutralConfig with dsimp := false }
|
||||
}
|
||||
def getSimpMatchContext : MetaM Simp.Context := do
|
||||
Simp.mkContext
|
||||
(simpTheorems := {})
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := { Simp.neutralConfig with dsimp := false })
|
||||
|
||||
def simpMatch (e : Expr) : MetaM Simp.Result := do
|
||||
let discharge? ← SplitIf.mkDischarge?
|
||||
|
||||
@@ -19,11 +19,10 @@ def getSimpContext : MetaM Simp.Context := do
|
||||
s ← s.addConst ``if_neg
|
||||
s ← s.addConst ``dif_pos
|
||||
s ← s.addConst ``dif_neg
|
||||
return {
|
||||
simpTheorems := #[s]
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := { Simp.neutralConfig with dsimp := false }
|
||||
}
|
||||
Simp.mkContext
|
||||
(simpTheorems := #[s])
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := { Simp.neutralConfig with dsimp := false })
|
||||
|
||||
/--
|
||||
Default `discharge?` function for `simpIf` methods.
|
||||
|
||||
@@ -10,11 +10,10 @@ import Lean.Meta.Tactic.Simp.Main
|
||||
|
||||
namespace Lean.Meta
|
||||
|
||||
private def getSimpUnfoldContext : MetaM Simp.Context :=
|
||||
return {
|
||||
congrTheorems := (← getSimpCongrTheorems)
|
||||
config := Simp.neutralConfig
|
||||
}
|
||||
private def getSimpUnfoldContext : MetaM Simp.Context := do
|
||||
Simp.mkContext
|
||||
(congrTheorems := (← getSimpCongrTheorems))
|
||||
(config := Simp.neutralConfig)
|
||||
|
||||
def unfold (e : Expr) (declName : Name) : MetaM Simp.Result := do
|
||||
if let some unfoldThm ← getUnfoldEqnFor? declName then
|
||||
|
||||
@@ -96,7 +96,7 @@ builtin_initialize
|
||||
|
||||
def tryUnificationHints (t s : Expr) : MetaM Bool := do
|
||||
trace[Meta.isDefEq.hint] "{t} =?= {s}"
|
||||
unless (← read).config.unificationHints do
|
||||
unless (← getConfig).unificationHints do
|
||||
return false
|
||||
if t.isMVar then
|
||||
return false
|
||||
|
||||
@@ -529,7 +529,7 @@ private def whnfMatcher (e : Expr) : MetaM Expr := do
|
||||
TODO: consider other solutions; investigate whether the solution above produces counterintuitive behavior. -/
|
||||
if (← getTransparency) matches .instances | .reducible then
|
||||
-- Also unfold some default-reducible constants; see `canUnfoldAtMatcher`
|
||||
withTransparency .instances <| withReader (fun ctx => { ctx with canUnfold? := canUnfoldAtMatcher }) do
|
||||
withTransparency .instances <| withCanUnfoldPred canUnfoldAtMatcher do
|
||||
whnf e
|
||||
else
|
||||
-- Do NOT use `canUnfoldAtMatcher` here as it does not affect all/default reducibility and inhibits caching (#2564).
|
||||
|
||||
@@ -205,7 +205,7 @@ def replaceLPsWithVars (e : Expr) : MetaM Expr := do
|
||||
| l => if !l.hasParam then some l else none
|
||||
|
||||
def isDefEqAssigning (t s : Expr) : MetaM Bool := do
|
||||
withReader (fun ctx => { ctx with config := { ctx.config with assignSyntheticOpaque := true }}) $
|
||||
withConfig (fun cfg => { cfg with assignSyntheticOpaque := true }) do
|
||||
Meta.isDefEq t s
|
||||
|
||||
def checkpointDefEq (t s : Expr) : MetaM Bool := do
|
||||
@@ -624,7 +624,7 @@ open TopDownAnalyze SubExpr
|
||||
def topDownAnalyze (e : Expr) : MetaM OptionsPerPos := do
|
||||
let s₀ ← get
|
||||
withTraceNode `pp.analyze (fun _ => return e) do
|
||||
withReader (fun ctx => { ctx with config := Elab.Term.setElabConfig ctx.config }) do
|
||||
withConfig Elab.Term.setElabConfig do
|
||||
let ϕ : AnalyzeM OptionsPerPos := do withNewMCtxDepth analyze; pure (← get).annotations
|
||||
try
|
||||
let knowsType := getPPAnalyzeKnowsType (← getOptions)
|
||||
|
||||
@@ -1617,7 +1617,16 @@ static inline uint8_t lean_int_dec_nonneg(b_lean_obj_arg a) {
|
||||
|
||||
/* Bool */
|
||||
|
||||
static inline uint64_t lean_bool_to_uint64(uint8_t a) { return ((uint64_t)a); }
|
||||
static inline uint8_t lean_bool_to_uint8(uint8_t a) { return a; }
|
||||
static inline uint16_t lean_bool_to_uint16(uint8_t a) { return (uint16_t)a; }
|
||||
static inline uint32_t lean_bool_to_uint32(uint8_t a) { return (uint32_t)a; }
|
||||
static inline uint64_t lean_bool_to_uint64(uint8_t a) { return (uint64_t)a; }
|
||||
static inline size_t lean_bool_to_usize(uint8_t a) { return (size_t)a; }
|
||||
static inline uint8_t lean_bool_to_int8(uint8_t a) { return (uint8_t)(int8_t)a; }
|
||||
static inline uint16_t lean_bool_to_int16(uint8_t a) { return (uint16_t)(int16_t)a; }
|
||||
static inline uint32_t lean_bool_to_int32(uint8_t a) { return (uint32_t)(int32_t)a; }
|
||||
static inline uint64_t lean_bool_to_int64(uint8_t a) { return (uint64_t)(int64_t)a; }
|
||||
static inline size_t lean_bool_to_isize(uint8_t a) { return (size_t)(ptrdiff_t)a; }
|
||||
|
||||
|
||||
/* UInt8 */
|
||||
|
||||
@@ -24,12 +24,14 @@ s!"/{defaultLakeDir}
|
||||
"
|
||||
|
||||
def basicFileContents :=
|
||||
s!"def hello := \"world\""
|
||||
s!"def hello := \"world\"
|
||||
"
|
||||
|
||||
def libRootFileContents (libName : String) (libRoot : Name) :=
|
||||
s!"-- This module serves as the root of the `{libName}` library.
|
||||
-- Import modules here that should be built as part of the library.
|
||||
import {libRoot}.Basic"
|
||||
import {libRoot}.Basic
|
||||
"
|
||||
|
||||
def mainFileName : FilePath :=
|
||||
s!"{defaultExeRoot}.lean"
|
||||
|
||||
@@ -515,7 +515,7 @@ protected def translateConfig : CliM PUnit := do
|
||||
if outFile?.isNone then
|
||||
IO.FS.rename pkg.configFile (pkg.configFile.addExtension "bak")
|
||||
|
||||
def ReservoirConfig.currentSchemaVersion : StdVer := v!"1.0.0"
|
||||
def ReservoirConfig.currentSchemaVersion : StdVer := {major := 1}
|
||||
|
||||
structure ReservoirConfig where
|
||||
name : String
|
||||
|
||||
@@ -119,7 +119,7 @@ def PackageConfig.mkSyntax (cfg : PackageConfig)
|
||||
|> addDeclFieldD `testDriverArgs cfg.testDriverArgs #[]
|
||||
|> addDeclFieldD `lintDriver lintDriver ""
|
||||
|> addDeclFieldD `lintDriverArgs cfg.lintDriverArgs #[]
|
||||
|> addDeclFieldD `version cfg.version v!"0.0.0"
|
||||
|> addDeclFieldD `version cfg.version {}
|
||||
|> addDeclField? `versionTags (quoteVerTags? cfg.versionTags)
|
||||
|> addDeclFieldD `description cfg.description ""
|
||||
|> addDeclFieldD `keywords cfg.keywords #[]
|
||||
|
||||
@@ -76,7 +76,7 @@ protected def PackageConfig.toToml (cfg : PackageConfig) (t : Table := {}) : Tab
|
||||
|>.smartInsert `releaseRepo (cfg.releaseRepo <|> cfg.releaseRepo?)
|
||||
|>.insertD `buildArchive (cfg.buildArchive?.getD cfg.buildArchive) (defaultBuildArchive cfg.name)
|
||||
|>.insertD `preferReleaseBuild cfg.preferReleaseBuild false
|
||||
|>.insertD `version cfg.version v!"0.0.0"
|
||||
|>.insertD `version cfg.version {}
|
||||
|> smartInsertVerTags cfg.versionTags
|
||||
|>.smartInsert `keywords cfg.description
|
||||
|>.smartInsert `keywords cfg.keywords
|
||||
|
||||
@@ -275,7 +275,7 @@ structure PackageConfig extends WorkspaceConfig, LeanConfig where
|
||||
|
||||
Packages without a defined version default to `0.0.0`.
|
||||
-/
|
||||
version : StdVer := v!"0.0.0"
|
||||
version : StdVer := {}
|
||||
|
||||
/--
|
||||
Git tags of this package's repository that should be treated as versions.
|
||||
|
||||
@@ -49,7 +49,7 @@ That is, Lake ignores the `-` suffix.
|
||||
- `"1.0.0"`: Switches to a semantic versioning scheme
|
||||
- `"1.1.0"`: Add optional `scope` package entry field
|
||||
-/
|
||||
@[inline] def Manifest.version : StdVer := v!"1.1.0"
|
||||
@[inline] def Manifest.version : StdVer := {major := 1, minor := 1}
|
||||
|
||||
/-- Manifest version `0.6.0` package entry. For backwards compatibility. -/
|
||||
inductive PackageEntryV6
|
||||
@@ -201,14 +201,14 @@ protected def fromJson? (json : Json) : Except String Manifest := do
|
||||
if ver.major > 1 then
|
||||
throw s!"manifest version '{ver}' is of a higher major version than this \
|
||||
Lake's '{Manifest.version}'; you may need to update your 'lean-toolchain'"
|
||||
else if ver < v!"0.5.0" then
|
||||
else if ver < {minor := 5} then
|
||||
throw s!"incompatible manifest version '{ver}'"
|
||||
else
|
||||
let name ← obj.getD "name" Name.anonymous
|
||||
let lakeDir ← obj.getD "lakeDir" defaultLakeDir
|
||||
let packagesDir? ← obj.get? "packagesDir"
|
||||
let packages ←
|
||||
if ver < v!"0.7.0" then
|
||||
if ver < {minor := 7} then
|
||||
(·.map PackageEntry.ofV6) <$> obj.getD "packages" #[]
|
||||
else
|
||||
obj.getD "packages" #[]
|
||||
|
||||
@@ -207,7 +207,7 @@ protected def PackageConfig.decodeToml (t : Table) (ref := Syntax.missing) : Exc
|
||||
let testDriverArgs ← t.tryDecodeD `testDriverArgs #[]
|
||||
let lintDriver ← t.tryDecodeD `lintDriver ""
|
||||
let lintDriverArgs ← t.tryDecodeD `lintDriverArgs #[]
|
||||
let version : StdVer ← t.tryDecodeD `version v!"0.0.0"
|
||||
let version : StdVer ← t.tryDecodeD `version {}
|
||||
let versionTags ← optDecodeD defaultVersionTags (t.find? `versionTags)
|
||||
<| StrPat.decodeToml (presets := versionTagPresets)
|
||||
let description ← t.tryDecodeD `description ""
|
||||
|
||||
29
tests/bench/simp_arith1.lean
Normal file
29
tests/bench/simp_arith1.lean
Normal file
@@ -0,0 +1,29 @@
|
||||
import Lean
|
||||
|
||||
open Lean Meta Elab in
|
||||
elab "largeGoal%" : term =>
|
||||
let n := 30 -- number of variables
|
||||
let r := 3 -- number of repetitions
|
||||
let mkAdd := mkApp2 (mkConst ``Nat.add)
|
||||
let mkMul := mkApp2 (mkConst ``Nat.mul)
|
||||
let decls := Array.ofFn fun (i : Fin n) =>
|
||||
((`x).appendIndexAfter i, (fun _ => pure (mkConst ``Nat)))
|
||||
withLocalDeclsD decls fun xs => do
|
||||
let mut e₁ : Expr := mkNatLit 42
|
||||
let mut e₂ : Expr := mkNatLit 23
|
||||
for _ in [:r] do
|
||||
for i in [:xs.size] do
|
||||
e₁ := mkAdd (mkMul (mkNatLit i) e₁) xs[i]!
|
||||
e₂ := mkAdd xs[i]! (mkMul e₂ (mkNatLit (xs.size - i)))
|
||||
let goal ← mkEq e₁ e₂
|
||||
let goal := mkNot goal
|
||||
let goal ← mkForallFVars xs goal
|
||||
return goal
|
||||
|
||||
set_option maxRecDepth 10000
|
||||
|
||||
-- manually verified: most time spent in type-checking
|
||||
-- set_option trace.profiler true
|
||||
example : largeGoal% := by
|
||||
intros
|
||||
simp_arith only
|
||||
@@ -316,6 +316,12 @@
|
||||
run_config:
|
||||
<<: *time
|
||||
cmd: lean reduceMatch.lean
|
||||
- attributes:
|
||||
description: simp_arith1
|
||||
tags: [fast, suite]
|
||||
run_config:
|
||||
<<: *time
|
||||
cmd: lean simp_arith1.lean
|
||||
- attributes:
|
||||
description: nat_repr
|
||||
tags: [fast, suite]
|
||||
|
||||
@@ -56,8 +56,8 @@ a : α
|
||||
• Fam2.any : Fam2 α α @ ⟨9, 4⟩†-⟨9, 12⟩†
|
||||
• α : Type @ ⟨9, 4⟩†-⟨9, 12⟩†
|
||||
• a (isBinder := true) : α @ ⟨8, 2⟩†-⟨10, 19⟩†
|
||||
• FVarAlias a: _uniq.632 -> _uniq.312
|
||||
• FVarAlias α: _uniq.631 -> _uniq.310
|
||||
• FVarAlias a: _uniq.585 -> _uniq.312
|
||||
• FVarAlias α: _uniq.584 -> _uniq.310
|
||||
• ?m x α a : α @ ⟨9, 18⟩-⟨9, 19⟩ @ Lean.Elab.Term.elabHole
|
||||
• [.] Fam2.nat : none @ ⟨10, 4⟩-⟨10, 12⟩
|
||||
• Fam2.nat : Nat → Fam2 Nat Nat @ ⟨10, 4⟩-⟨10, 12⟩
|
||||
@@ -71,8 +71,8 @@ a : α
|
||||
• Fam2.nat n : Fam2 Nat Nat @ ⟨10, 4⟩†-⟨10, 14⟩
|
||||
• n (isBinder := true) : Nat @ ⟨10, 13⟩-⟨10, 14⟩
|
||||
• a (isBinder := true) : Nat @ ⟨8, 2⟩†-⟨10, 19⟩†
|
||||
• FVarAlias a: _uniq.663 -> _uniq.312
|
||||
• FVarAlias n: _uniq.662 -> _uniq.310
|
||||
• FVarAlias a: _uniq.616 -> _uniq.312
|
||||
• FVarAlias n: _uniq.615 -> _uniq.310
|
||||
• n : Nat @ ⟨10, 18⟩-⟨10, 19⟩ @ Lean.Elab.Term.elabIdent
|
||||
• [.] n : some Nat @ ⟨10, 18⟩-⟨10, 19⟩
|
||||
• n : Nat @ ⟨10, 18⟩-⟨10, 19⟩
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
1081.lean:7:2-7:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f 0 y = f 0 y : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
f 0 y = y : Prop
|
||||
1081.lean:23:4-23:7: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
insert a ⟨0, ⋯⟩ v = insert a ⟨0, ⋯⟩ v : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
insert a ⟨0, ⋯⟩ v = cons a v : Prop
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
1433.lean:11:49-11:52: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
dividend % divisor = dividend % divisor : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
dividend % divisor = wrongRem : Prop
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
set_option pp.mvars false
|
||||
|
||||
def Additive (α : Type) := α
|
||||
|
||||
instance [OfNat α 1] : OfNat (Additive α) (nat_lit 0) := ⟨(1 : α)⟩
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
755.lean:5:44-5:47: error: type mismatch
|
||||
755.lean:7:44-7:47: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
0 = @OfNat.ofNat Nat 0 (instOfNatNat 0) : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
0 = @OfNat.ofNat (Additive Nat) 0 instOfNatAdditiveOfOfNatNat : Prop
|
||||
755.lean:24:2-24:5: error: type mismatch
|
||||
0 = 0 : Prop
|
||||
755.lean:26:2-26:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
2 * 3 = @HMul.hMul Nat Nat Nat instHMul 2 3 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
2 * 3 = @HMul.hMul (Foo Nat) (Foo Nat) (Foo Nat) instHMulFooOfHAdd 2 3 : Prop
|
||||
755.lean:27:2-27:5: error: type mismatch
|
||||
2 * 3 = 2 * 3 : Prop
|
||||
755.lean:29:2-29:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
2 + 3 = @HAdd.hAdd Nat Nat Nat instHAdd 2 3 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
2 + 3 = @HAdd.hAdd (Foo Nat) (Foo Nat) (Foo Nat) instHAddFoo 2 3 : Prop
|
||||
755.lean:30:2-30:5: error: type mismatch
|
||||
2 + 3 = 2 + 3 : Prop
|
||||
755.lean:32:2-32:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
2 - 3 = @HSub.hSub Nat Nat Nat instHSub 2 3 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
2 - 3 = @HSub.hSub (Foo Nat) (Foo Nat) (Foo Nat) instHSubFooOfHAdd 2 3 : Prop
|
||||
2 - 3 = 2 - 3 : Prop
|
||||
|
||||
20
tests/lean/bool2int.lean
Normal file
20
tests/lean/bool2int.lean
Normal file
@@ -0,0 +1,20 @@
|
||||
#eval Bool.toUInt8 false = 0
|
||||
#eval Bool.toUInt8 true = 1
|
||||
#eval Bool.toUInt16 false = 0
|
||||
#eval Bool.toUInt16 true = 1
|
||||
#eval Bool.toUInt32 false = 0
|
||||
#eval Bool.toUInt32 true = 1
|
||||
#eval Bool.toUInt64 false = 0
|
||||
#eval Bool.toUInt64 true = 1
|
||||
#eval Bool.toUSize false = 0
|
||||
#eval Bool.toUSize true = 1
|
||||
#eval Bool.toInt8 false = 0
|
||||
#eval Bool.toInt8 true = 1
|
||||
#eval Bool.toInt16 false = 0
|
||||
#eval Bool.toInt16 true = 1
|
||||
#eval Bool.toInt32 false = 0
|
||||
#eval Bool.toInt32 true = 1
|
||||
#eval Bool.toInt64 false = 0
|
||||
#eval Bool.toInt64 true = 1
|
||||
#eval Bool.toISize false = 0
|
||||
#eval Bool.toISize true = 1
|
||||
20
tests/lean/bool2int.lean.expected.out
Normal file
20
tests/lean/bool2int.lean.expected.out
Normal file
@@ -0,0 +1,20 @@
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
@@ -1,7 +1,7 @@
|
||||
calcErrors.lean:7:30-7:33: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
b + b = b + b : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
b + b = 0 + c + b : Prop
|
||||
calcErrors.lean:13:8-13:29: error: invalid 'calc' step, left-hand side is
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
The functions inserted for the coercions are supposed to be inlined immediately during elaboration.
|
||||
-/
|
||||
|
||||
set_option pp.mvars false
|
||||
|
||||
variable (p : Nat → Prop) (m : IO (Subtype p))
|
||||
|
||||
/-!
|
||||
@@ -15,3 +17,18 @@ variable (p : Nat → Prop) (m : IO (Subtype p))
|
||||
`Lean.Internal.coeM`
|
||||
-/
|
||||
#check (m : IO Nat)
|
||||
|
||||
/-!
|
||||
Making sure the monad lift coercion elaborator does not have side effects.
|
||||
|
||||
It used to be responsible for hinting that the LHSs of equalities were defeq, like in the following example.
|
||||
It was checking that `Eq (some true)` and `Eq _` were defeq monads. The defeq check caused `_` to be solved as `some true`.
|
||||
-/
|
||||
/--
|
||||
error: invalid dotted identifier notation, expected type is not of the form (... → C ...) where C is a constant
|
||||
?_
|
||||
-/
|
||||
#guard_msgs in
|
||||
example : some true = (some true).map id := by
|
||||
refine show _ = .some true from ?_
|
||||
rfl
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
etaStructIssue.lean:20:2-20:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
mkNat e x₁ = mkNat e x₁ : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
mkNat e x₁ = mkNat e.mk x₂ : Prop
|
||||
|
||||
7
tests/lean/interactive/builtinCodeactions.lean
Normal file
7
tests/lean/interactive/builtinCodeactions.lean
Normal file
@@ -0,0 +1,7 @@
|
||||
/-- Must not introduce line break between `at` and `h` -/
|
||||
example {a b c d : Nat} (h : a = b)
|
||||
(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA : b = c)
|
||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa : c = d) :
|
||||
a = b := by
|
||||
simp? [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] at h
|
||||
--^ codeAction
|
||||
13
tests/lean/interactive/builtinCodeactions.lean.expected.out
Normal file
13
tests/lean/interactive/builtinCodeactions.lean.expected.out
Normal file
@@ -0,0 +1,13 @@
|
||||
{"title":
|
||||
"Try this: simp only [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] at h",
|
||||
"kind": "quickfix",
|
||||
"isPreferred": true,
|
||||
"edit":
|
||||
{"documentChanges":
|
||||
[{"textDocument": {"version": 1, "uri": "file:///builtinCodeactions.lean"},
|
||||
"edits":
|
||||
[{"range":
|
||||
{"start": {"line": 5, "character": 2},
|
||||
"end": {"line": 5, "character": 97}},
|
||||
"newText":
|
||||
"simp only [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] at h"}]}]}}
|
||||
@@ -1,6 +1,6 @@
|
||||
isDefEqOffsetBug.lean:19:2-19:5: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
0 + 0 = 0 + 0 : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
0 + 0 = 0 : Prop
|
||||
|
||||
@@ -8,16 +8,10 @@ the following variables have been introduced by the implicit lambda feature
|
||||
a✝ : Bool
|
||||
b✝ : Bool
|
||||
you can disable implicit lambdas using `@` or writing a lambda expression with `{}` or `[]` binder annotations.
|
||||
mulcommErrorMessage.lean:11:22-11:25: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
true = true : Prop
|
||||
but is expected to have type
|
||||
true = false : Prop
|
||||
mulcommErrorMessage.lean:12:22-12:25: error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
false = false : Prop
|
||||
?m = ?m : Prop
|
||||
but is expected to have type
|
||||
false = true : Prop
|
||||
mulcommErrorMessage.lean:16:3-17:47: error: type mismatch
|
||||
|
||||
@@ -5,4 +5,4 @@ argument
|
||||
has type
|
||||
@PersistentHashMap Nat Nat instBEqOfDecidableEq instHashableNat : Type
|
||||
but is expected to have type
|
||||
@PersistentHashMap Nat Nat instBEqOfDecidableEq natDiffHash : Type
|
||||
@PersistentHashMap Nat Nat ?m natDiffHash : Type
|
||||
|
||||
@@ -25,7 +25,7 @@ def isFinite : Prop :=
|
||||
|
||||
instance hasNextWF : WellFoundedRelation {s : ρ // isFinite s} where
|
||||
rel := λ s1 s2 => hasNext s2.val s1.val
|
||||
wf := ⟨λ ⟨s,h⟩ => ⟨⟨s,h⟩, by
|
||||
wf := ⟨λ ⟨s,h⟩ => ⟨Subtype.mk s h, by
|
||||
simp only [Subtype.forall]
|
||||
cases h; case intro w h =>
|
||||
induction w generalizing s
|
||||
|
||||
24
tests/lean/run/3150.lean
Normal file
24
tests/lean/run/3150.lean
Normal file
@@ -0,0 +1,24 @@
|
||||
class One (α : Type) where
|
||||
one : α
|
||||
|
||||
variable (R A : Type) [One R] [One A]
|
||||
|
||||
class OneHom where
|
||||
toFun : R → A
|
||||
map_one : toFun One.one = One.one
|
||||
|
||||
structure Subone where
|
||||
mem : R → Prop
|
||||
one_mem : mem One.one
|
||||
|
||||
structure Subalgebra [OneHom R A] extends Subone A : Type where
|
||||
algebraMap_mem : ∀ r : R, mem (OneHom.toFun r)
|
||||
one_mem := OneHom.map_one (R := R) (A := A) ▸ algebraMap_mem One.one
|
||||
|
||||
/--
|
||||
error: fields missing: 'one_mem'
|
||||
-/
|
||||
#guard_msgs in
|
||||
example [OneHom R A] : Subalgebra R A where
|
||||
mem := _
|
||||
algebraMap_mem := _
|
||||
@@ -4,13 +4,13 @@ set_option pp.mvars false
|
||||
|
||||
/--
|
||||
error: application type mismatch
|
||||
⟨Nat.lt_irrefl ↑(?_ n), Fin.is_lt (?_ n)⟩
|
||||
⟨Nat.lt_irrefl (?_ n), Fin.is_lt ?_⟩
|
||||
argument
|
||||
Fin.is_lt (?_ n)
|
||||
Fin.is_lt ?_
|
||||
has type
|
||||
↑(?_ n) < ?_ n : Prop
|
||||
↑?_ < ?_ : Prop
|
||||
but is expected to have type
|
||||
↑(?_ n) < ↑(?_ n) : Prop
|
||||
?_ n < ?_ n : Prop
|
||||
-/
|
||||
#guard_msgs in
|
||||
def foo := fun n => (not_and_self_iff _).mp ⟨Nat.lt_irrefl _, Fin.is_lt _⟩
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
set_option pp.mvars false
|
||||
|
||||
structure Note where
|
||||
pitch : UInt64
|
||||
start : Nat
|
||||
@@ -16,13 +18,13 @@ theorem Note.self_containsNote_lowerSemitone_self (n : Note) :
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
n = n : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
n = n - 1 : Prop
|
||||
-/
|
||||
#guard_msgs in
|
||||
set_option maxRecDepth 100 in
|
||||
set_option maxHeartbeats 100 in
|
||||
set_option maxHeartbeats 200 in
|
||||
example (n : UInt64) : n = n - 1 :=
|
||||
rfl
|
||||
|
||||
|
||||
@@ -328,9 +328,11 @@ set_option pp.analyze.explicitHoles false in
|
||||
#testDelab ∀ {α : Sort u} {β : α → Sort v} {f₁ f₂ : (x : α) → β x}, (∀ (x : α), f₁ x = f₂ _) → f₁ = f₂
|
||||
expecting ∀ {α : Sort u} {β : α → Sort v} {f₁ f₂ : (x : α) → β x}, (∀ (x : α), f₁ x = f₂ x) → f₁ = f₂
|
||||
|
||||
/- TODO(kmill) 2024-11-10 fix the following test
|
||||
set_option pp.analyze.trustSubtypeMk true in
|
||||
#testDelab fun (n : Nat) (val : List Nat) (property : List.length val = n) => List.length { val := val, property := property : { x : List Nat // List.length x = n } }.val = n
|
||||
expecting fun n val property => (Subtype.val (p := fun x => x.length = n) (⟨val, property⟩ : { x : List Nat // x.length = n })).length = n
|
||||
-/
|
||||
|
||||
#testDelabN Nat.brecOn
|
||||
#testDelabN Nat.below
|
||||
|
||||
26
tests/lean/run/messageKind.lean
Normal file
26
tests/lean/run/messageKind.lean
Normal file
@@ -0,0 +1,26 @@
|
||||
import Lean.Elab.Command
|
||||
|
||||
open Lean Elab Command
|
||||
|
||||
elab tk:"#guard_msg_kind " kind:ident " in " cmd:command : command => do
|
||||
let initMsgs ← modifyGet fun st => (st.messages, {st with messages := {}})
|
||||
elabCommandTopLevel cmd
|
||||
let msgs ← modifyGet fun st => (st.messages, {st with messages := initMsgs})
|
||||
let kind := kind.getId
|
||||
for msg in msgs.toList do
|
||||
if msg.kind != kind then
|
||||
logErrorAt tk s!"expected {kind}, got {msg.kind}"
|
||||
|
||||
/- Test inferring kind from a tag. -/
|
||||
#guard_msg_kind custom in
|
||||
run_cmd do logInfo <| .tagged `custom ""
|
||||
|
||||
/- Test trace message kind. -/
|
||||
#guard_msg_kind trace in
|
||||
set_option trace.Elab.step true in
|
||||
def trace := ()
|
||||
|
||||
/- Test linter kind. -/
|
||||
#guard_msg_kind linter.unusedVariables in
|
||||
#guard_msgs (info) in -- hack to avoid re-triggering the linter
|
||||
def unused (x : Unit) := ()
|
||||
@@ -1,10 +1,11 @@
|
||||
@[irreducible] def f (x : Nat) := x + 1
|
||||
set_option allowUnsafeReducibility true
|
||||
set_option pp.mvars false
|
||||
/--
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
@@ -22,7 +23,7 @@ end
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
@@ -38,7 +39,7 @@ end Boo
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
@@ -54,7 +55,7 @@ example : f x = x + 1 :=
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
set_option pp.mvars false
|
||||
|
||||
def f (x : Nat) := x + 1
|
||||
|
||||
example : f x = x + 1 := rfl
|
||||
@@ -6,7 +8,7 @@ example : f x = x + 1 := rfl
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
@@ -22,7 +24,7 @@ seal f
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
f x = f x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
f x = x + 1 : Prop
|
||||
-/
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Tests that definitions by well-founded recursion are irreducible.
|
||||
-/
|
||||
|
||||
set_option pp.mvars false
|
||||
|
||||
def foo : Nat → Nat
|
||||
| 0 => 0
|
||||
| n+1 => foo n
|
||||
@@ -11,7 +13,7 @@ termination_by n => n
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
foo 0 = foo 0 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
foo 0 = 0 : Prop
|
||||
-/
|
||||
@@ -22,7 +24,7 @@ example : foo 0 = 0 := rfl
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
foo (n + 1) = foo (n + 1) : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
foo (n + 1) = foo n : Prop
|
||||
-/
|
||||
@@ -70,7 +72,7 @@ end Unsealed
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
foo 0 = foo 0 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
foo 0 = 0 : Prop
|
||||
-/
|
||||
@@ -89,7 +91,7 @@ termination_by n => n
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
foo = foo : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
foo = bar : Prop
|
||||
-/
|
||||
@@ -114,7 +116,7 @@ seal baz in
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
baz 0 = baz 0 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
baz 0 = 0 : Prop
|
||||
-/
|
||||
@@ -136,7 +138,7 @@ seal quux in
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
quux 0 = quux 0 : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
quux 0 = 0 : Prop
|
||||
-/
|
||||
|
||||
@@ -5,11 +5,12 @@ import UserAttr.BlaAttr
|
||||
|
||||
attribute [local irreducible] myFun
|
||||
|
||||
set_option pp.mvars false
|
||||
/--
|
||||
error: type mismatch
|
||||
rfl
|
||||
has type
|
||||
myFun x = myFun x : Prop
|
||||
?_ = ?_ : Prop
|
||||
but is expected to have type
|
||||
myFun x = x + 1 : Prop
|
||||
-/
|
||||
|
||||
Reference in New Issue
Block a user