diff --git a/src/Init/Control/Except.lean b/src/Init/Control/Except.lean index 01fa752649f8..bfbc86b23675 100644 --- a/src/Init/Control/Except.lean +++ b/src/Init/Control/Except.lean @@ -128,7 +128,7 @@ end Except /-- Adds exceptions of type `ε` to a monad `m`. -/ -def ExceptT (ε : Type u) (m : Type u → Type v) (α : Type u) : Type v := +@[instance_reducible] def ExceptT (ε : Type u) (m : Type u → Type v) (α : Type u) : Type v := m (Except ε α) /-- diff --git a/src/Init/Control/ExceptCps.lean b/src/Init/Control/ExceptCps.lean index d38cbd99b91b..b62837f4e0c4 100644 --- a/src/Init/Control/ExceptCps.lean +++ b/src/Init/Control/ExceptCps.lean @@ -21,7 +21,7 @@ Adds exceptions of type `ε` to a monad `m`. Instead of using `Except ε` to model exceptions, this implementation uses continuation passing style. This has different performance characteristics from `ExceptT ε`. -/ -@[expose] def ExceptCpsT (ε : Type u) (m : Type u → Type v) (α : Type u) := (β : Type u) → (α → m β) → (ε → m β) → m β +@[expose, instance_reducible] def ExceptCpsT (ε : Type u) (m : Type u → Type v) (α : Type u) := (β : Type u) → (α → m β) → (ε → m β) → m β namespace ExceptCpsT diff --git a/src/Init/Control/Id.lean b/src/Init/Control/Id.lean index b3e1016359bc..9efd42c952e6 100644 --- a/src/Init/Control/Id.lean +++ b/src/Init/Control/Id.lean @@ -36,7 +36,7 @@ def containsFive (xs : List Nat) : Bool := Id.run do true ``` -/ -@[expose] def Id (type : Type u) : Type u := type +@[expose, instance_reducible] def Id (type : Type u) : Type u := type namespace Id diff --git a/src/Init/Control/Lawful/MonadLift/Instances.lean b/src/Init/Control/Lawful/MonadLift/Instances.lean index a15130c871a3..7454ed9dc961 100644 --- a/src/Init/Control/Lawful/MonadLift/Instances.lean +++ b/src/Init/Control/Lawful/MonadLift/Instances.lean @@ -103,11 +103,11 @@ namespace StateRefT' instance {ω σ : Type} {m : Type → Type} [Monad m] : LawfulMonadLift m (StateRefT' ω σ m) where monadLift_pure _ := by simp only [MonadLift.monadLift, pure] - unfold StateRefT'.lift instMonad._aux_5 ReaderT.pure + unfold StateRefT'.lift ReaderT.pure simp only monadLift_bind _ _ := by simp only [MonadLift.monadLift, bind] - unfold StateRefT'.lift instMonad._aux_13 ReaderT.bind + unfold StateRefT'.lift ReaderT.bind simp only end StateRefT' diff --git a/src/Init/Control/Option.lean b/src/Init/Control/Option.lean index 56688d610d65..c4bd8f1d56f1 100644 --- a/src/Init/Control/Option.lean +++ b/src/Init/Control/Option.lean @@ -21,7 +21,7 @@ instance : ToBool (Option α) := ⟨Option.isSome⟩ Adds the ability to fail to a monad. Unlike ordinary exceptions, there is no way to signal why a failure occurred. -/ -@[expose] def OptionT (m : Type u → Type v) (α : Type u) : Type v := +@[expose, instance_reducible] def OptionT (m : Type u → Type v) (α : Type u) : Type v := m (Option α) /-- diff --git a/src/Init/Control/State.lean b/src/Init/Control/State.lean index 4106ebc8da41..e564f24c8809 100644 --- a/src/Init/Control/State.lean +++ b/src/Init/Control/State.lean @@ -22,7 +22,7 @@ Adds a mutable state of type `σ` to a monad. Actions in the resulting monad are functions that take an initial state and return, in `m`, a tuple of a value and a state. -/ -@[expose] def StateT (σ : Type u) (m : Type u → Type v) (α : Type u) : Type (max u v) := +@[expose, instance_reducible] def StateT (σ : Type u) (m : Type u → Type v) (α : Type u) : Type (max u v) := σ → m (α × σ) /-- diff --git a/src/Init/Control/StateCps.lean b/src/Init/Control/StateCps.lean index 96a533956938..46173ae90577 100644 --- a/src/Init/Control/StateCps.lean +++ b/src/Init/Control/StateCps.lean @@ -21,7 +21,7 @@ The State monad transformer using CPS style. An alternative implementation of a state monad transformer that internally uses continuation passing style instead of tuples. -/ -@[expose] def StateCpsT (σ : Type u) (m : Type u → Type v) (α : Type u) := (δ : Type u) → σ → (α → σ → m δ) → m δ +@[expose, instance_reducible] def StateCpsT (σ : Type u) (m : Type u → Type v) (α : Type u) := (δ : Type u) → σ → (α → σ → m δ) → m δ namespace StateCpsT diff --git a/src/Init/Control/StateRef.lean b/src/Init/Control/StateRef.lean index 833811aa9685..5150269359a0 100644 --- a/src/Init/Control/StateRef.lean +++ b/src/Init/Control/StateRef.lean @@ -20,7 +20,7 @@ A state monad that uses an actual mutable reference cell (i.e. an `ST.Ref ω σ` The macro `StateRefT σ m α` infers `ω` from `m`. It should normally be used instead. -/ -@[expose] def StateRefT' (ω : Type) (σ : Type) (m : Type → Type) (α : Type) : Type := ReaderT (ST.Ref ω σ) m α +@[expose, instance_reducible] def StateRefT' (ω : Type) (σ : Type) (m : Type → Type) (α : Type) : Type := ReaderT (ST.Ref ω σ) m α /-! Recall that `StateRefT` is a macro that infers `ω` from the `m`. -/ diff --git a/src/Init/Core.lean b/src/Init/Core.lean index 4496fd76d775..567b3d770478 100644 --- a/src/Init/Core.lean +++ b/src/Init/Core.lean @@ -769,7 +769,7 @@ the `BEq` typeclass. Unlike `x ≠ y` (which is notation for `Ne x y`), this is `Bool` valued instead of `Prop` valued. It is mainly intended for programming applications. -/ -@[inline] def bne {α : Type u} [BEq α] (a b : α) : Bool := +@[inline, implicit_reducible] def bne {α : Type u} [BEq α] (a b : α) : Bool := !(a == b) @[inherit_doc] infix:50 " != " => bne @@ -1331,7 +1331,7 @@ def Subrelation {α : Sort u} (q r : α → α → Prop) := The inverse image of `r : β → β → Prop` by a function `α → β` is the relation `s : α → α → Prop` defined by `s a b = r (f a) (f b)`. -/ -def InvImage {α : Sort u} {β : Sort v} (r : β → β → Prop) (f : α → β) : α → α → Prop := +@[instance_reducible] def InvImage {α : Sort u} {β : Sort v} (r : β → β → Prop) (f : α → β) : α → α → Prop := fun a₁ a₂ => r (f a₁) (f a₂) /-- @@ -1478,7 +1478,7 @@ Examples: * `(1, 2).map (· + 1) (· * 3) = (2, 6)` * `(1, 2).map toString (· * 3) = ("1", 6)` -/ -def Prod.map {α₁ : Type u₁} {α₂ : Type u₂} {β₁ : Type v₁} {β₂ : Type v₂} +@[instance_reducible] def Prod.map {α₁ : Type u₁} {α₂ : Type u₂} {β₁ : Type v₁} {β₂ : Type v₂} (f : α₁ → α₂) (g : β₁ → β₂) : α₁ × β₁ → α₂ × β₂ | (a, b) => (f a, g b) diff --git a/src/Init/Data/Array/Attach.lean b/src/Init/Data/Array/Attach.lean index c1336eb5602b..9502589a50e6 100644 --- a/src/Init/Data/Array/Attach.lean +++ b/src/Init/Data/Array/Attach.lean @@ -162,6 +162,10 @@ theorem pmap_eq_map_attach {p : α → Prop} {f : ∀ a, p a → β} {xs : Array cases xs simp [List.pmap_eq_map_attach] +theorem attachWith_eq_map_attach {xs : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} : + xs.attachWith P H = xs.attach.map fun ⟨x, h⟩ => ⟨x, H _ h⟩ := by + cases xs <;> simp_all [List.attachWith_eq_map_attach] + @[simp] theorem pmap_eq_attachWith {p q : α → Prop} {f : ∀ a, p a → q a} {xs : Array α} (H) : pmap (fun a h => ⟨a, f a h⟩) xs H = xs.attachWith q (fun x h => f x (H x h)) := by diff --git a/src/Init/Data/Array/Basic.lean b/src/Init/Data/Array/Basic.lean index 3104770cdfad..836724c12e99 100644 --- a/src/Init/Data/Array/Basic.lean +++ b/src/Init/Data/Array/Basic.lean @@ -170,7 +170,7 @@ Low-level indexing operator which is as fast as a C array read. This avoids overhead due to unboxing a `Nat` used as an index. -/ -@[extern "lean_array_uget", simp, expose] +@[extern "lean_array_uget", simp, expose, instance_reducible] def uget (xs : @& Array α) (i : USize) (h : i.toNat < xs.size) : α := xs[i.toNat] @@ -189,7 +189,7 @@ in-place when the reference to the array is unique. This avoids overhead due to unboxing a `Nat` used as an index. -/ -@[extern "lean_array_uset", expose] +@[extern "lean_array_uset", expose, instance_reducible] def uset (xs : Array α) (i : USize) (v : α) (h : i.toNat < xs.size) : Array α := xs.set i.toNat v h diff --git a/src/Init/Data/Array/DecidableEq.lean b/src/Init/Data/Array/DecidableEq.lean index a7a702c66578..a4d25cabac4e 100644 --- a/src/Init/Data/Array/DecidableEq.lean +++ b/src/Init/Data/Array/DecidableEq.lean @@ -76,7 +76,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) : simpa [isEqv_iff_rel] using h' @[simp, grind =] theorem isEqv_toList [BEq α] (xs ys : Array α) : (xs.toList.isEqv ys.toList r) = (xs.isEqv ys r) := by - simp [isEqv_eq_decide, List.isEqv_eq_decide, Array.size]; rfl + simp [isEqv_eq_decide, List.isEqv_eq_decide, Array.size] theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by have ⟨h, h'⟩ := rel_of_isEqv h @@ -154,7 +154,7 @@ theorem beq_eq_decide [BEq α] (xs ys : Array α) : simp [BEq.beq, isEqv_eq_decide] @[simp, grind =] theorem beq_toList [BEq α] (xs ys : Array α) : (xs.toList == ys.toList) = (xs == ys) := by - simp [beq_eq_decide, List.beq_eq_decide, Array.size]; rfl + simp [beq_eq_decide, List.beq_eq_decide, Array.size] end Array diff --git a/src/Init/Data/Array/FinRange.lean b/src/Init/Data/Array/FinRange.lean index dc743a3d2300..d1b42035f7aa 100644 --- a/src/Init/Data/Array/FinRange.lean +++ b/src/Init/Data/Array/FinRange.lean @@ -26,7 +26,7 @@ Examples: * `Array.finRange 0 = (#[] : Array (Fin 0))` * `Array.finRange 2 = (#[0, 1] : Array (Fin 2))` -/ -protected def finRange (n : Nat) : Array (Fin n) := ofFn fun i => i +@[expose, instance_reducible] protected def finRange (n : Nat) : Array (Fin n) := ofFn fun i => i @[simp, grind =] theorem size_finRange {n} : (Array.finRange n).size = n := by simp [Array.finRange] diff --git a/src/Init/Data/Array/Lemmas.lean b/src/Init/Data/Array/Lemmas.lean index f43763fa9029..d1ba71fdab86 100644 --- a/src/Init/Data/Array/Lemmas.lean +++ b/src/Init/Data/Array/Lemmas.lean @@ -1872,7 +1872,7 @@ theorem getElem_of_append {xs ys zs : Array α} (eq : xs = ys.push a ++ zs) (h : rw [← getElem?_eq_getElem, eq, getElem?_append_left (by simp; omega), ← h] simp -@[simp] theorem append_singleton {a : α} {as : Array α} : as ++ #[a] = as.push a := rfl +@[simp] theorem append_singleton {a : α} {as : Array α} : as ++ #[a] = as.push a := (rfl) @[simp] theorem append_singleton_assoc {a : α} {xs ys : Array α} : xs ++ (#[a] ++ ys) = xs.push a ++ ys := by rw [← append_assoc, append_singleton] @@ -2833,9 +2833,8 @@ theorem getElem_extract_aux {xs : Array α} {start stop : Nat} (h : i < (xs.extr @[simp, grind =] theorem getElem_extract {xs : Array α} {start stop : Nat} (h : i < (xs.extract start stop).size) : - (xs.extract start stop)[i] = xs[start + i]'(getElem_extract_aux h) := - show (extract.loop xs (min stop xs.size - start) start #[])[i] - = xs[start + i]'(getElem_extract_aux h) by rw [getElem_extract_loop_ge]; rfl; exact Nat.zero_le _ + (xs.extract start stop)[i] = xs[start + i]'(getElem_extract_aux h) := by + simp [extract, getElem_extract_loop_ge] theorem getElem?_extract {xs : Array α} {start stop : Nat} : (xs.extract start stop)[i]? = if i < min stop xs.size - start then xs[start + i]? else none := by diff --git a/src/Init/Data/BitVec/Basic.lean b/src/Init/Data/BitVec/Basic.lean index 07c71162a302..d70b4d738d93 100644 --- a/src/Init/Data/BitVec/Basic.lean +++ b/src/Init/Data/BitVec/Basic.lean @@ -73,6 +73,7 @@ protected def zero (n : Nat) : BitVec n := .ofNatLT 0 (Nat.two_pow_pos n) instance : Inhabited (BitVec n) where default := .zero n /-- Returns a bitvector of size `n` where all bits are `1`. -/ +@[implicit_reducible] def allOnes (n : Nat) : BitVec n := .ofNatLT (2^n - 1) (Nat.le_of_eq (Nat.sub_add_cancel (Nat.two_pow_pos n))) @@ -83,7 +84,7 @@ section getXsb /-- Returns the `i`th least significant bit. -/ -@[inline] def getLsb (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i +@[inline, implicit_reducible] def getLsb (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i /-- Returns the `i`th least significant bit, or `none` if `i ≥ w`. -/ @[inline] def getLsb? (x : BitVec w) (i : Nat) : Option Bool := @@ -99,15 +100,15 @@ Returns the `i`th most significant bit. if h : i < w then some (getMsb x ⟨i, h⟩) else none /-- Returns the `i`th least significant bit or `false` if `i ≥ w`. -/ -@[inline] def getLsbD (x : BitVec w) (i : Nat) : Bool := +@[inline, implicit_reducible] def getLsbD (x : BitVec w) (i : Nat) : Bool := x.toNat.testBit i /-- Returns the `i`th most significant bit, or `false` if `i ≥ w`. -/ -@[inline] def getMsbD (x : BitVec w) (i : Nat) : Bool := +@[inline, implicit_reducible] def getMsbD (x : BitVec w) (i : Nat) : Bool := i < w && x.getLsbD (w-1-i) /-- Returns the most significant bit in a bitvector. -/ -@[inline] protected def msb (x : BitVec n) : Bool := getMsbD x 0 +@[inline, implicit_reducible] protected def msb (x : BitVec n) : Bool := getMsbD x 0 end getXsb @@ -130,7 +131,7 @@ theorem getElem_eq_testBit_toNat (x : BitVec w) (i : Nat) (h : i < w) : @[simp, grind =] theorem getLsbD_eq_getElem {x : BitVec w} {i : Nat} (h : i < w) : - x.getLsbD i = x[i] := rfl + x.getLsbD i = x[i] := (rfl) end getElem @@ -139,6 +140,7 @@ section Int /-- Interprets the bitvector as an integer stored in two's complement form. -/ +@[instance_reducible] protected def toInt (x : BitVec n) : Int := if 2 * x.toNat < 2^n then x.toNat @@ -152,6 +154,7 @@ over- and underflowing as needed. The underlying `Nat` is `(2^n + (i mod 2^n)) mod 2^n`. Converting the bitvector back to an `Int` with `BitVec.toInt` results in the value `i.bmod (2^n)`. -/ +@[implicit_reducible] protected def ofInt (n : Nat) (i : Int) : BitVec n := .ofNatLT (i % (Int.ofNat (2^n))).toNat (by apply (Int.toNat_lt _).mpr · apply Int.emod_lt_of_pos @@ -226,12 +229,14 @@ Usually accessed via the `-` prefix operator. SMT-LIB name: `bvneg`. -/ +@[instance_reducible] protected def neg (x : BitVec n) : BitVec n := .ofNat n (2^n - x.toNat) instance : Neg (BitVec n) := ⟨.neg⟩ /-- Returns the absolute value of a signed bitvector. -/ +@[implicit_reducible] protected def abs (x : BitVec n) : BitVec n := if x.msb then .neg x else x /-- @@ -240,6 +245,7 @@ modulo `2^n`. Usually accessed via the `*` operator. SMT-LIB name: `bvmul`. -/ +@[implicit_reducible] protected def mul (x y : BitVec n) : BitVec n := BitVec.ofNat n (x.toNat * y.toNat) instance : Mul (BitVec n) := ⟨.mul⟩ @@ -261,6 +267,7 @@ instance : Pow (BitVec n) Nat where Unsigned division of bitvectors using the Lean convention where division by zero returns zero. Usually accessed via the `/` operator. -/ +@[implicit_reducible] def udiv (x y : BitVec n) : BitVec n := (x.toNat / y.toNat)#'(by exact Nat.lt_of_le_of_lt (Nat.div_le_self _ _) x.isLt) instance : Div (BitVec n) := ⟨.udiv⟩ @@ -270,6 +277,7 @@ Unsigned modulo for bitvectors. Usually accessed via the `%` operator. SMT-LIB name: `bvurem`. -/ +@[implicit_reducible] def umod (x y : BitVec n) : BitVec n := (x.toNat % y.toNat)#'(by exact Nat.lt_of_le_of_lt (Nat.mod_le _ _) x.isLt) instance : Mod (BitVec n) := ⟨.umod⟩ @@ -281,6 +289,7 @@ where division by zero returns `BitVector.allOnes n`. SMT-LIB name: `bvudiv`. -/ +@[implicit_reducible] def smtUDiv (x y : BitVec n) : BitVec n := if y = 0 then allOnes n else udiv x y /-- @@ -293,6 +302,7 @@ Examples: * `(5#4).sdiv -2 = -2#4` * `(-7#4).sdiv (-2) = 3#4` -/ +@[implicit_reducible] def sdiv (x y : BitVec n) : BitVec n := match x.msb, y.msb with | false, false => udiv x y @@ -309,6 +319,7 @@ Specifically, `x.smtSDiv 0 = if x >= 0 then -1 else 1` SMT-LIB name: `bvsdiv`. -/ +@[implicit_reducible] def smtSDiv (x y : BitVec n) : BitVec n := match x.msb, y.msb with | false, false => smtUDiv x y @@ -321,6 +332,7 @@ Remainder for signed division rounding to zero. SMT-LIB name: `bvsrem`. -/ +@[implicit_reducible] def srem (x y : BitVec n) : BitVec n := match x.msb, y.msb with | false, false => umod x y @@ -333,6 +345,7 @@ Remainder for signed division rounded to negative infinity. SMT-LIB name: `bvsmod`. -/ +@[implicit_reducible] def smod (x y : BitVec m) : BitVec m := match x.msb, y.msb with | false, false => umod x y @@ -367,6 +380,7 @@ Unsigned less-than for bitvectors. SMT-LIB name: `bvult`. -/ +@[implicit_reducible] protected def ult (x y : BitVec n) : Bool := x.toNat < y.toNat /-- @@ -374,6 +388,7 @@ Unsigned less-than-or-equal-to for bitvectors. SMT-LIB name: `bvule`. -/ +@[implicit_reducible] protected def ule (x y : BitVec n) : Bool := x.toNat ≤ y.toNat /-- @@ -385,6 +400,7 @@ Examples: * `BitVec.slt 6#4 7 = true` * `BitVec.slt 7#4 8 = false` -/ +@[implicit_reducible] protected def slt (x y : BitVec n) : Bool := x.toInt < y.toInt /-- @@ -392,6 +408,7 @@ Signed less-than-or-equal-to for bitvectors. SMT-LIB name: `bvsle`. -/ +@[implicit_reducible] protected def sle (x y : BitVec n) : Bool := x.toInt ≤ y.toInt end relations @@ -405,7 +422,7 @@ width `m`. Using `x.cast eq` should be preferred over `eq ▸ x` because there are special-purpose `simp` lemmas that can more consistently simplify `BitVec.cast` away. -/ -@[inline] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq ▸ x.isLt) +@[inline, implicit_reducible] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq ▸ x.isLt) @[simp, grind =] theorem cast_ofNat {n m : Nat} (h : n = m) (x : Nat) : (BitVec.ofNat n x).cast h = BitVec.ofNat m x := by @@ -421,6 +438,7 @@ that can more consistently simplify `BitVec.cast` away. Extracts the bits `start` to `start + len - 1` from a bitvector of size `n` to yield a new bitvector of size `len`. If `start + len > n`, then the bitvector is zero-extended. -/ +@[implicit_reducible] def extractLsb' (start len : Nat) (x : BitVec n) : BitVec len := .ofNat _ (x.toNat >>> start) /-- @@ -439,6 +457,7 @@ Increases the width of a bitvector to one that is at least as large by zero-exte This is a constant-time operation because the underlying `Nat` is unmodified; because the new width is at least as large as the old one, no overflow is possible. -/ +@[implicit_reducible] def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w := x.toNat#'(by apply Nat.lt_of_lt_of_le x.isLt @@ -447,6 +466,7 @@ def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w := /-- Returns `zeroExtend (w+n) x <<< n` without needing to compute `x % 2^(2+n)`. -/ +@[implicit_reducible] def shiftLeftZeroExtend (msbs : BitVec w) (m : Nat) : BitVec (w + m) := let shiftLeftLt {x : Nat} (p : x < 2^w) (m : Nat) : x <<< m < 2^(w + m) := by simp [Nat.shiftLeft_eq, Nat.pow_add] @@ -469,6 +489,7 @@ The specific behavior depends on the relationship between the starting width `w` SMT-LIB name: `zero_extend`. -/ +@[implicit_reducible] def setWidth (v : Nat) (x : BitVec w) : BitVec v := if h : w ≤ v then setWidth' h x @@ -489,6 +510,7 @@ If `x` is an empty bitvector, then the sign is treated as zero. SMT-LIB name: `sign_extend`. -/ +@[implicit_reducible] def signExtend (v : Nat) (x : BitVec w) : BitVec v := .ofInt v x.toInt end cast @@ -503,6 +525,7 @@ SMT-LIB name: `bvand`. Example: * `0b1010#4 &&& 0b0110#4 = 0b0010#4` -/ +@[implicit_reducible] protected def and (x y : BitVec n) : BitVec n := (x.toNat &&& y.toNat)#'(by exact Nat.and_lt_two_pow x.toNat y.isLt) instance : AndOp (BitVec w) := ⟨.and⟩ @@ -515,6 +538,7 @@ SMT-LIB name: `bvor`. Example: * `0b1010#4 ||| 0b0110#4 = 0b1110#4` -/ +@[implicit_reducible] protected def or (x y : BitVec n) : BitVec n := (x.toNat ||| y.toNat)#'(by exact Nat.or_lt_two_pow x.isLt y.isLt) instance : OrOp (BitVec w) := ⟨.or⟩ @@ -527,6 +551,7 @@ SMT-LIB name: `bvxor`. Example: * `0b1010#4 ^^^ 0b0110#4 = 0b1100#4` -/ +@[implicit_reducible] protected def xor (x y : BitVec n) : BitVec n := (x.toNat ^^^ y.toNat)#'(by exact Nat.xor_lt_two_pow x.isLt y.isLt) instance : XorOp (BitVec w) := ⟨.xor⟩ @@ -539,6 +564,7 @@ SMT-LIB name: `bvnot`. Example: * `~~~(0b0101#4) == 0b1010` -/ +@[implicit_reducible] protected def not (x : BitVec n) : BitVec n := allOnes n ^^^ x instance : Complement (BitVec w) := ⟨.not⟩ @@ -548,6 +574,7 @@ equivalent to `x * 2^s`, modulo `2^n`. SMT-LIB name: `bvshl` except this operator uses a `Nat` shift value. -/ +@[implicit_reducible] protected def shiftLeft (x : BitVec n) (s : Nat) : BitVec n := BitVec.ofNat n (x.toNat <<< s) instance : HShiftLeft (BitVec w) Nat (BitVec w) := ⟨.shiftLeft⟩ @@ -559,6 +586,7 @@ As a numeric operation, this is equivalent to `x / 2^s`, rounding down. SMT-LIB name: `bvlshr` except this operator uses a `Nat` shift value. -/ +@[instance_reducible] def ushiftRight (x : BitVec n) (s : Nat) : BitVec n := (x.toNat >>> s)#'(by let ⟨x, lt⟩ := x @@ -576,6 +604,7 @@ As a numeric operation, this is equivalent to `x.toInt >>> s`. SMT-LIB name: `bvashr` except this operator uses a `Nat` shift value. -/ +@[instance_reducible] def sshiftRight (x : BitVec n) (s : Nat) : BitVec n := .ofInt n (x.toInt >>> s) instance {n} : HShiftLeft (BitVec m) (BitVec n) (BitVec m) := ⟨fun x y => x <<< y.toNat⟩ @@ -593,6 +622,7 @@ def sshiftRight' (a : BitVec n) (s : BitVec m) : BitVec n := a.sshiftRight s.toN /-- Auxiliary function for `rotateLeft`, which does not take into account the case where the rotation amount is greater than the bitvector width. -/ +@[implicit_reducible] def rotateLeftAux (x : BitVec w) (n : Nat) : BitVec w := x <<< n ||| x >>> (w - n) @@ -607,6 +637,7 @@ SMT-LIB name: `rotate_left`, except this operator uses a `Nat` shift amount. Example: * `(0b0011#4).rotateLeft 3 = 0b1001` -/ +@[implicit_reducible] def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w) @@ -614,6 +645,7 @@ def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w) Auxiliary function for `rotateRight`, which does not take into account the case where the rotation amount is greater than the bitvector width. -/ +@[implicit_reducible] def rotateRightAux (x : BitVec w) (n : Nat) : BitVec w := x >>> n ||| x <<< (w - n) @@ -628,6 +660,7 @@ SMT-LIB name: `rotate_right`, except this operator uses a `Nat` shift amount. Example: * `rotateRight 0b01001#5 1 = 0b10100` -/ +@[implicit_reducible] def rotateRight (x : BitVec w) (n : Nat) : BitVec w := rotateRightAux x (n % w) /-- @@ -639,6 +672,7 @@ SMT-LIB name: `concat`. Example: * `0xAB#8 ++ 0xCD#8 = 0xABCD#16`. -/ +@[implicit_reducible] def append (msbs : BitVec n) (lsbs : BitVec m) : BitVec (n+m) := shiftLeftZeroExtend msbs m ||| setWidth' (Nat.le_add_left m n) lsbs @@ -646,6 +680,7 @@ instance : HAppend (BitVec w) (BitVec v) (BitVec (w + v)) := ⟨.append⟩ -- TODO: write this using multiplication /-- Concatenates `i` copies of `x` into a new vector of length `w * i`. -/ +@[implicit_reducible] def replicate : (i : Nat) → BitVec w → BitVec (w*i) | 0, _ => 0#0 | n+1, x => @@ -719,20 +754,20 @@ instance : Hashable (BitVec n) where section normalization_eqs /-! We add simp-lemmas that rewrite bitvector operations into the equivalent notation -/ -@[simp, grind =] theorem append_eq (x : BitVec w) (y : BitVec v) : BitVec.append x y = x ++ y := rfl -@[simp, grind =] theorem shiftLeft_eq (x : BitVec w) (n : Nat) : BitVec.shiftLeft x n = x <<< n := rfl -@[simp, grind =] theorem ushiftRight_eq (x : BitVec w) (n : Nat) : BitVec.ushiftRight x n = x >>> n := rfl -@[simp, grind =] theorem not_eq (x : BitVec w) : BitVec.not x = ~~~x := rfl -@[simp, grind =] theorem and_eq (x y : BitVec w) : BitVec.and x y = x &&& y := rfl -@[simp, grind =] theorem or_eq (x y : BitVec w) : BitVec.or x y = x ||| y := rfl -@[simp, grind =] theorem xor_eq (x y : BitVec w) : BitVec.xor x y = x ^^^ y := rfl -@[simp, grind =] theorem neg_eq (x : BitVec w) : BitVec.neg x = -x := rfl -@[simp, grind =] theorem add_eq (x y : BitVec w) : BitVec.add x y = x + y := rfl -@[simp, grind =] theorem sub_eq (x y : BitVec w) : BitVec.sub x y = x - y := rfl -@[simp, grind =] theorem mul_eq (x y : BitVec w) : BitVec.mul x y = x * y := rfl -@[simp, grind =] theorem udiv_eq (x y : BitVec w) : BitVec.udiv x y = x / y := rfl -@[simp, grind =] theorem umod_eq (x y : BitVec w) : BitVec.umod x y = x % y := rfl -@[simp, grind =] theorem zero_eq : BitVec.zero n = 0#n := rfl +@[simp, grind =] theorem append_eq (x : BitVec w) (y : BitVec v) : BitVec.append x y = x ++ y := (rfl) +@[simp, grind =] theorem shiftLeft_eq (x : BitVec w) (n : Nat) : BitVec.shiftLeft x n = x <<< n := (rfl) +@[simp, grind =] theorem ushiftRight_eq (x : BitVec w) (n : Nat) : BitVec.ushiftRight x n = x >>> n := (rfl) +@[simp, grind =] theorem not_eq (x : BitVec w) : BitVec.not x = ~~~x := (rfl) +@[simp, grind =] theorem and_eq (x y : BitVec w) : BitVec.and x y = x &&& y := (rfl) +@[simp, grind =] theorem or_eq (x y : BitVec w) : BitVec.or x y = x ||| y := (rfl) +@[simp, grind =] theorem xor_eq (x y : BitVec w) : BitVec.xor x y = x ^^^ y := (rfl) +@[simp, grind =] theorem neg_eq (x : BitVec w) : BitVec.neg x = -x := (rfl) +@[simp, grind =] theorem add_eq (x y : BitVec w) : BitVec.add x y = x + y := (rfl) +@[simp, grind =] theorem sub_eq (x y : BitVec w) : BitVec.sub x y = x - y := (rfl) +@[simp, grind =] theorem mul_eq (x y : BitVec w) : BitVec.mul x y = x * y := (rfl) +@[simp, grind =] theorem udiv_eq (x y : BitVec w) : BitVec.udiv x y = x / y := (rfl) +@[simp, grind =] theorem umod_eq (x y : BitVec w) : BitVec.umod x y = x % y := (rfl) +@[simp, grind =] theorem zero_eq : BitVec.zero n = 0#n := (rfl) end normalization_eqs /-- Converts a list of `Bool`s into a big-endian `BitVec`. -/ @@ -823,12 +858,14 @@ def smulOverflow {w : Nat} (x y : BitVec w) : Bool := /-- Count the number of leading zeros downward from the `n`-th bit to the `0`-th bit for the bitblaster. This builds a tree of `if-then-else` lookups whose length is linear in the bitwidth, and an efficient circuit for bitblasting `clz`. -/ +@[implicit_reducible] def clzAuxRec {w : Nat} (x : BitVec w) (n : Nat) : BitVec w := match n with | 0 => if x.getLsbD 0 then BitVec.ofNat w (w - 1) else BitVec.ofNat w w | n' + 1 => if x.getLsbD n then BitVec.ofNat w (w - 1 - n) else clzAuxRec x n' /-- Count the number of leading zeros. -/ +@[implicit_reducible] def clz (x : BitVec w) : BitVec w := clzAuxRec x (w - 1) /-- Count the number of trailing zeros. -/ @@ -836,6 +873,7 @@ def ctz (x : BitVec w) : BitVec w := (x.reverse).clz /-- Count the number of bits with value `1` downward from the `pos`-th bit to the `0`-th bit of `x`, storing the result in `acc`. -/ +@[implicit_reducible] def cpopNatRec (x : BitVec w) (pos acc : Nat) : Nat := match pos with | 0 => acc @@ -844,7 +882,7 @@ def cpopNatRec (x : BitVec w) (pos acc : Nat) : Nat := /-- Population count operation, to count the number of bits with value `1` in `x`. Also known as `popcount`, `popcnt`. -/ -@[suggest_for BitVec.popcount BitVec.popcnt] +@[suggest_for BitVec.popcount BitVec.popcnt, implicit_reducible] def cpop (x : BitVec w) : BitVec w := BitVec.ofNat w (cpopNatRec x w 0) end BitVec diff --git a/src/Init/Data/BitVec/BasicAux.lean b/src/Init/Data/BitVec/BasicAux.lean index 6d544b2e3bde..87a06b3f18bf 100644 --- a/src/Init/Data/BitVec/BasicAux.lean +++ b/src/Init/Data/BitVec/BasicAux.lean @@ -38,7 +38,7 @@ Usually accessed via the `+` operator. SMT-LIB name: `bvadd`. -/ -@[expose] +@[expose, implicit_reducible] protected def add (x y : BitVec n) : BitVec n := .ofNat n (x.toNat + y.toNat) instance : Add (BitVec n) := ⟨BitVec.add⟩ @@ -47,7 +47,7 @@ Subtracts one bitvector from another. This can be interpreted as either signed o modulo `2^n`. Usually accessed via the `-` operator. -/ -@[expose] +@[expose, implicit_reducible] protected def sub (x y : BitVec n) : BitVec n := .ofNat n ((2^n - y.toNat) + x.toNat) instance : Sub (BitVec n) := ⟨BitVec.sub⟩ diff --git a/src/Init/Data/BitVec/Bitblast.lean b/src/Init/Data/BitVec/Bitblast.lean index 71c9ef5714f8..5a7c1d212510 100644 --- a/src/Init/Data/BitVec/Bitblast.lean +++ b/src/Init/Data/BitVec/Bitblast.lean @@ -2012,8 +2012,7 @@ theorem getElem_smod {x y : BitVec w} (h : i < w) : | true, false => (if -x % y = 0#w then (-x % y) else (y - -x % y))[i] | true, true => (-(-x % -y))[i] := by simp only [smod, umod_eq, neg_eq, zero_eq, add_eq, sub_eq] - by_cases hx : x.msb <;> by_cases hy : y.msb - <;> simp [hx, hy] + by_cases hx : x.msb <;> by_cases hy : y.msb <;> simp [hx, hy] theorem getLsbD_smod {x y : BitVec w} : (x.smod y).getLsbD i = @@ -2037,8 +2036,7 @@ theorem getMsbD_smod {x y : BitVec w} : | true, false => (if -x % y = 0#w then (-x % y) else (y - -x % y)).getMsbD i | true, true => (-(-x % -y)).getMsbD i := by simp only [smod, umod_eq, neg_eq, zero_eq, add_eq, sub_eq] - by_cases hx : x.msb <;> by_cases hy : y.msb - <;> simp [hx, hy] + by_cases hx : x.msb <;> by_cases hy : y.msb <;> simp [hx, hy] theorem msb_smod {x y : BitVec w} : (x.smod y).msb = (x.msb && y = 0) || (y.msb && (x.smod y) ≠ 0) := by diff --git a/src/Init/Data/BitVec/Lemmas.lean b/src/Init/Data/BitVec/Lemmas.lean index 696ed3ea6e4c..57ad16fb3567 100644 --- a/src/Init/Data/BitVec/Lemmas.lean +++ b/src/Init/Data/BitVec/Lemmas.lean @@ -2063,7 +2063,7 @@ theorem shiftLeft_ofNat_eq {x : BitVec w} {k : Nat} : x <<< (BitVec.ofNat w k) = /-! ### ushiftRight -/ @[simp, bitvec_to_nat, grind =] theorem toNat_ushiftRight (x : BitVec n) (i : Nat) : - (x >>> i).toNat = x.toNat >>> i := rfl + (x >>> i).toNat = x.toNat >>> i := (rfl) @[simp, grind =] theorem getLsbD_ushiftRight (x : BitVec n) (i j : Nat) : getLsbD (x >>> i) j = getLsbD x (i+j) := by @@ -2115,7 +2115,6 @@ theorem ushiftRight_eq_zero {x : BitVec w} {n : Nat} (hn : w ≤ n) : have : 2^w ≤ 2^n := Nat.pow_le_pow_of_le Nat.one_lt_two hn rw [Nat.shiftRight_eq_div_pow, Nat.div_eq_of_lt (by omega)] - /-- Unsigned shift right by at least one bit makes the interpretations of the bitvector as an `Int` or `Nat` agree, because it makes the value of the bitvector less than or equal to `2^(w-1)`. @@ -4713,7 +4712,7 @@ theorem smod_eq (x y : BitVec w) : x.smod y = let u := umod (- x) y (if u = 0#w then u else y - u) | true, true => - ((- x).umod (- y)) := by - rw [BitVec.smod] + rw [BitVec.smod, BitVec.zero_eq] rcases x.msb <;> rcases y.msb <;> simp @[bitvec_to_nat] diff --git a/src/Init/Data/Bool.lean b/src/Init/Data/Bool.lean index e25737b4ae4a..10c605a3d41a 100644 --- a/src/Init/Data/Bool.lean +++ b/src/Init/Data/Bool.lean @@ -64,8 +64,8 @@ theorem ne_false_iff : {b : Bool} → b ≠ false ↔ b = true := by decide theorem eq_iff_iff {a b : Bool} : a = b ↔ (a ↔ b) := by cases b <;> simp -@[simp] theorem decide_eq_true {b : Bool} [Decidable (b = true)] : decide (b = true) = b := by cases b <;> simp -@[simp] theorem decide_eq_false {b : Bool} [Decidable (b = false)] : decide (b = false) = !b := by cases b <;> simp +@[simp] theorem decide_eq_true {b : Bool} {_ : Decidable (b = true)} : decide (b = true) = b := by cases b <;> simp +@[simp] theorem decide_eq_false {b : Bool} {_ : Decidable (b = false)} : decide (b = false) = !b := by cases b <;> simp theorem decide_true_eq {b : Bool} [Decidable (true = b)] : decide (true = b) = b := by cases b <;> simp theorem decide_false_eq {b : Bool} [Decidable (false = b)] : decide (false = b) = !b := by cases b <;> simp @@ -385,7 +385,7 @@ theorem and_or_inj_left_iff : /-- Converts `true` to `1` and `false` to `0`. -/ -@[expose] def toNat (b : Bool) : Nat := cond b 1 0 +@[expose, implicit_reducible] def toNat (b : Bool) : Nat := cond b 1 0 @[simp, bitvec_to_nat, grind =] theorem toNat_false : false.toNat = 0 := rfl diff --git a/src/Init/Data/ByteArray/Basic.lean b/src/Init/Data/ByteArray/Basic.lean index 13a33ad96cb1..34e5950de2ea 100644 --- a/src/Init/Data/ByteArray/Basic.lean +++ b/src/Init/Data/ByteArray/Basic.lean @@ -75,7 +75,7 @@ Retrieves the byte at the indicated index. Callers must prove that the index is Use {name}`uget` for a more efficient alternative or {name}`get!` for a variant that panics if the index is out of bounds. -/ -@[extern "lean_byte_array_fget"] +@[extern "lean_byte_array_fget", implicit_reducible] def get : (a : @& ByteArray) → (i : @& Nat) → (h : i < a.size := by get_elem_tactic) → UInt8 | ⟨bs⟩, i, _ => bs[i] diff --git a/src/Init/Data/ByteArray/Bootstrap.lean b/src/Init/Data/ByteArray/Bootstrap.lean index 09a823173e08..9030d88e4610 100644 --- a/src/Init/Data/ByteArray/Bootstrap.lean +++ b/src/Init/Data/ByteArray/Bootstrap.lean @@ -22,7 +22,7 @@ Appends two byte arrays. In compiled code, calls to {name}`ByteArray.append` are replaced with the much more efficient {name (scope:="Init.Data.ByteArray.Basic")}`ByteArray.fastAppend`. -/ -@[expose] +@[expose, implicit_reducible] protected def append (a b : ByteArray) : ByteArray := ⟨⟨a.data.toList ++ b.data.toList⟩⟩ diff --git a/src/Init/Data/ByteArray/Lemmas.lean b/src/Init/Data/ByteArray/Lemmas.lean index 02cc3efb3de8..8b0d9d3302e6 100644 --- a/src/Init/Data/ByteArray/Lemmas.lean +++ b/src/Init/Data/ByteArray/Lemmas.lean @@ -111,13 +111,13 @@ theorem getElem_eq_getElem_data {a : ByteArray} {i : Nat} {h : i < a.size} : theorem getElem_append_left {i : Nat} {a b : ByteArray} {h : i < (a ++ b).size} (hlt : i < a.size) : (a ++ b)[i] = a[i] := by simp only [getElem_eq_getElem_data, data_append] - rw [Array.getElem_append_left (by simpa)]; rfl + rw [Array.getElem_append_left (by simpa)] theorem getElem_append_right {i : Nat} {a b : ByteArray} {h : i < (a ++ b).size} (hle : a.size ≤ i) : (a ++ b)[i] = b[i - a.size]'(by simp_all; omega) := by simp only [getElem_eq_getElem_data, data_append] rw [Array.getElem_append_right (by simpa)] - simp; rfl + simp @[simp] theorem _root_.List.getElem_toByteArray {l : List UInt8} {i : Nat} {h : i < l.toByteArray.size} : @@ -223,7 +223,7 @@ theorem getElem_extract_aux {xs : ByteArray} {start stop : Nat} (h : i < (xs.ext theorem getElem_extract {i : Nat} {b : ByteArray} {start stop : Nat} (h) : (b.extract start stop)[i]'h = b[start + i]'(getElem_extract_aux h) := by - simp [getElem_eq_getElem_data]; rfl + simp [getElem_eq_getElem_data] theorem extract_eq_extract_left {a : ByteArray} {i i' j : Nat} : a.extract i j = a.extract i' j ↔ min j a.size - i = min j a.size - i' := by @@ -236,25 +236,25 @@ theorem extract_add_one {a : ByteArray} {i : Nat} (ha : i + 1 ≤ a.size) : omega · rename_i j hj hj' obtain rfl : j = 0 := by simpa using hj' - simp [ByteArray.getElem_eq_getElem_data]; rfl + simp [ByteArray.getElem_eq_getElem_data] theorem extract_add_two {a : ByteArray} {i : Nat} (ha : i + 2 ≤ a.size) : a.extract i (i + 2) = [a[i], a[i + 1]].toByteArray := by rw [extract_eq_extract_append_extract (i + 1) (by simp) (by omega), extract_add_one (by omega), extract_add_one (by omega)] - simp [← List.toByteArray_append]; rfl + simp [← List.toByteArray_append] theorem extract_add_three {a : ByteArray} {i : Nat} (ha : i + 3 ≤ a.size) : a.extract i (i + 3) = [a[i], a[i + 1], a[i + 2]].toByteArray := by rw [extract_eq_extract_append_extract (i + 1) (by simp) (by omega), extract_add_one (by omega), extract_add_two (by omega)] - simp [← List.toByteArray_append]; rfl + simp [← List.toByteArray_append] theorem extract_add_four {a : ByteArray} {i : Nat} (ha : i + 4 ≤ a.size) : a.extract i (i + 4) = [a[i], a[i + 1], a[i + 2], a[i + 3]].toByteArray := by rw [extract_eq_extract_append_extract (i + 1) (by simp) (by omega), extract_add_one (by omega), extract_add_three (by omega)] - simp [← List.toByteArray_append]; rfl + simp [← List.toByteArray_append] theorem append_assoc {a b c : ByteArray} : a ++ b ++ c = a ++ (b ++ c) := by ext1 diff --git a/src/Init/Data/Char/Basic.lean b/src/Init/Data/Char/Basic.lean index 60b5554fa5ca..bf5465529069 100644 --- a/src/Init/Data/Char/Basic.lean +++ b/src/Init/Data/Char/Basic.lean @@ -69,7 +69,7 @@ theorem isValidChar_zero : isValidChar 0 := /-- The character's Unicode code point as a `Nat`. -/ -@[inline] def toNat (c : Char) : Nat := +@[inline, implicit_reducible] def toNat (c : Char) : Nat := c.val.toNat /-- @@ -94,7 +94,7 @@ instance : Inhabited Char where Returns `true` if the character is a space `(' ', U+0020)`, a tab `('\t', U+0009)`, a carriage return `('\r', U+000D)`, or a newline `('\n', U+000A)`. -/ -@[inline] def isWhitespace (c : Char) : Bool := +@[inline, implicit_reducible] def isWhitespace (c : Char) : Bool := c = ' ' || c = '\t' || c = '\r' || c = '\n' /-- @@ -102,7 +102,7 @@ Returns `true` if the character is a uppercase ASCII letter. The uppercase ASCII letters are the following: `ABCDEFGHIJKLMNOPQRSTUVWXYZ`. -/ -@[inline] def isUpper (c : Char) : Bool := +@[inline, implicit_reducible] def isUpper (c : Char) : Bool := c.val ≥ 'A'.val ∧ c.val ≤ 'Z'.val /-- @@ -110,7 +110,7 @@ Returns `true` if the character is a lowercase ASCII letter. The lowercase ASCII letters are the following: `abcdefghijklmnopqrstuvwxyz`. -/ -@[inline] def isLower (c : Char) : Bool := +@[inline, implicit_reducible] def isLower (c : Char) : Bool := c.val ≥ 'a'.val && c.val ≤ 'z'.val /-- @@ -118,7 +118,7 @@ Returns `true` if the character is an ASCII letter. The ASCII letters are the following: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`. -/ -@[inline] def isAlpha (c : Char) : Bool := +@[inline, implicit_reducible] def isAlpha (c : Char) : Bool := c.isUpper || c.isLower /-- @@ -126,7 +126,7 @@ Returns `true` if the character is an ASCII digit. The ASCII digits are the following: `0123456789`. -/ -@[inline] def isDigit (c : Char) : Bool := +@[inline, implicit_reducible] def isDigit (c : Char) : Bool := c.val ≥ '0'.val && c.val ≤ '9'.val /-- @@ -143,7 +143,7 @@ Returns `true` if the character is an ASCII letter or digit. The ASCII letters are the following: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`. The ASCII digits are the following: `0123456789`. -/ -@[inline] def isAlphanum (c : Char) : Bool := +@[inline, implicit_reducible] def isAlphanum (c : Char) : Bool := c.isAlpha || c.isDigit /-- @@ -152,7 +152,7 @@ alphabet are returned unchanged. The uppercase ASCII letters are the following: `ABCDEFGHIJKLMNOPQRSTUVWXYZ`. -/ -@[inline] +@[inline, implicit_reducible] def toLower (c : Char) : Char := if h : c.val ≥ 'A'.val ∧ c.val ≤ 'Z'.val then ⟨c.val + ('a'.val - 'A'.val), ?_⟩ @@ -169,7 +169,7 @@ alphabet are returned unchanged. The lowercase ASCII letters are the following: `abcdefghijklmnopqrstuvwxyz`. -/ -@[inline] +@[inline, implicit_reducible] def toUpper (c : Char) : Char := if h : 'a'.val ≤ c.val ∧ c.val ≤ 'z'.val then ⟨c.val + ('A'.val - 'a'.val), ?_⟩ diff --git a/src/Init/Data/Dyadic/Basic.lean b/src/Init/Data/Dyadic/Basic.lean index fe78c8478bc0..197f830c1b5f 100644 --- a/src/Init/Data/Dyadic/Basic.lean +++ b/src/Init/Data/Dyadic/Basic.lean @@ -408,7 +408,7 @@ theorem ofIntWithPrec_shiftLeft_add {n : Nat} : /-- The "precision" of a dyadic number, i.e. in `n * 2^(-p)` with `n` odd the precision is `p`. -/ -- TODO: If `WithBot` is upstreamed, replace this with `WithBot Int`. -def precision : Dyadic → Option Int +@[instance_reducible] def precision : Dyadic → Option Int | .zero => none | .ofOdd _ p _ => some p diff --git a/src/Init/Data/Fin/Basic.lean b/src/Init/Data/Fin/Basic.lean index e4f0208e41a2..94b69243c5d8 100644 --- a/src/Init/Data/Fin/Basic.lean +++ b/src/Init/Data/Fin/Basic.lean @@ -40,7 +40,7 @@ Examples: * `(2 : Fin 3).succ = (3 : Fin 4)` * `(2 : Fin 3) + 1 = (0 : Fin 3)` -/ -def succ : Fin n → Fin (n + 1) +@[instance_reducible] def succ : Fin n → Fin (n + 1) | ⟨i, h⟩ => ⟨i+1, Nat.succ_lt_succ h⟩ variable {n : Nat} @@ -50,6 +50,7 @@ Returns `a` modulo `n` as a `Fin n`. The assumption `NeZero n` ensures that `Fin n` is nonempty. -/ +@[implicit_reducible] protected def ofNat (n : Nat) [NeZero n] (a : Nat) : Fin n := ⟨a % n, Nat.mod_lt _ (pos_of_neZero n)⟩ @@ -85,6 +86,7 @@ Examples: * `(2 : Fin 8) + (2 : Fin 8) = (4 : Fin 8)` * `(2 : Fin 3) + (2 : Fin 3) = (1 : Fin 3)` -/ +@[implicit_reducible] protected def add : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(a + b) % n, by exact mlt h⟩ @@ -96,6 +98,7 @@ Examples: * `(2 : Fin 10) * (7 : Fin 10) = (4 : Fin 10)` * `(3 : Fin 10) * (7 : Fin 10) = (1 : Fin 10)` -/ +@[implicit_reducible] protected def mul : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(a * b) % n, by exact mlt h⟩ @@ -106,6 +109,7 @@ Examples: * `(5 : Fin 11) - (3 : Fin 11) = (2 : Fin 11)` * `(3 : Fin 11) - (5 : Fin 11) = (9 : Fin 11)` -/ +@[implicit_reducible] protected def sub : Fin n → Fin n → Fin n /- The definition of `Fin.sub` has been updated to improve performance. @@ -137,6 +141,7 @@ Modulus of bounded numbers, usually invoked via the `%` operator. The resulting value is that computed by the `%` operator on `Nat`. -/ +@[implicit_reducible] protected def mod : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨a % b, by exact Nat.lt_of_le_of_lt (Nat.mod_le _ _) h⟩ @@ -151,6 +156,7 @@ Examples: * `(5 : Fin 10) / (0 : Fin 10) = (0 : Fin 10)` * `(5 : Fin 10) / (7 : Fin 10) = (0 : Fin 10)` -/ +@[implicit_reducible] protected def div : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨a / b, by exact Nat.lt_of_le_of_lt (Nat.div_le_self _ _) h⟩ @@ -165,18 +171,21 @@ def modn : Fin n → Nat → Fin n /-- Bitwise and. -/ +@[implicit_reducible] def land : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(Nat.land a b) % n, by exact mlt h⟩ /-- Bitwise or. -/ +@[implicit_reducible] def lor : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(Nat.lor a b) % n, by exact mlt h⟩ /-- Bitwise xor (“exclusive or”). -/ +@[implicit_reducible] def xor : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(Nat.xor a b) % n, by exact mlt h⟩ @@ -188,6 +197,7 @@ Examples: * `(1 : Fin 10) <<< (3 : Fin 10) = (8 : Fin 10)` * `(1 : Fin 10) <<< (4 : Fin 10) = (6 : Fin 10)` -/ +@[implicit_reducible] def shiftLeft : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(a <<< b) % n, by exact mlt h⟩ @@ -202,6 +212,7 @@ Examples: * `(15 : Fin 16) >>> (2 : Fin 16) = (3 : Fin 16)` * `(15 : Fin 17) >>> (2 : Fin 17) = (3 : Fin 17)` -/ +@[implicit_reducible] def shiftRight : Fin n → Fin n → Fin n | ⟨a, h⟩, ⟨b, _⟩ => ⟨(a >>> b) % n, by exact mlt h⟩ @@ -276,7 +287,7 @@ Examples: * `Fin.last 4 = (4 : Fin 5)` * `(Fin.last 0).val = (0 : Nat)` -/ -@[inline] def last (n : Nat) : Fin (n + 1) := ⟨n, n.lt_succ_self⟩ +@[inline, instance_reducible] def last (n : Nat) : Fin (n + 1) := ⟨n, n.lt_succ_self⟩ /-- Replaces the bound with another that is suitable for the value. @@ -294,7 +305,7 @@ example (i : Fin 10) : Fin 12 := cases i; simp; omega ``` -/ -@[inline] def castLT (i : Fin m) (h : i.1 < n) : Fin n := ⟨i.1, h⟩ +@[inline, implicit_reducible] def castLT (i : Fin m) (h : i.1 < n) : Fin n := ⟨i.1, h⟩ /-- Coarsens a bound to one at least as large. @@ -302,14 +313,14 @@ Coarsens a bound to one at least as large. See also `Fin.castAdd` for a version that represents the larger bound with addition rather than an explicit inequality proof. -/ -@[inline] def castLE (h : n ≤ m) (i : Fin n) : Fin m := ⟨i, Nat.lt_of_lt_of_le i.2 h⟩ +@[inline, instance_reducible] def castLE (h : n ≤ m) (i : Fin n) : Fin m := ⟨i, Nat.lt_of_lt_of_le i.2 h⟩ /-- Uses a proof that two bounds are equal to allow a value bounded by one to be used with the other. In other words, when `eq : n = m`, `Fin.cast eq i` converts `i : Fin n` into a `Fin m`. -/ -@[inline] protected def cast (eq : n = m) (i : Fin n) : Fin m := ⟨i, eq ▸ i.2⟩ +@[inline, instance_reducible] protected def cast (eq : n = m) (i : Fin n) : Fin m := ⟨i, eq ▸ i.2⟩ /-- Coarsens a bound to one at least as large. @@ -317,13 +328,13 @@ Coarsens a bound to one at least as large. See also `Fin.natAdd` and `Fin.addNat` for addition functions that increase the bound, and `Fin.castLE` for a version that uses an explicit inequality proof. -/ -@[inline] def castAdd (m) : Fin n → Fin (n + m) := +@[inline, instance_reducible] def castAdd (m) : Fin n → Fin (n + m) := castLE <| Nat.le_add_right n m /-- Coarsens a bound by one. -/ -@[inline] def castSucc : Fin n → Fin (n + 1) := castAdd 1 +@[inline, instance_reducible] def castSucc : Fin n → Fin (n + 1) := castAdd 1 /-- Adds a natural number to a `Fin`, increasing the bound. @@ -338,6 +349,7 @@ Examples: * `Fin.addNat (1 : Fin 8) 2 = (3 : Fin 10)` -/ +@[implicit_reducible] def addNat (i : Fin n) (m) : Fin (n + m) := ⟨i + m, Nat.add_lt_add_right i.2 _⟩ /-- @@ -352,6 +364,7 @@ Examples: * `Fin.natAdd 1 (0 : Fin 8) = (1 : Fin 9)` * `Fin.natAdd 1 (2 : Fin 8) = (3 : Fin 9)` -/ +@[implicit_reducible] def natAdd (n) (i : Fin m) : Fin (n + m) := ⟨n + i, Nat.add_lt_add_left i.2 _⟩ /-- @@ -366,7 +379,7 @@ Examples: * `(0 : Fin 6).rev = (5 : Fin 6)` * `(2 : Fin 5).rev = (2 : Fin 5)` -/ -@[inline] def rev (i : Fin n) : Fin n := ⟨n - (i + 1), Nat.sub_lt i.pos (Nat.succ_pos _)⟩ +@[inline, implicit_reducible] def rev (i : Fin n) : Fin n := ⟨n - (i + 1), Nat.sub_lt i.pos (Nat.succ_pos _)⟩ /-- Subtraction of a natural number from a `Fin`, with the bound narrowed. @@ -378,7 +391,7 @@ Examples: * `(5 : Fin 9).subNat 0 (by decide) = (5 : Fin 9)` * `(3 : Fin 9).subNat 3 (by decide) = (0 : Fin 6)` -/ -@[inline] def subNat (m) (i : Fin (n + m)) (h : m ≤ i) : Fin n := +@[inline, implicit_reducible] def subNat (m) (i : Fin (n + m)) (h : m ≤ i) : Fin n := ⟨i - m, Nat.sub_lt_right_of_lt_add h i.2⟩ /-- @@ -388,7 +401,7 @@ Examples: * `(4 : Fin 8).pred (by decide) = (3 : Fin 7)` * `(1 : Fin 2).pred (by decide) = (0 : Fin 1)` -/ -@[inline] def pred {n : Nat} (i : Fin (n + 1)) (h : i ≠ 0) : Fin n := +@[inline, implicit_reducible] def pred {n : Nat} (i : Fin (n + 1)) (h : i ≠ 0) : Fin n := subNat 1 i <| Nat.pos_of_ne_zero <| mt (Fin.eq_of_val_eq (j := 0)) h theorem val_inj {a b : Fin n} : a.1 = b.1 ↔ a = b := ⟨Fin.eq_of_val_eq, Fin.val_eq_of_eq⟩ diff --git a/src/Init/Data/Fin/Lemmas.lean b/src/Init/Data/Fin/Lemmas.lean index c87fe6577be4..643ae7ef8b5b 100644 --- a/src/Init/Data/Fin/Lemmas.lean +++ b/src/Init/Data/Fin/Lemmas.lean @@ -1012,7 +1012,9 @@ For the induction: @[simp, grind =] theorem reverseInduction_last {n : Nat} {motive : Fin (n + 1) → Sort _} {zero succ} : (reverseInduction zero succ (Fin.last n) : motive (Fin.last n)) = zero := by - rw [reverseInduction, reverseInduction.go]; simp; rfl + rw [reverseInduction, reverseInduction.go]; simp + +-- TODO: Why does the following fail with `Fin.succ` merely implicit-reducible? private theorem reverseInduction_castSucc_aux {n : Nat} {motive : Fin (n + 1) → Sort _} {succ} (i : Fin n) (j : Nat) (h) (h2 : i.1 < j) (zero : motive ⟨j, h⟩) : @@ -1023,7 +1025,7 @@ private theorem reverseInduction_castSucc_aux {n : Nat} {motive : Fin (n + 1) | succ j ih => rw [reverseInduction.go, dif_neg (by exact Nat.ne_of_lt h2)] by_cases hij : i = j - · subst hij; simp [reverseInduction.go]; rfl + · subst hij; simp [reverseInduction.go] · dsimp only rw [ih _ _ (by omega), eq_comm, reverseInduction.go, dif_neg (by change i.1 + 1 ≠ _; omega)] diff --git a/src/Init/Data/Int/Basic.lean b/src/Init/Data/Int/Basic.lean index 7098c0dad879..ee17db6f1f7f 100644 --- a/src/Init/Data/Int/Basic.lean +++ b/src/Init/Data/Int/Basic.lean @@ -99,6 +99,7 @@ Examples: * `Int.negOfNat 6 = -6` * `Int.negOfNat 0 = 0` -/ +@[instance_reducible] def negOfNat : Nat → Int | 0 => 0 | succ m => negSucc m @@ -115,7 +116,7 @@ Examples: * `-(-6 : Int) = 6` * `(12 : Int).neg = -12` -/ -@[extern "lean_int_neg"] +@[extern "lean_int_neg", instance_reducible] protected def neg (n : @& Int) : Int := match n with | ofNat n => negOfNat n @@ -141,6 +142,7 @@ Examples: * `Int.subNatNat 2 5 = -3` * `Int.subNatNat 0 13 = -13` -/ +@[instance_reducible] def subNatNat (m n : Nat) : Int := match (n - m : Nat) with | 0 => ofNat (m - n) -- m ≥ n @@ -157,7 +159,7 @@ Examples: * `(7 : Int) + (6 : Int) = 13` * `(6 : Int) + (-6 : Int) = 0` -/ -@[extern "lean_int_add"] +@[extern "lean_int_add", instance_reducible] protected def add (m n : @& Int) : Int := match m, n with | ofNat m, ofNat n => ofNat (m + n) @@ -180,7 +182,7 @@ Examples: * `(6 : Int) * (-6 : Int) = -36` * `(7 : Int) * (0 : Int) = 0` -/ -@[extern "lean_int_mul"] +@[extern "lean_int_mul", implicit_reducible] protected def mul (m n : @& Int) : Int := match m, n with | ofNat m, ofNat n => ofNat (m * n) @@ -203,7 +205,7 @@ Examples: * `(7 : Int) - (0 : Int) = 7` * `(0 : Int) - (7 : Int) = -7` -/ -@[extern "lean_int_sub"] +@[extern "lean_int_sub", instance_reducible] protected def sub (m n : @& Int) : Int := m + (- n) instance : Sub Int where @@ -250,7 +252,7 @@ Examples: * `if (6 : Int) = (3 : Int) * (2 : Int) then "yes" else "no" = "yes"` * `(¬ (6 : Int) = (3 : Int)) = true` -/ -@[extern "lean_int_dec_eq"] +@[extern "lean_int_dec_eq", implicit_reducible] protected def decEq (a b : @& Int) : Decidable (a = b) := match a, b with | ofNat a, ofNat b => match decEq a b with @@ -275,7 +277,7 @@ set_option bootstrap.genMatcherCode false in ``` Implemented by efficient native code. -/ -@[extern "lean_int_dec_nonneg"] +@[extern "lean_int_dec_nonneg", implicit_reducible] def decNonneg (m : @& Int) : Decidable (NonNeg m) := match m with | ofNat m => isTrue <| NonNeg.mk m @@ -323,7 +325,7 @@ Examples: * `(0 : Int).natAbs = 0` * `(-11 : Int).natAbs = 11` -/ -@[extern "lean_nat_abs"] +@[extern "lean_nat_abs", instance_reducible] def natAbs (m : @& Int) : Nat := match m with | ofNat m => m @@ -361,6 +363,7 @@ Examples: * `(0 : Int).toNat = 0` * `(-7 : Int).toNat = 0` -/ +@[implicit_reducible] def toNat : Int → Nat | ofNat n => n | negSucc _ => 0 @@ -397,6 +400,7 @@ Examples: * `(0 : Int) ^ 10 = 0` * `(-7 : Int) ^ 3 = -343` -/ +@[instance_reducible] protected def pow : Int → Nat → Int | (m : Nat), n => Int.ofNat (m ^ n) | m@-[_+1], n => if n % 2 = 0 then Int.ofNat (m.natAbs ^ n) else - Int.ofNat (m.natAbs ^ n) diff --git a/src/Init/Data/Int/Bitwise/Basic.lean b/src/Init/Data/Int/Bitwise/Basic.lean index 749592645c04..a075952e3b0b 100644 --- a/src/Init/Data/Int/Bitwise/Basic.lean +++ b/src/Init/Data/Int/Bitwise/Basic.lean @@ -43,7 +43,7 @@ Examples: * `(-0b1000 : Int) >>> 1 = -0b0100` * `(-0b0111 : Int) >>> 1 = -0b0100` -/ -@[expose] +@[expose, implicit_reducible] protected def shiftRight : Int → Nat → Int | Int.ofNat n, s => Int.ofNat (n >>> s) | Int.negSucc n, s => Int.negSucc (n >>> s) diff --git a/src/Init/Data/Int/DivMod/Basic.lean b/src/Init/Data/Int/DivMod/Basic.lean index c519d6206125..855635fb1ddc 100644 --- a/src/Init/Data/Int/DivMod/Basic.lean +++ b/src/Init/Data/Int/DivMod/Basic.lean @@ -69,7 +69,7 @@ Examples: * `(-12 : Int) / (7 : Int) = -2` * `(-12 : Int) / (-7 : Int) = 2` -/ -@[extern "lean_int_ediv"] +@[extern "lean_int_ediv", implicit_reducible] def ediv : (@& Int) → (@& Int) → Int | ofNat m, ofNat n => ofNat (m / n) | ofNat m, -[n+1] => -ofNat (m / succ n) @@ -99,7 +99,7 @@ Examples: * `(-12 : Int) % (7 : Int) = 2` * `(-12 : Int) % (-7 : Int) = 2` -/ -@[extern "lean_int_emod"] +@[extern "lean_int_emod", implicit_reducible] def emod : (@& Int) → (@& Int) → Int | ofNat m, n => ofNat (m % natAbs n) | -[m+1], n => subNatNat (natAbs n) (succ (m % natAbs n)) @@ -174,7 +174,7 @@ Examples: * `(-12 : Int).tdiv (7 : Int) = -1` * `(-12 : Int).tdiv (-7 : Int) = 1` -/ -@[extern "lean_int_div"] +@[extern "lean_int_div", implicit_reducible] def tdiv : (@& Int) → (@& Int) → Int | ofNat m, ofNat n => ofNat (m / n) | ofNat m, -[n +1] => -ofNat (m / succ n) @@ -207,7 +207,7 @@ Examples: * `(-12 : Int).tmod (7 : Int) = -5` * `(-12 : Int).tmod (-7 : Int) = -5` -/ -@[extern "lean_int_mod"] +@[extern "lean_int_mod", implicit_reducible] def tmod : (@& Int) → (@& Int) → Int | ofNat m, ofNat n => ofNat (m % n) | ofNat m, -[n +1] => ofNat (m % succ n) @@ -238,6 +238,7 @@ Examples: * `(-12 : Int).fdiv (7 : Int) = -2` * `(-12 : Int).fdiv (-7 : Int) = 1` -/ +@[implicit_reducible] def fdiv : Int → Int → Int | 0, _ => 0 | ofNat m, ofNat n => ofNat (m / n) @@ -268,6 +269,7 @@ Examples: * `(-12 : Int).fmod (-7 : Int) = -5` -/ +@[implicit_reducible] def fmod : Int → Int → Int | 0, _ => 0 | ofNat m, ofNat n => ofNat (m % n) @@ -312,6 +314,7 @@ Examples: * `(-12 : Int).bmod 8 = -4` * `(-12 : Int).bmod 9 = -3` -/ +@[implicit_reducible] def bmod (x : Int) (m : Nat) : Int := let r := x % m if r < (m + 1) / 2 then @@ -336,6 +339,7 @@ Examples: * `(-12 : Int).bdiv 8 = -1` * `(-12 : Int).bdiv 9 = -1` -/ +@[implicit_reducible] def bdiv (x : Int) (m : Nat) : Int := if m = 0 then 0 diff --git a/src/Init/Data/Int/Order.lean b/src/Init/Data/Int/Order.lean index 7fd2319375b6..e0a2d830d099 100644 --- a/src/Init/Data/Int/Order.lean +++ b/src/Init/Data/Int/Order.lean @@ -1406,7 +1406,7 @@ theorem natAbs_mul_self : ∀ {a : Int}, ↑(natAbs a * natAbs a) = a * a protected theorem eq_nat_or_neg (a : Int) : ∃ n : Nat, a = n ∨ a = -↑n := ⟨_, natAbs_eq a⟩ theorem natAbs_mul_natAbs_eq {a b : Int} {c : Nat} - (h : a * b = (c : Int)) : a.natAbs * b.natAbs = c := by rw [← natAbs_mul, h, natAbs.eq_def] + (h : a * b = (c : Int)) : a.natAbs * b.natAbs = c := by rw [← natAbs_mul, h, natAbs_natCast] @[simp] theorem natAbs_mul_self' (a : Int) : (natAbs a * natAbs a : Int) = a * a := by rw [← Int.natCast_mul, natAbs_mul_self] diff --git a/src/Init/Data/Iterators/Basic.lean b/src/Init/Data/Iterators/Basic.lean index 297d757614a2..4479a60feb97 100644 --- a/src/Init/Data/Iterators/Basic.lean +++ b/src/Init/Data/Iterators/Basic.lean @@ -183,14 +183,14 @@ add_decl_doc IterM.mk Converts a pure iterator (`Iter β`) into a monadic iterator (`IterM Id β`) in the identity monad `Id`. -/ -@[expose] +@[expose, instance_reducible] def Iter.toIterM {α : Type w} {β : Type w} (it : Iter (α := α) β) : IterM (α := α) Id β := ⟨it.internalState⟩ /-- Converts a monadic iterator (`IterM Id β`) over `Id` into a pure iterator (`Iter β`). -/ -@[expose] +@[expose, instance_reducible] def IterM.toIter {α : Type w} {β : Type w} (it : IterM (α := α) Id β) : Iter (α := α) β := ⟨it.internalState⟩ @@ -565,6 +565,12 @@ def IterM.Step.toPure {α : Type w} {β : Type w} [Iterator α Id β] {it : Iter (step : it.Step) : it.toIter.Step := ⟨step.val.mapIterator IterM.toIter, (by simp [Iter.IsPlausibleStep, step.property])⟩ +@[simp] +theorem IterM.Step.val_toPure {α β : Type w} [Iterator α Id β] {it : IterM (α := α) Id β} + {step : it.Step} : + step.toPure.val = step.val.mapIterator IterM.toIter := + (rfl) + @[simp] theorem IterM.Step.toPure_yield {α β : Type w} [Iterator α Id β] {it : IterM (α := α) Id β} {it' out h} : IterM.Step.toPure (⟨.yield it' out, h⟩ : it.Step) = .yield it'.toIter out h := diff --git a/src/Init/Data/Iterators/Combinators/Monadic/ULift.lean b/src/Init/Data/Iterators/Combinators/Monadic/ULift.lean index 290f4c754c44..cf3231fcf733 100644 --- a/src/Init/Data/Iterators/Combinators/Monadic/ULift.lean +++ b/src/Init/Data/Iterators/Combinators/Monadic/ULift.lean @@ -18,7 +18,7 @@ section ULiftT namespace Iterators /-- `ULiftT.{v, u}` shrinks a monad on `Type max u v` to a monad on `Type u`. -/ -@[expose] -- for codegen +@[expose, instance_reducible] -- for codegen def ULiftT (n : Type max u v → Type v') (α : Type u) := n (ULift.{v} α) /-- Returns the underlying `n`-monadic representation of a `ULiftT n α` value. -/ diff --git a/src/Init/Data/Iterators/Lemmas/Combinators/FilterMap.lean b/src/Init/Data/Iterators/Lemmas/Combinators/FilterMap.lean index 2d486ce3a44d..3f9c45a20498 100644 --- a/src/Init/Data/Iterators/Lemmas/Combinators/FilterMap.lean +++ b/src/Init/Data/Iterators/Lemmas/Combinators/FilterMap.lean @@ -215,13 +215,15 @@ theorem Iter.step_filterMap {f : β → Option γ} : | some out' => .yield (it'.filterMap f) out' (.yieldSome (out := out) h h') | .skip it' h => .skip (it'.filterMap f) (.skip h) | .done h => .done (.done h) := by + apply Subtype.ext simp only [filterMap_eq_toIter_filterMap_toIterM, toIterM_toIter, IterM.step_filterMap, step] simp only [monadLift, Id.run_bind] generalize it.toIterM.step.run = step cases step.inflate using PlausibleIterStep.casesOn · simp only [IterM.Step.toPure_yield, toIter_toIterM, toIterM_toIter] split <;> split <;> (try exfalso; simp_all; done) - · simp + · simp [PlausibleIterStep.skip, Id.run_pure, Shrink.inflate_deflate, + IterM.Step.val_toPure, IterStep.mapIterator_skip] · rename_i h₁ _ h₂ rw [h₁] at h₂ cases h₂ @@ -255,6 +257,7 @@ theorem Iter.step_map {f : β → γ} : .skip (it'.map f) (.skip h) | .done h => .done (.done h) := by + apply Subtype.ext simp only [map_eq_toIter_map_toIterM, step, toIterM_toIter, IterM.step_map, Id.run_bind] generalize it.toIterM.step.run = step cases step.inflate using PlausibleIterStep.casesOn <;> simp @@ -270,6 +273,7 @@ def Iter.step_filter {f : β → Bool} : .skip (it'.filter f) (.skip h) | .done h => .done (.done h) := by + apply Subtype.ext simp only [filter_eq_toIter_filter_toIterM, step, toIterM_toIter, IterM.step_filter, Id.run_bind] generalize it.toIterM.step.run = step cases step.inflate using PlausibleIterStep.casesOn diff --git a/src/Init/Data/Iterators/Lemmas/Combinators/Take.lean b/src/Init/Data/Iterators/Lemmas/Combinators/Take.lean index d2f9a602f7b8..c1612003a7fe 100644 --- a/src/Init/Data/Iterators/Lemmas/Combinators/Take.lean +++ b/src/Init/Data/Iterators/Lemmas/Combinators/Take.lean @@ -109,6 +109,7 @@ theorem Iter.step_toTake {α β} [Iterator α Id β] [Finite α Id] | .yield it' out h => .yield it'.toTake out (.yield h Nat.zero_ne_one) | .skip it' h => .skip it'.toTake (.skip h Nat.zero_ne_one) | .done h => .done (.done h)) := by + apply Subtype.ext simp only [toTake_eq_toIter_toTake_toIterM, Iter.step, toIterM_toIter, IterM.step_toTake, Id.run_bind] cases it.toIterM.step.run.inflate using PlausibleIterStep.casesOn <;> simp diff --git a/src/Init/Data/List/Attach.lean b/src/Init/Data/List/Attach.lean index 660518dc265b..3721b0623eae 100644 --- a/src/Init/Data/List/Attach.lean +++ b/src/Init/Data/List/Attach.lean @@ -134,6 +134,10 @@ theorem pmap_eq_map_attach {p : α → Prop} {f : ∀ a, p a → β} {l : List pmap f l H = l.attach.map fun x => f x.1 (H _ x.2) := by rw [attach, attachWith, map_pmap]; exact pmap_congr_left l fun _ _ _ _ => rfl +theorem attachWith_eq_map_attach {xs : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a} : + xs.attachWith P H = xs.attach.map fun ⟨x, h⟩ => ⟨x, H _ h⟩ := by + induction xs <;> simp_all + @[simp] theorem pmap_eq_attachWith {p q : α → Prop} {f : ∀ a, p a → q a} {l : List α} (H) : pmap (fun a h => ⟨a, f a h⟩) l H = l.attachWith q (fun x h => f x (H x h)) := by @@ -404,7 +408,7 @@ theorem foldr_attach {l : List α} {f : α → β → β} {b : β} : theorem attach_map {l : List α} {f : α → β} : (l.map f).attach = l.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem h⟩) := by - induction l <;> simp [*] + induction l <;> simp [*, map] theorem attachWith_map {l : List α} {f : α → β} {P : β → Prop} (H : ∀ (b : β), b ∈ l.map f → P b) : (l.map f).attachWith P H = (l.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem h))).map diff --git a/src/Init/Data/List/Basic.lean b/src/Init/Data/List/Basic.lean index 354a7cfb216d..7935d968144c 100644 --- a/src/Init/Data/List/Basic.lean +++ b/src/Init/Data/List/Basic.lean @@ -474,8 +474,8 @@ We define the basic functional programming operations on `List`: /-! ### map -/ -@[simp, grind =] theorem map_nil {f : α → β} : map f [] = [] := rfl -@[simp, grind =] theorem map_cons {f : α → β} {a : α} {l : List α} : map f (a :: l) = f a :: map f l := rfl +@[simp, grind =] theorem map_nil {f : α → β} : map f [] = [] := id rfl +@[simp, grind =] theorem map_cons {f : α → β} {a : α} {l : List α} : map f (a :: l) = f a :: map f l := id rfl /-! ### filter -/ @@ -702,6 +702,7 @@ Creates a list that contains `n` copies of `a`. * `List.replicate 0 "zero" = []` * `List.replicate 2 ' ' = [' ', ' ']` -/ +@[implicit_reducible] def replicate : (n : Nat) → (a : α) → List α | 0, _ => [] | n+1, a => a :: replicate n a @@ -769,6 +770,7 @@ Examples: * `["grape"].isEmpty = false` * `["apple", "banana"].isEmpty = false` -/ +@[instance_reducible] def isEmpty : List α → Bool | [] => true | _ :: _ => false @@ -937,8 +939,8 @@ def drop : (n : Nat) → (xs : List α) → List α @[simp, grind =] theorem drop_nil : ([] : List α).drop i = [] := by cases i <;> rfl -@[simp, grind =] theorem drop_zero {l : List α} : l.drop 0 = l := rfl -@[simp, grind =] theorem drop_succ_cons {a : α} {l : List α} {i : Nat} : (a :: l).drop (i + 1) = l.drop i := rfl +@[simp, grind =] theorem drop_zero {l : List α} : l.drop 0 = l := id rfl +@[simp, grind =] theorem drop_succ_cons {a : α} {l : List α} {i : Nat} : (a :: l).drop (i + 1) = l.drop i := id rfl theorem drop_eq_nil_of_le {as : List α} {i : Nat} (h : as.length ≤ i) : as.drop i = [] := by match as, i with @@ -1054,11 +1056,11 @@ def dropLast {α} : List α → List α | [_] => [] | a::as => a :: dropLast as -@[simp, grind =] theorem dropLast_nil : ([] : List α).dropLast = [] := rfl -@[simp, grind =] theorem dropLast_singleton : [x].dropLast = [] := rfl +@[simp, grind =] theorem dropLast_nil : ([] : List α).dropLast = [] := (rfl) +@[simp, grind =] theorem dropLast_singleton : [x].dropLast = [] := (rfl) @[simp, grind =] theorem dropLast_cons_cons : - (x::y::zs).dropLast = x :: (y::zs).dropLast := rfl + (x::y::zs).dropLast = x :: (y::zs).dropLast := (rfl) @[deprecated dropLast_cons_cons (since := "2026-02-26")] theorem dropLast_cons₂ : (x::y::zs).dropLast = x :: (y::zs).dropLast := dropLast_cons_cons @@ -2122,10 +2124,10 @@ def range' : (start len : Nat) → (step : Nat := 1) → List Nat | _, 0, _ => [] | s, n+1, step => s :: range' (s+step) n step -@[simp, grind =] theorem range'_zero : range' s 0 step = [] := rfl -@[simp, grind =] theorem range'_one {s step : Nat} : range' s 1 step = [s] := rfl +@[simp, grind =] theorem range'_zero : range' s 0 step = [] := (rfl) +@[simp, grind =] theorem range'_one {s step : Nat} : range' s 1 step = [s] := (rfl) -- The following theorem is intentionally not a simp lemma. -theorem range'_succ : range' s (n + 1) step = s :: range' (s + step) n step := rfl +theorem range'_succ : range' s (n + 1) step = s :: range' (s + step) n step := (rfl) /-! ### zipIdx -/ diff --git a/src/Init/Data/List/FinRange.lean b/src/Init/Data/List/FinRange.lean index 6f9b08b9438b..1ffeb8b1fb2b 100644 --- a/src/Init/Data/List/FinRange.lean +++ b/src/Init/Data/List/FinRange.lean @@ -25,7 +25,7 @@ Examples: * `List.finRange 0 = ([] : List (Fin 0))` * `List.finRange 2 = ([0, 1] : List (Fin 2))` -/ -@[expose] def finRange (n : Nat) : List (Fin n) := ofFn fun i => i +@[expose, instance_reducible] def finRange (n : Nat) : List (Fin n) := ofFn fun i => i @[simp, grind =] theorem length_finRange {n : Nat} : (List.finRange n).length = n := by simp [List.finRange] diff --git a/src/Init/Data/List/Lemmas.lean b/src/Init/Data/List/Lemmas.lean index 52c8db9bd341..fdcb0e4079f6 100644 --- a/src/Init/Data/List/Lemmas.lean +++ b/src/Init/Data/List/Lemmas.lean @@ -796,6 +796,8 @@ theorem length_eq_of_beq [BEq α] {l₁ l₂ : List α} (h : l₁ == l₂) : l /-! ### getLast -/ +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in @[grind =] theorem getLast_eq_getElem : ∀ {l : List α} (h : l ≠ []), getLast l h = l[l.length - 1]'(by @@ -828,6 +830,8 @@ theorem getLast_eq_getLastD {a l} (h) : @getLast α (a::l) h = getLastD l a := b @[simp, grind =] theorem getLast_singleton {a} (h) : @getLast α [a] h = a := rfl +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem getLast!_cons_eq_getLastD [Inhabited α] : @getLast! α _ (a::l) = getLastD l a := by simp [getLast!, getLast_eq_getLastD] @@ -860,6 +864,8 @@ theorem getLast?_eq_getLast : ∀ {l : List α} h, l.getLast? = some (l.getLast | [], h => nomatch h rfl | _ :: _, _ => rfl +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in @[grind =] theorem getLast?_eq_getElem? : ∀ {l : List α}, l.getLast? = l[l.length - 1]? | [] => rfl | a::l => by @@ -1762,6 +1768,8 @@ theorem append_eq_append_iff {ws xs ys zs : List α} : · simp [isEmpty_iff] at h simp [h] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem head_append_left {l₁ l₂ : List α} (h : l₁ ≠ []) : head (l₁ ++ l₂) (fun h => by simp_all) = head l₁ h := by rw [head_append, dif_neg (by simp_all)] @@ -2990,6 +2998,8 @@ theorem head_eq_getLast_reverse {l : List α} (h : l ≠ []) : · simp [isEmpty_iff] at h' simp [h'] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem getLast_append_right {l : List α} (h : l' ≠ []) : (l ++ l').getLast (fun h => by simp_all) = l'.getLast h := by rw [getLast_append, dif_neg (by simp_all)] diff --git a/src/Init/Data/List/MinMaxOn.lean b/src/Init/Data/List/MinMaxOn.lean index 25b6e091c2dc..15695df05fa1 100644 --- a/src/Init/Data/List/MinMaxOn.lean +++ b/src/Init/Data/List/MinMaxOn.lean @@ -247,7 +247,7 @@ protected theorem min_map (xs.map f).min (by simpa) = f (xs.minOn f h) := by match xs with | x :: xs => - simp only [List.minOn, map_cons, List.min, foldl_map] + simp only [List.minOn, map, List.min, foldl_map] rw [foldl_hom] simp [min_apply] @@ -485,6 +485,8 @@ protected theorem minOn?_singleton [LE β] [DecidableLE β] {x : α} {f : α → [x].minOn? f = some x := by simp [List.minOn?_cons_eq_some_minOn] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in @[simp] protected theorem minOn?_id [Min α] [LE α] [DecidableLE α] [LawfulOrderLeftLeaningMin α] {xs : List α} : xs.minOn? id = xs.min? := by diff --git a/src/Init/Data/List/TakeDrop.lean b/src/Init/Data/List/TakeDrop.lean index 7694777b40bf..ded923f17a25 100644 --- a/src/Init/Data/List/TakeDrop.lean +++ b/src/Init/Data/List/TakeDrop.lean @@ -230,10 +230,10 @@ theorem take_left' {l₁ l₂ : List α} {i} (h : length l₁ = i) : take i (l theorem take_add_one {l : List α} {i : Nat} : l.take (i + 1) = l.take i ++ l[i]?.toList := by induction l generalizing i with | nil => - simp only [take_nil, Option.toList, getElem?_nil, append_nil] + simp only [take_nil, Option.toList, append_nil, getElem?_nil] | cons hd tl hl => cases i - · simp only [take, Option.toList, getElem?_cons_zero, nil_append] + · simp only [take, Option.toList, nil_append, getElem?_cons, ↓reduceIte] · simp only [take, hl, getElem?_cons_succ, cons_append] @[deprecated take_add_one (since := "2025-10-26")] @@ -256,7 +256,7 @@ theorem dropLast_eq_take {l : List α} : l.dropLast = l.take (l.length - 1) := b | [], i => by simp | l, 0 => by simp | _ :: tl, n + 1 => by - dsimp + simp rw [map_drop] theorem drop_eq_extract {l : List α} {k : Nat} : diff --git a/src/Init/Data/List/ToArray.lean b/src/Init/Data/List/ToArray.lean index dfec099a93a9..3c652630391f 100644 --- a/src/Init/Data/List/ToArray.lean +++ b/src/Init/Data/List/ToArray.lean @@ -512,8 +512,8 @@ private theorem takeWhile_go_succ (p : α → Bool) (a : α) (l : List α) (i : simp only [size_toArray, length_cons, Nat.add_lt_add_iff_right, getElem_toArray, getElem_cons_succ] split - rw [takeWhile_go_succ] - rfl + · rw [takeWhile_go_succ] + · rfl private theorem takeWhile_go_toArray (p : α → Bool) (l : List α) (i : Nat) : Array.takeWhile.go p l.toArray i r = r ++ (takeWhile p (l.drop i)).toArray := by diff --git a/src/Init/Data/Nat/Bitwise/Basic.lean b/src/Init/Data/Nat/Bitwise/Basic.lean index ad920d6cfe64..5b43cceb4be3 100644 --- a/src/Init/Data/Nat/Bitwise/Basic.lean +++ b/src/Init/Data/Nat/Bitwise/Basic.lean @@ -144,7 +144,7 @@ of a number. /-- Returns `true` if the `(n+1)`th least significant bit is `1`, or `false` if it is `0`. -/ -@[expose] def testBit (m n : Nat) : Bool := +@[expose, implicit_reducible] def testBit (m n : Nat) : Bool := -- `1 &&& n` is faster than `n &&& 1` for big `n`. 1 &&& (m >>> n) != 0 diff --git a/src/Init/Data/Nat/Bitwise/Lemmas.lean b/src/Init/Data/Nat/Bitwise/Lemmas.lean index 7b3ad59ca192..29f5054f0595 100644 --- a/src/Init/Data/Nat/Bitwise/Lemmas.lean +++ b/src/Init/Data/Nat/Bitwise/Lemmas.lean @@ -410,8 +410,8 @@ theorem testBit_bitwise (of_false_false : f false false = false) (x y i : Nat) : else if y_zero : y = 0 then simp [x_zero, y_zero] cases p : f true false <;> - cases xi : testBit x i <;> - simp [p, xi, of_false_false] + cases testBit x i <;> + simp [p, of_false_false] else simp only [x_zero, y_zero, ←Nat.two_mul] cases i with diff --git a/src/Init/Data/Option/Attach.lean b/src/Init/Data/Option/Attach.lean index 9fe81974d481..1e70c42a981e 100644 --- a/src/Init/Data/Option/Attach.lean +++ b/src/Init/Data/Option/Attach.lean @@ -322,7 +322,7 @@ If this function is encountered in a proof state, the right approach is usually It is a synonym for `Option.map Subtype.val`. -/ -@[expose] +@[expose, instance_reducible] def unattach {α : Type _} {p : α → Prop} (o : Option { x // p x }) := o.map (·.val) @[simp] theorem unattach_none {p : α → Prop} : (none : Option { x // p x }).unattach = none := rfl diff --git a/src/Init/Data/Option/Basic.lean b/src/Init/Data/Option/Basic.lean index 707348ca449a..b8f54754f485 100644 --- a/src/Init/Data/Option/Basic.lean +++ b/src/Init/Data/Option/Basic.lean @@ -58,7 +58,7 @@ deriving instance BEq for Option @[simp, grind =] theorem map_some (a) (f : α → β) : (some a).map f = some (f a) := rfl /-- Lifts an optional value to any `Alternative`, sending `none` to `failure`. -/ -def getM [Alternative m] : Option α → m α +@[instance_reducible] def getM [Alternative m] : Option α → m α | none => failure | some a => pure a @@ -66,7 +66,7 @@ def getM [Alternative m] : Option α → m α @[simp, grind =] theorem getM_some [Alternative m] {a : α} : getM (some a) = (pure a : m α) := rfl /-- Returns `true` on `some x` and `false` on `none`. -/ -@[inline] def isSome : Option α → Bool +@[inline, instance_reducible] def isSome : Option α → Bool | some _ => true | none => false @@ -82,7 +82,7 @@ Examples: * `(none : Option Nat).isNone = true` * `(some Nat.add).isNone = false` -/ -@[inline] def isNone : Option α → Bool +@[inline, instance_reducible] def isNone : Option α → Bool | some _ => false | none => true @@ -118,7 +118,7 @@ Examples: * `(some 2).bind (Option.guard (· > 2)) = none` * `(some 4).bind (Option.guard (· > 2)) = some 4` -/ -@[inline] protected def bind : Option α → (α → Option β) → Option β +@[inline, instance_reducible] protected def bind : Option α → (α → Option β) → Option β | none, _ => none | some a, f => f a @@ -194,7 +194,7 @@ Examples: * `none.filter (fun x : Nat => x % 2 == 0) = none` * `none.filter (fun x : Nat => true) = none` -/ -@[always_inline, inline] protected def filter (p : α → Bool) : Option α → Option α +@[always_inline, inline, instance_reducible] protected def filter (p : α → Bool) : Option α → Option α | some a => if p a then some a else none | none => none @@ -206,7 +206,7 @@ Examples: * `(some 22).all (· % 2 == 0) = true * `none.all (fun x : Nat => x % 2 == 0) = true -/ -@[always_inline, inline] protected def all (p : α → Bool) : Option α → Bool +@[always_inline, inline, instance_reducible] protected def all (p : α → Bool) : Option α → Bool | some a => p a | none => true @@ -221,7 +221,7 @@ Examples: * `(some 22).any (· % 2 == 0) = true * `none.any (fun x : Nat => true) = false -/ -@[always_inline, inline] protected def any (p : α → Bool) : Option α → Bool +@[always_inline, inline, instance_reducible] protected def any (p : α → Bool) : Option α → Bool | some a => p a | none => false @@ -376,7 +376,7 @@ Examples: /-- Extracts the value from an option that can be proven to be `some`. -/ -@[inline] def get {α : Type u} : (o : Option α) → isSome o → α +@[inline, implicit_reducible] def get {α : Type u} : (o : Option α) → isSome o → α | some x, _ => x @[simp, grind =] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x @@ -393,7 +393,7 @@ Examples: * `Option.guard (· > 2) 1 = none` * `Option.guard (· > 2) 5 = some 5` -/ -@[inline] def guard (p : α → Bool) (a : α) : Option α := +@[inline, instance_reducible] def guard (p : α → Bool) (a : α) : Option α := if p a then some a else none /-- @@ -436,7 +436,7 @@ Examples: * `(some none).join = none` * `(some (some v)).join = some v` -/ -@[inline] def join (x : Option (Option α)) : Option α := x.bind id +@[inline, instance_reducible] def join (x : Option (Option α)) : Option α := x.bind id @[simp, grind =] theorem join_none : (none : Option (Option α)).join = none := rfl @[simp, grind =] theorem join_some : (some o).join = o := rfl diff --git a/src/Init/Data/Option/Instances.lean b/src/Init/Data/Option/Instances.lean index bf7e5187d2cc..bab6f0bd2bdc 100644 --- a/src/Init/Data/Option/Instances.lean +++ b/src/Init/Data/Option/Instances.lean @@ -134,14 +134,14 @@ some ⟨3, ⋯⟩ none ``` -/ -@[inline, expose] def pelim (o : Option α) (b : β) (f : (a : α) → o = some a → β) : β := +@[inline, expose, instance_reducible] def pelim (o : Option α) (b : β) (f : (a : α) → o = some a → β) : β := match o with | none => b | some a => f a rfl /-- Partial filter. If `o : Option α`, `p : (a : α) → o = some a → Bool`, then `o.pfilter p` is the same as `o.filter p` but `p` is passed the proof that `o = some a`. -/ -@[inline, expose] def pfilter (o : Option α) (p : (a : α) → o = some a → Bool) : Option α := +@[inline, expose, instance_reducible] def pfilter (o : Option α) (p : (a : α) → o = some a → Bool) : Option α := match o with | none => none | some a => bif p a rfl then o else none diff --git a/src/Init/Data/Ord/Basic.lean b/src/Init/Data/Ord/Basic.lean index e49df155aeda..772419157696 100644 --- a/src/Init/Data/Ord/Basic.lean +++ b/src/Init/Data/Ord/Basic.lean @@ -91,7 +91,7 @@ Ordering.gt Ordering.lt ``` -/ -@[macro_inline, expose] def «then» (a b : Ordering) : Ordering := +@[macro_inline, expose, instance_reducible] def «then» (a b : Ordering) : Ordering := match a with | .eq => b | a => a diff --git a/src/Init/Data/Prod.lean b/src/Init/Data/Prod.lean index 8baac8d8a8d7..0ac2c7800544 100644 --- a/src/Init/Data/Prod.lean +++ b/src/Init/Data/Prod.lean @@ -58,7 +58,7 @@ Examples: * `(1, 2).swap = (2, 1)` * `("orange", -87).swap = (-87, "orange")` -/ -@[expose] def swap : α × β → β × α := fun p => (p.2, p.1) +@[expose, implicit_reducible] def swap : α × β → β × α := fun p => (p.2, p.1) @[simp, grind =] theorem swap_swap : ∀ x : α × β, swap (swap x) = x diff --git a/src/Init/Data/Range/Polymorphic/Lemmas.lean b/src/Init/Data/Range/Polymorphic/Lemmas.lean index a0421905be16..ee9508fd4dab 100644 --- a/src/Init/Data/Range/Polymorphic/Lemmas.lean +++ b/src/Init/Data/Range/Polymorphic/Lemmas.lean @@ -872,7 +872,7 @@ theorem toArray_eq_if_roo [UpwardEnumerable α] [LT α] [DecidableLT α] #[] := by rw [Internal.toArray_eq_toArray_iter, Rxo.Iterator.toArray_eq_match]; rfl -theorem toList_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] +public theorem toList_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] [LawfulUpwardEnumerable α] [Rxo.IsAlwaysFinite α] [LawfulUpwardEnumerableLT α] : r.toList = if r.lower < r.upper then match UpwardEnumerable.succ? r.lower with @@ -881,7 +881,7 @@ theorem toList_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] else [] := by rw [Internal.toList_eq_toList_iter, Rxo.Iterator.toList_eq_match] - simp only [Internal.iter] + simp -implicitDefEqProofs only [Internal.iter.eq_1] split · split · simp [Rxo.Iterator.toList_eq_match, *] @@ -889,7 +889,7 @@ theorem toList_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] rfl · rfl -theorem toArray_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] +public theorem toArray_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] [LawfulUpwardEnumerable α] [Rxo.IsAlwaysFinite α] [LawfulUpwardEnumerableLT α] : r.toArray = if r.lower < r.upper then match UpwardEnumerable.succ? r.lower with @@ -898,7 +898,7 @@ theorem toArray_eq_if_rco [UpwardEnumerable α] [LT α] [DecidableLT α] else #[] := by rw [Internal.toArray_eq_toArray_iter, Rxo.Iterator.toArray_eq_match] - simp only [Internal.iter] + simp -implicitDefEqProofs only [Internal.iter.eq_1] split · split · simp [Rxo.Iterator.toArray_eq_match, *] @@ -1317,7 +1317,7 @@ namespace Roc variable {r : Roc α} -theorem toList_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] +public theorem toList_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α] [Rxc.IsAlwaysFinite α] : r.toList = match UpwardEnumerable.succ? r.lower with | none => [] @@ -1327,9 +1327,9 @@ theorem toList_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] else [] := by rw [Internal.toList_eq_toList_iter, Rxc.Iterator.toList_eq_match (it := Internal.iter r)] - simp [Internal.iter, Internal.toList_eq_toList_iter] + simp -implicitDefEqProofs [Internal.iter.eq_1, Internal.toList_eq_toList_iter] -theorem toArray_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] +public theorem toArray_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α] [Rxc.IsAlwaysFinite α] : r.toArray = match UpwardEnumerable.succ? r.lower with | none => #[] @@ -1339,7 +1339,7 @@ theorem toArray_eq_match [LE α] [DecidableLE α] [UpwardEnumerable α] else #[] := by rw [Internal.toArray_eq_toArray_iter, Rxc.Iterator.toArray_eq_match (it := Internal.iter r)] - simp [Internal.iter, Internal.toArray_eq_toArray_iter] + simp -implicitDefEqProofs [Internal.iter.eq_1, Internal.toArray_eq_toArray_iter] @[cbv_eval] theorem toList_eq_match_rcc [LE α] [DecidableLE α] [UpwardEnumerable α] @@ -1592,18 +1592,18 @@ theorem toList_eq_match_rco [UpwardEnumerable α] [LT α] [DecidableLT α] | none => [] | some next => (next...r.upper).toList := by rw [Internal.toList_eq_toList_iter, Rxo.Iterator.toList_eq_match] - simp only [Internal.iter] + simp -implicitDefEqProofs only [Internal.iter.eq_1] split · rfl · simp [Rco.toList_eq_if_roo, Roo.toList, Internal.iter] -theorem toArray_eq_match_rco [UpwardEnumerable α] [LT α] [DecidableLT α] +public theorem toArray_eq_match_rco [UpwardEnumerable α] [LT α] [DecidableLT α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α] [Rxo.IsAlwaysFinite α] : r.toArray = match UpwardEnumerable.succ? r.lower with | none => #[] | some next => (next...r.upper).toArray := by rw [Internal.toArray_eq_toArray_iter, Rxo.Iterator.toArray_eq_match] - simp only [Internal.iter] + simp -implicitDefEqProofs only [Internal.iter.eq_1] split · rfl · simp [Rco.toArray_eq_if_roo, Roo.toArray, Internal.iter] @@ -2065,7 +2065,7 @@ theorem toList_eq_match_rcc [LE α] [DecidableLE α] [Least? α] [UpwardEnumerab simp only [Internal.toList_eq_toList_iter, Rcc.Internal.toList_eq_toList_iter, Rxc.Iterator.toList_eq_match (it := Internal.iter r), Rxc.Iterator.toList_eq_match (it := Rcc.Internal.iter _)] - simp [Internal.iter, Rcc.Internal.iter] + simp -implicitDefEqProofs [Internal.iter.eq_1, Rcc.Internal.iter.eq_1] theorem toList_eq_toList_rcc [LE α] [DecidableLE α] [Least? α] [UpwardEnumerable α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α] [LawfulUpwardEnumerableLeast? α] @@ -2368,9 +2368,9 @@ theorem toList_eq_match_rco [LT α] [DecidableLT α] [Least? α] [UpwardEnumerab simp only [Internal.toList_eq_toList_iter, Rco.Internal.toList_eq_toList_iter, Rxo.Iterator.toList_eq_match (it := Internal.iter r), Rxo.Iterator.toList_eq_match (it := Rco.Internal.iter _)] - simp [Internal.iter, Rco.Internal.iter] + simp -implicitDefEqProofs [Internal.iter.eq_1, Rco.Internal.iter.eq_1] -theorem toArray_eq_match_rco [LT α] [DecidableLT α] [Least? α] [UpwardEnumerable α] +public theorem toArray_eq_match_rco [LT α] [DecidableLT α] [Least? α] [UpwardEnumerable α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α] [Rxo.IsAlwaysFinite α] : r.toArray = match Least?.least? (α := α) with @@ -2379,7 +2379,7 @@ theorem toArray_eq_match_rco [LT α] [DecidableLT α] [Least? α] [UpwardEnumera simp only [Internal.toArray_eq_toArray_iter, Rco.Internal.toArray_eq_toArray_iter, Rxo.Iterator.toArray_eq_match (it := Internal.iter r), Rxo.Iterator.toArray_eq_match (it := Rco.Internal.iter _)] - simp [Internal.iter, Rco.Internal.iter] + simp -implicitDefEqProofs [Internal.iter.eq_1, Rco.Internal.iter.eq_1] theorem toList_eq_toList_rco [LT α] [DecidableLT α] [Least? α] [UpwardEnumerable α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α] [LawfulUpwardEnumerableLeast? α] diff --git a/src/Init/Data/Rat/Basic.lean b/src/Init/Data/Rat/Basic.lean index 1dc04343844f..2ae9f12357af 100644 --- a/src/Init/Data/Rat/Basic.lean +++ b/src/Init/Data/Rat/Basic.lean @@ -275,6 +275,7 @@ unfold it. Use `Rat.add_def` instead.) instance : Add Rat := ⟨Rat.add⟩ /-- Negation of rational numbers. -/ +@[instance_reducible] protected def neg (a : Rat) : Rat := { a with num := -a.num, reduced := by rw [Int.natAbs_neg]; exact a.reduced } diff --git a/src/Init/Data/Rat/Lemmas.lean b/src/Init/Data/Rat/Lemmas.lean index c31acd531937..1ef0bf423824 100644 --- a/src/Init/Data/Rat/Lemmas.lean +++ b/src/Init/Data/Rat/Lemmas.lean @@ -179,10 +179,14 @@ theorem mk'_eq_divInt {n d h c} : (⟨n, d, h, c⟩ : Rat) = n /. d := (num_divI @[deprecated num_divInt_den (since := "2025-08-22")] abbrev divInt_self := @num_divInt_den +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in @[simp] theorem zero_divInt (n) : 0 /. n = 0 := by cases n <;> simp [divInt] @[simp] theorem divInt_zero (n) : n /. 0 = 0 := mkRat_zero n +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem neg_divInt_neg (num den) : -num /. -den = num /. den := by match den with | Nat.succ n => @@ -225,6 +229,8 @@ theorem divInt_num_den (z : d ≠ 0) (h : n /. d = ⟨n', d', z', c⟩) : rw [← Int.neg_inj, Int.neg_neg] at h₂ simp [Int.natCast_mul, h₁, h₂, Int.mul_neg, Int.neg_eq_zero] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem num_divInt (a b : Int) : (a /. b).num = b.sign * a / b.gcd a := by rw [divInt.eq_def] simp only [inline, Nat.succ_eq_add_one] @@ -236,6 +242,8 @@ theorem num_divInt (a b : Int) : (a /. b).num = b.sign * a / b.gcd a := by simp · simp [Int.gcd, Nat.gcd_comm] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem den_divInt (a b : Int) : (a /. b).den = if b = 0 then 1 else b.natAbs / b.gcd a := by rw [divInt.eq_def] simp only [inline, Nat.succ_eq_add_one] diff --git a/src/Init/Data/SInt/Basic.lean b/src/Init/Data/SInt/Basic.lean index d113f9629ef3..901d39f8205f 100644 --- a/src/Init/Data/SInt/Basic.lean +++ b/src/Init/Data/SInt/Basic.lean @@ -90,7 +90,7 @@ abbrev Int8.size : Nat := 256 /-- Obtain the `BitVec` that contains the 2's complement representation of the `Int8`. -/ -@[inline] def Int8.toBitVec (x : Int8) : BitVec 8 := x.toUInt8.toBitVec -- +@[inline, instance_reducible] def Int8.toBitVec (x : Int8) : BitVec 8 := x.toUInt8.toBitVec -- theorem Int8.toBitVec.inj : {x y : Int8} → x.toBitVec = y.toBitVec → x = y | ⟨⟨_⟩⟩, ⟨⟨_⟩⟩, rfl => rfl @@ -109,7 +109,7 @@ Examples: * `Int8.ofInt (-129) = 127` * `Int8.ofInt (128) = -128` -/ -@[extern "lean_int8_of_int"] +@[extern "lean_int8_of_int", implicit_reducible] def Int8.ofInt (i : @& Int) : Int8 := ⟨⟨BitVec.ofInt 8 i⟩⟩ /-- Converts a natural number to an 8-bit signed integer, wrapping around on overflow. @@ -122,7 +122,7 @@ Examples: * `Int8.ofNat 128 = -128` * `Int8.ofNat 255 = -1` -/ -@[extern "lean_int8_of_nat"] +@[extern "lean_int8_of_nat", instance_reducible] def Int8.ofNat (n : @& Nat) : Int8 := ⟨⟨BitVec.ofNat 8 n⟩⟩ /-- Converts an arbitrary-precision integer to an 8-bit integer, wrapping on overflow or underflow. @@ -151,14 +151,14 @@ Converts an 8-bit signed integer to an arbitrary-precision integer that denotes This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int8_to_int", tagged_return] +@[extern "lean_int8_to_int", tagged_return, instance_reducible] def Int8.toInt (i : Int8) : Int := i.toBitVec.toInt /-- Converts an 8-bit signed integer to a natural number, mapping all negative numbers to `0`. Use `Int8.toBitVec` to obtain the two's complement representation. -/ -@[suggest_for Int8.toNat, inline] def Int8.toNatClampNeg (i : Int8) : Nat := i.toInt.toNat +@[suggest_for Int8.toNat, inline, implicit_reducible] def Int8.toNatClampNeg (i : Int8) : Nat := i.toInt.toNat /-- Obtains the `Int8` whose 2's complement representation is the given `BitVec 8`. -/ @[inline] def Int8.ofBitVec (b : BitVec 8) : Int8 := ⟨⟨b⟩⟩ @@ -167,7 +167,7 @@ Negates 8-bit signed integers. Usually accessed via the `-` prefix operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int8_neg"] +@[extern "lean_int8_neg", instance_reducible] def Int8.neg (i : Int8) : Int8 := ⟨⟨-i.toBitVec⟩⟩ instance : ToString Int8 where @@ -188,7 +188,7 @@ abbrev Int8.maxValue : Int8 := 127 /-- The smallest number that `Int8` can represent: `-2^7 = -128`. -/ abbrev Int8.minValue : Int8 := -128 /-- Constructs an `Int8` from an `Int` that is known to be in bounds. -/ -@[inline] +@[inline, implicit_reducible] def Int8.ofIntLE (i : Int) (_hl : Int8.minValue.toInt ≤ i) (_hr : i ≤ Int8.maxValue.toInt) : Int8 := Int8.ofInt i /-- Constructs an `Int8` from an `Int`, clamping if the value is too small or too large. -/ @@ -210,7 +210,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int8_add"] +@[extern "lean_int8_add", implicit_reducible] protected def Int8.add (a b : Int8) : Int8 := ⟨⟨a.toBitVec + b.toBitVec⟩⟩ /-- Subtracts one 8-bit signed integer from another, wrapping around on over- or underflow. Usually @@ -218,7 +218,7 @@ accessed via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int8_sub"] +@[extern "lean_int8_sub", implicit_reducible] protected def Int8.sub (a b : Int8) : Int8 := ⟨⟨a.toBitVec - b.toBitVec⟩⟩ /-- Multiplies two 8-bit signed integers, wrapping around on over- or underflow. Usually accessed via @@ -226,7 +226,7 @@ the `*` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int8_mul"] +@[extern "lean_int8_mul", implicit_reducible] protected def Int8.mul (a b : Int8) : Int8 := ⟨⟨a.toBitVec * b.toBitVec⟩⟩ /-- Truncating division for 8-bit signed integers, rounding towards zero. Usually accessed via the `/` @@ -243,7 +243,7 @@ Examples: * `Int8.div (-10) 3 = (-3)` * `Int8.div 10 0 = 0` -/ -@[extern "lean_int8_div"] +@[extern "lean_int8_div", implicit_reducible] protected def Int8.div (a b : Int8) : Int8 := ⟨⟨BitVec.sdiv a.toBitVec b.toBitVec⟩⟩ /-- The power operation, raising an 8-bit signed integer to a natural number power, @@ -275,7 +275,7 @@ Examples: * `Int8.mod 4 0 = 4` * `Int8.mod (-4) 0 = (-4)` -/ -@[extern "lean_int8_mod"] +@[extern "lean_int8_mod", implicit_reducible] protected def Int8.mod (a b : Int8) : Int8 := ⟨⟨BitVec.srem a.toBitVec b.toBitVec⟩⟩ /-- Bitwise and for 8-bit signed integers. Usually accessed via the `&&&` operator. @@ -445,7 +445,7 @@ abbrev Int16.size : Nat := 65536 /-- Obtain the `BitVec` that contains the 2's complement representation of the `Int16`. -/ -@[inline] def Int16.toBitVec (x : Int16) : BitVec 16 := x.toUInt16.toBitVec +@[inline, instance_reducible] def Int16.toBitVec (x : Int16) : BitVec 16 := x.toUInt16.toBitVec theorem Int16.toBitVec.inj : {x y : Int16} → x.toBitVec = y.toBitVec → x = y | ⟨⟨_⟩⟩, ⟨⟨_⟩⟩, rfl => rfl @@ -465,7 +465,7 @@ Examples: * `Int16.ofInt 70000 = 4464` * `Int16.ofInt (-40000) = 25536` -/ -@[extern "lean_int16_of_int"] +@[extern "lean_int16_of_int", implicit_reducible] def Int16.ofInt (i : @& Int) : Int16 := ⟨⟨BitVec.ofInt 16 i⟩⟩ /-- Converts a natural number to a 16-bit signed integer, wrapping around on overflow. @@ -478,7 +478,7 @@ Examples: * `Int16.ofNat 32768 = -32768` * `Int16.ofNat 32770 = -32766` -/ -@[extern "lean_int16_of_nat"] +@[extern "lean_int16_of_nat", instance_reducible] def Int16.ofNat (n : @& Nat) : Int16 := ⟨⟨BitVec.ofNat 16 n⟩⟩ /-- Converts an arbitrary-precision integer to a 16-bit integer, wrapping on overflow or underflow. @@ -508,14 +508,14 @@ Converts a 16-bit signed integer to an arbitrary-precision integer that denotes This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int16_to_int", tagged_return] +@[extern "lean_int16_to_int", tagged_return, instance_reducible] def Int16.toInt (i : Int16) : Int := i.toBitVec.toInt /-- Converts a 16-bit signed integer to a natural number, mapping all negative numbers to `0`. Use `Int16.toBitVec` to obtain the two's complement representation. -/ -@[suggest_for Int16.toNat, inline] def Int16.toNatClampNeg (i : Int16) : Nat := i.toInt.toNat +@[suggest_for Int16.toNat, inline, implicit_reducible] def Int16.toNatClampNeg (i : Int16) : Nat := i.toInt.toNat /-- Obtains the `Int16` whose 2's complement representation is the given `BitVec 16`. -/ @[inline] def Int16.ofBitVec (b : BitVec 16) : Int16 := ⟨⟨b⟩⟩ @@ -539,7 +539,7 @@ Negates 16-bit signed integers. Usually accessed via the `-` prefix operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int16_neg"] +@[extern "lean_int16_neg", instance_reducible] def Int16.neg (i : Int16) : Int16 := ⟨⟨-i.toBitVec⟩⟩ instance : ToString Int16 where @@ -560,7 +560,7 @@ abbrev Int16.maxValue : Int16 := 32767 /-- The smallest number that `Int16` can represent: `-2^15 = -32768`. -/ abbrev Int16.minValue : Int16 := -32768 /-- Constructs an `Int16` from an `Int` that is known to be in bounds. -/ -@[inline] +@[inline, implicit_reducible] def Int16.ofIntLE (i : Int) (_hl : Int16.minValue.toInt ≤ i) (_hr : i ≤ Int16.maxValue.toInt) : Int16 := Int16.ofInt i /-- Constructs an `Int16` from an `Int`, clamping if the value is too small or too large. -/ @@ -583,7 +583,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int16_add"] +@[extern "lean_int16_add", implicit_reducible] protected def Int16.add (a b : Int16) : Int16 := ⟨⟨a.toBitVec + b.toBitVec⟩⟩ /-- Subtracts one 16-bit signed integer from another, wrapping around on over- or underflow. Usually @@ -591,7 +591,7 @@ accessed via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int16_sub"] +@[extern "lean_int16_sub", implicit_reducible] protected def Int16.sub (a b : Int16) : Int16 := ⟨⟨a.toBitVec - b.toBitVec⟩⟩ /-- Multiplies two 16-bit signed integers, wrapping around on over- or underflow. Usually accessed via @@ -599,7 +599,7 @@ the `*` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int16_mul"] +@[extern "lean_int16_mul", implicit_reducible] protected def Int16.mul (a b : Int16) : Int16 := ⟨⟨a.toBitVec * b.toBitVec⟩⟩ /-- Truncating division for 16-bit signed integers, rounding towards zero. Usually accessed via the `/` @@ -616,7 +616,7 @@ Examples: * `Int16.div (-10) 3 = (-3)` * `Int16.div 10 0 = 0` -/ -@[extern "lean_int16_div"] +@[extern "lean_int16_div", implicit_reducible] protected def Int16.div (a b : Int16) : Int16 := ⟨⟨BitVec.sdiv a.toBitVec b.toBitVec⟩⟩ /-- The power operation, raising a 16-bit signed integer to a natural number power, @@ -648,7 +648,7 @@ Examples: * `Int16.mod 4 0 = 4` * `Int16.mod (-4) 0 = (-4)` -/ -@[extern "lean_int16_mod"] +@[extern "lean_int16_mod", implicit_reducible] protected def Int16.mod (a b : Int16) : Int16 := ⟨⟨BitVec.srem a.toBitVec b.toBitVec⟩⟩ /-- Bitwise and for 16-bit signed integers. Usually accessed via the `&&&` operator. @@ -818,7 +818,7 @@ abbrev Int32.size : Nat := 4294967296 /-- Obtain the `BitVec` that contains the 2's complement representation of the `Int32`. -/ -@[inline] def Int32.toBitVec (x : Int32) : BitVec 32 := x.toUInt32.toBitVec +@[inline, instance_reducible] def Int32.toBitVec (x : Int32) : BitVec 32 := x.toUInt32.toBitVec theorem Int32.toBitVec.inj : {x y : Int32} → x.toBitVec = y.toBitVec → x = y | ⟨⟨_⟩⟩, ⟨⟨_⟩⟩, rfl => rfl @@ -839,7 +839,7 @@ Examples: * `Int32.ofInt 2147483648 = -2147483648` * `Int32.ofInt (-2147483649) = 2147483647` -/ -@[extern "lean_int32_of_int"] +@[extern "lean_int32_of_int", implicit_reducible] def Int32.ofInt (i : @& Int) : Int32 := ⟨⟨BitVec.ofInt 32 i⟩⟩ /-- Converts a natural number to a 32-bit signed integer, wrapping around on overflow. @@ -852,7 +852,7 @@ Examples: * `Int32.ofNat 2_147_483_647 = 2_147_483_647` * `Int32.ofNat 2_147_483_648 = -2_147_483_648` -/ -@[extern "lean_int32_of_nat"] +@[extern "lean_int32_of_nat", instance_reducible] def Int32.ofNat (n : @& Nat) : Int32 := ⟨⟨BitVec.ofNat 32 n⟩⟩ /-- Converts an arbitrary-precision integer to a 32-bit integer, wrapping on overflow or underflow. @@ -882,14 +882,14 @@ Converts a 32-bit signed integer to an arbitrary-precision integer that denotes This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int32_to_int"] +@[extern "lean_int32_to_int", instance_reducible] def Int32.toInt (i : Int32) : Int := i.toBitVec.toInt /-- Converts a 32-bit signed integer to a natural number, mapping all negative numbers to `0`. Use `Int32.toBitVec` to obtain the two's complement representation. -/ -@[suggest_for Int32.toNat, inline] def Int32.toNatClampNeg (i : Int32) : Nat := i.toInt.toNat +@[suggest_for Int32.toNat, inline, implicit_reducible] def Int32.toNatClampNeg (i : Int32) : Nat := i.toInt.toNat /-- Obtains the `Int32` whose 2's complement representation is the given `BitVec 32`. -/ @[inline] def Int32.ofBitVec (b : BitVec 32) : Int32 := ⟨⟨b⟩⟩ @@ -928,7 +928,7 @@ Negates 32-bit signed integers. Usually accessed via the `-` prefix operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int32_neg"] +@[extern "lean_int32_neg", instance_reducible] def Int32.neg (i : Int32) : Int32 := ⟨⟨-i.toBitVec⟩⟩ instance : ToString Int32 where @@ -949,7 +949,7 @@ abbrev Int32.maxValue : Int32 := 2147483647 /-- The smallest number that `Int32` can represent: `-2^31 = -2147483648`. -/ abbrev Int32.minValue : Int32 := -2147483648 /-- Constructs an `Int32` from an `Int` that is known to be in bounds. -/ -@[inline] +@[inline, implicit_reducible] def Int32.ofIntLE (i : Int) (_hl : Int32.minValue.toInt ≤ i) (_hr : i ≤ Int32.maxValue.toInt) : Int32 := Int32.ofInt i /-- Constructs an `Int32` from an `Int`, clamping if the value is too small or too large. -/ @@ -972,7 +972,7 @@ Adds two 32-bit signed integers, wrapping around on over- or underflow. Usually This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int32_add"] +@[extern "lean_int32_add", implicit_reducible] protected def Int32.add (a b : Int32) : Int32 := ⟨⟨a.toBitVec + b.toBitVec⟩⟩ /-- Subtracts one 32-bit signed integer from another, wrapping around on over- or underflow. Usually @@ -980,7 +980,7 @@ accessed via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int32_sub"] +@[extern "lean_int32_sub", implicit_reducible] protected def Int32.sub (a b : Int32) : Int32 := ⟨⟨a.toBitVec - b.toBitVec⟩⟩ /-- Multiplies two 32-bit signed integers, wrapping around on over- or underflow. Usually accessed via @@ -988,7 +988,7 @@ the `*` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int32_mul"] +@[extern "lean_int32_mul", implicit_reducible] protected def Int32.mul (a b : Int32) : Int32 := ⟨⟨a.toBitVec * b.toBitVec⟩⟩ /-- Truncating division for 32-bit signed integers, rounding towards zero. Usually accessed via the `/` @@ -1005,7 +1005,7 @@ Examples: * `Int32.div (-10) 3 = (-3)` * `Int32.div 10 0 = 0` -/ -@[extern "lean_int32_div"] +@[extern "lean_int32_div", implicit_reducible] protected def Int32.div (a b : Int32) : Int32 := ⟨⟨BitVec.sdiv a.toBitVec b.toBitVec⟩⟩ /-- The power operation, raising a 32-bit signed integer to a natural number power, @@ -1037,7 +1037,7 @@ Examples: * `Int32.mod 4 0 = 4` * `Int32.mod (-4) 0 = (-4)` -/ -@[extern "lean_int32_mod"] +@[extern "lean_int32_mod", implicit_reducible] protected def Int32.mod (a b : Int32) : Int32 := ⟨⟨BitVec.srem a.toBitVec b.toBitVec⟩⟩ /-- Bitwise and for 32-bit signed integers. Usually accessed via the `&&&` operator. @@ -1207,7 +1207,7 @@ abbrev Int64.size : Nat := 18446744073709551616 /-- Obtain the `BitVec` that contains the 2's complement representation of the `Int64`. -/ -@[inline] def Int64.toBitVec (x : Int64) : BitVec 64 := x.toUInt64.toBitVec +@[inline, instance_reducible] def Int64.toBitVec (x : Int64) : BitVec 64 := x.toUInt64.toBitVec theorem Int64.toBitVec.inj : {x y : Int64} → x.toBitVec = y.toBitVec → x = y | ⟨⟨_⟩⟩, ⟨⟨_⟩⟩, rfl => rfl @@ -1228,7 +1228,7 @@ Examples: * `Int64.ofInt 9_223_372_036_854_775_808 = -9_223_372_036_854_775_808` * `Int64.ofInt (-9_223_372_036_854_775_809) = 9_223_372_036_854_775_807` -/ -@[extern "lean_int64_of_int"] +@[extern "lean_int64_of_int", implicit_reducible] def Int64.ofInt (i : @& Int) : Int64 := ⟨⟨BitVec.ofInt 64 i⟩⟩ /-- Converts a natural number to a 64-bit signed integer, wrapping around to negative numbers on @@ -1243,7 +1243,7 @@ Examples: * `Int64.ofNat 9_223_372_036_854_775_808 = -9_223_372_036_854_775_808` * `Int64.ofNat 18_446_744_073_709_551_618 = 0` -/ -@[extern "lean_int64_of_nat"] +@[extern "lean_int64_of_nat", instance_reducible] def Int64.ofNat (n : @& Nat) : Int64 := ⟨⟨BitVec.ofNat 64 n⟩⟩ /-- Converts an arbitrary-precision integer to a 64-bit integer, wrapping on overflow or underflow. @@ -1276,14 +1276,14 @@ Converts a 64-bit signed integer to an arbitrary-precision integer that denotes This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int64_to_int_sint"] +@[extern "lean_int64_to_int_sint", instance_reducible] def Int64.toInt (i : Int64) : Int := i.toBitVec.toInt /-- Converts a 64-bit signed integer to a natural number, mapping all negative numbers to `0`. Use `Int64.toBitVec` to obtain the two's complement representation. -/ -@[suggest_for Int64.toNat, inline] def Int64.toNatClampNeg (i : Int64) : Nat := i.toInt.toNat +@[suggest_for Int64.toNat, inline, implicit_reducible] def Int64.toNatClampNeg (i : Int64) : Nat := i.toInt.toNat /-- Obtains the `Int64` whose 2's complement representation is the given `BitVec 64`. -/ @[inline] def Int64.ofBitVec (b : BitVec 64) : Int64 := ⟨⟨b⟩⟩ @@ -1337,7 +1337,7 @@ Negates 64-bit signed integers. Usually accessed via the `-` prefix operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int64_neg"] +@[extern "lean_int64_neg", instance_reducible] def Int64.neg (i : Int64) : Int64 := ⟨⟨-i.toBitVec⟩⟩ instance : ToString Int64 where @@ -1358,7 +1358,7 @@ abbrev Int64.maxValue : Int64 := 9223372036854775807 /-- The smallest number that `Int64` can represent: `-2^63 = -9223372036854775808`. -/ abbrev Int64.minValue : Int64 := -9223372036854775808 /-- Constructs an `Int64` from an `Int` that is known to be in bounds. -/ -@[inline] +@[inline, implicit_reducible] def Int64.ofIntLE (i : Int) (_hl : Int64.minValue.toInt ≤ i) (_hr : i ≤ Int64.maxValue.toInt) : Int64 := Int64.ofInt i /-- Constructs an `Int64` from an `Int`, clamping if the value is too small or too large. -/ @@ -1381,7 +1381,7 @@ Adds two 64-bit signed integers, wrapping around on over- or underflow. Usually This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int64_add"] +@[extern "lean_int64_add", implicit_reducible] protected def Int64.add (a b : Int64) : Int64 := ⟨⟨a.toBitVec + b.toBitVec⟩⟩ /-- Subtracts one 64-bit signed integer from another, wrapping around on over- or underflow. Usually @@ -1389,7 +1389,7 @@ accessed via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int64_sub"] +@[extern "lean_int64_sub", implicit_reducible] protected def Int64.sub (a b : Int64) : Int64 := ⟨⟨a.toBitVec - b.toBitVec⟩⟩ /-- Multiplies two 64-bit signed integers, wrapping around on over- or underflow. Usually accessed via @@ -1397,7 +1397,7 @@ the `*` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_int64_mul"] +@[extern "lean_int64_mul", implicit_reducible] protected def Int64.mul (a b : Int64) : Int64 := ⟨⟨a.toBitVec * b.toBitVec⟩⟩ /-- Truncating division for 64-bit signed integers, rounding towards zero. Usually accessed via the `/` @@ -1414,7 +1414,7 @@ Examples: * `Int64.div (-10) 3 = (-3)` * `Int64.div 10 0 = 0` -/ -@[extern "lean_int64_div"] +@[extern "lean_int64_div", implicit_reducible] protected def Int64.div (a b : Int64) : Int64 := ⟨⟨BitVec.sdiv a.toBitVec b.toBitVec⟩⟩ /-- The power operation, raising a 64-bit signed integer to a natural number power, @@ -1446,7 +1446,7 @@ Examples: * `Int64.mod 4 0 = 4` * `Int64.mod (-4) 0 = (-4)` -/ -@[extern "lean_int64_mod"] +@[extern "lean_int64_mod", implicit_reducible] protected def Int64.mod (a b : Int64) : Int64 := ⟨⟨BitVec.srem a.toBitVec b.toBitVec⟩⟩ /-- Bitwise and for 64-bit signed integers. Usually accessed via the `&&&` operator. @@ -1615,7 +1615,7 @@ abbrev ISize.size : Nat := 2^System.Platform.numBits /-- Obtain the `BitVec` that contains the 2's complement representation of the `ISize`. -/ -@[inline] def ISize.toBitVec (x : ISize) : BitVec System.Platform.numBits := x.toUSize.toBitVec +@[inline, instance_reducible] def ISize.toBitVec (x : ISize) : BitVec System.Platform.numBits := x.toUSize.toBitVec theorem ISize.toBitVec.inj : {x y : ISize} → x.toBitVec = y.toBitVec → x = y | ⟨⟨_⟩⟩, ⟨⟨_⟩⟩, rfl => rfl @@ -1637,7 +1637,7 @@ overflow. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_of_nat"] +@[extern "lean_isize_of_nat", instance_reducible] def ISize.ofNat (n : @& Nat) : ISize := ⟨⟨BitVec.ofNat System.Platform.numBits n⟩⟩ @[inherit_doc ISize.ofInt] abbrev Int.toISize := ISize.ofInt @@ -1647,14 +1647,14 @@ Converts a word-sized signed integer to an arbitrary-precision integer that deno This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_to_int"] +@[extern "lean_isize_to_int", instance_reducible] def ISize.toInt (i : ISize) : Int := i.toBitVec.toInt /-- Converts a word-sized signed integer to a natural number, mapping all negative numbers to `0`. Use `ISize.toBitVec` to obtain the two's complement representation. -/ -@[suggest_for ISize.toNat, inline] def ISize.toNatClampNeg (i : ISize) : Nat := i.toInt.toNat +@[suggest_for ISize.toNat, inline, implicit_reducible] def ISize.toNatClampNeg (i : ISize) : Nat := i.toInt.toNat /-- Obtains the `ISize` whose 2's complement representation is the given `BitVec`. -/ @[inline] def ISize.ofBitVec (b : BitVec System.Platform.numBits) : ISize := ⟨⟨b⟩⟩ @@ -1728,7 +1728,7 @@ Negates word-sized signed integers. Usually accessed via the `-` prefix operator This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_neg"] +@[extern "lean_isize_neg", instance_reducible] protected def ISize.neg (i : ISize) : ISize := ⟨⟨-i.toBitVec⟩⟩ instance : ToString ISize where @@ -1773,7 +1773,7 @@ the `+` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_add"] +@[extern "lean_isize_add", implicit_reducible] protected def ISize.add (a b : ISize) : ISize := ⟨⟨a.toBitVec + b.toBitVec⟩⟩ /-- Subtracts one word-sized signed integer from another, wrapping around on over- or underflow. Usually @@ -1781,7 +1781,7 @@ accessed via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_sub"] +@[extern "lean_isize_sub", implicit_reducible] protected def ISize.sub (a b : ISize) : ISize := ⟨⟨a.toBitVec - b.toBitVec⟩⟩ /-- Multiplies two word-sized signed integers, wrapping around on over- or underflow. Usually accessed @@ -1789,7 +1789,7 @@ via the `*` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_isize_mul"] +@[extern "lean_isize_mul", implicit_reducible] protected def ISize.mul (a b : ISize) : ISize := ⟨⟨a.toBitVec * b.toBitVec⟩⟩ /-- Truncating division for word-sized signed integers, rounding towards zero. Usually accessed via the @@ -1806,7 +1806,7 @@ Examples: * `ISize.div (-10) 3 = (-3)` * `ISize.div 10 0 = 0` -/ -@[extern "lean_isize_div"] +@[extern "lean_isize_div", implicit_reducible] protected def ISize.div (a b : ISize) : ISize := ⟨⟨BitVec.sdiv a.toBitVec b.toBitVec⟩⟩ /-- The power operation, raising a word-sized signed integer to a natural number power, @@ -1838,7 +1838,7 @@ Examples: * `ISize.mod 4 0 = 4` * `ISize.mod (-4) 0 = (-4)` -/ -@[extern "lean_isize_mod"] +@[extern "lean_isize_mod", implicit_reducible] protected def ISize.mod (a b : ISize) : ISize := ⟨⟨BitVec.srem a.toBitVec b.toBitVec⟩⟩ /-- Bitwise and for word-sized signed integers. Usually accessed via the `&&&` operator. diff --git a/src/Init/Data/SInt/Lemmas.lean b/src/Init/Data/SInt/Lemmas.lean index 9bac38deecd2..30be3e0b0952 100644 --- a/src/Init/Data/SInt/Lemmas.lean +++ b/src/Init/Data/SInt/Lemmas.lean @@ -1864,7 +1864,7 @@ theorem ISize.toInt_div_of_ne_right (a b : ISize) (h : b ≠ -1) : (a / b).toInt exact Or.inr (by simpa [← toBitVec_inj] using h) theorem Int8.toInt16_ne_minValue (a : Int8) : a.toInt16 ≠ Int16.minValue := - have := a.le_toInt; by simp [← Int16.toInt_inj]; omega + have := a.le_toInt; by simp[← Int16.toInt_inj]; omega theorem Int8.toInt32_ne_minValue (a : Int8) : a.toInt32 ≠ Int32.minValue := have := a.le_toInt; by simp [← Int32.toInt_inj]; omega theorem Int8.toInt64_ne_minValue (a : Int8) : a.toInt64 ≠ Int64.minValue := diff --git a/src/Init/Data/Slice/Array/Lemmas.lean b/src/Init/Data/Slice/Array/Lemmas.lean index c86f01b1f1d6..1aa52b1f881d 100644 --- a/src/Init/Data/Slice/Array/Lemmas.lean +++ b/src/Init/Data/Slice/Array/Lemmas.lean @@ -44,16 +44,8 @@ theorem step_eq {it : Iter (α := SubarrayIterator α) α} : simp only [Iter.step, IterM.Step.toPure, Iter.toIter_toIterM, IterStep.mapIterator, IterM.step, Iterator.step, SubarrayIterator.step, Id.run_pure, Shrink.inflate_deflate] by_cases h : it.internalState.xs.start < it.internalState.xs.stop - · simp only [h, ↓reduceDIte] - split - · rfl - · rename_i h' - exact h'.elim h - · simp only [h, ↓reduceDIte] - split - · rename_i h' - exact h.elim h' - · rfl + · simp [h, ↓reduceDIte] + · simp [h, ↓reduceDIte] theorem val_step_eq {it : Iter (α := SubarrayIterator α) α} : it.step.val = if h : it.1.xs.start < it.1.xs.stop then diff --git a/src/Init/Data/String/Basic.lean b/src/Init/Data/String/Basic.lean index 7ff696d6c286..9b9ff83da44b 100644 --- a/src/Init/Data/String/Basic.lean +++ b/src/Init/Data/String/Basic.lean @@ -70,11 +70,11 @@ theorem ByteArray.isValidUTF8_utf8Encode_singleton_append_iff {b : ByteArray} {c Decodes a sequence of characters from their UTF-8 representation. Returns `none` if the bytes are not a sequence of Unicode scalar values. -/ -@[inline, expose] +@[inline, expose, implicit_reducible] def ByteArray.utf8Decode? (b : ByteArray) : Option (Array Char) := go 0 #[] (by simp) where - @[semireducible] + @[semireducible, implicit_reducible] go (i : Nat) (acc : Array Char) (hi : i ≤ b.size) : Option (Array Char) := if i < b.size then match h : utf8DecodeChar? b i with @@ -218,7 +218,7 @@ theorem List.asString_append {l₁ l₂ : List Char} : String.ofList (l₁ ++ l₂) = String.ofList l₁ ++ String.ofList l₂ := String.ofList_append -@[expose] +@[expose, implicit_reducible] def String.Internal.toArray (b : String) : Array Char := b.toByteArray.utf8Decode?.get (b.toByteArray.isSome_utf8Decode?_iff.2 b.isValidUTF8) @@ -237,7 +237,7 @@ Examples: * `"".toList = []` * `"\n".toList = ['\n']` -/ -@[extern "lean_string_data", expose] +@[extern "lean_string_data", expose, implicit_reducible] def String.toList (s : String) : List Char := (String.Internal.toArray s).toList @@ -1005,7 +1005,7 @@ theorem Slice.Pos.offset_ofStr {s : Slice} {pos : s.str.Pos} {h₁ h₂} : /-- Given a slice and a valid position within the slice, obtain a new slice on the same underlying string by replacing the start of the slice with the given position. -/ -@[inline, expose] -- for the defeq `(s.sliceFrom pos).str = s.str` +@[inline, expose, instance_reducible] -- for the defeq `(s.sliceFrom pos).str = s.str` def Slice.sliceFrom (s : Slice) (pos : s.Pos) : Slice where str := s.str startInclusive := pos.str @@ -1030,7 +1030,7 @@ theorem Slice.endExclusive_sliceFrom {s : Slice} {pos : s.Pos} : /-- Given a slice and a valid position within the slice, obtain a new slice on the same underlying string by replacing the end of the slice with the given position. -/ -@[inline, expose] -- for the defeq `(s.sliceTo pos).str = s.str` +@[inline, expose, instance_reducible] -- for the defeq `(s.sliceTo pos).str = s.str` def Slice.sliceTo (s : Slice) (pos : s.Pos) : Slice where str := s.str startInclusive := s.startInclusive @@ -1055,7 +1055,7 @@ theorem Slice.endExclusive_sliceTo {s : Slice} {pos : s.Pos} : /-- Given a slice and two valid positions within the slice, obtain a new slice on the same underlying string formed by the new bounds. -/ -@[inline, expose] -- for the defeq `(s.slice newStart newEnd).str = s.str` +@[inline, expose, instance_reducible] -- for the defeq `(s.slice newStart newEnd).str = s.str` def Slice.slice (s : Slice) (newStart newEnd : s.Pos) (h : newStart ≤ newEnd) : Slice where str := s.str @@ -1194,7 +1194,7 @@ theorem Pos.Raw.IsValidForSlice.ofSlice {s : String} {p : Pos.Raw} (h : p.IsVali isValidForSlice_toSlice_iff.1 h /-- Turns a valid position on the string `s` into a valid position on the slice `s.toSlice`. -/ -@[inline, expose] +@[inline, expose, instance_reducible] def Pos.toSlice {s : String} (pos : s.Pos) : s.toSlice.Pos where offset := pos.offset isValidForSlice := pos.isValid.toSlice @@ -1703,7 +1703,7 @@ def pos! (s : String) (off : Pos.Raw) : s.Pos := Pos.ofToSlice (s.toSlice.pos! off) @[simp] -theorem offset_pos {s : String} {off : Pos.Raw} {h} : (s.pos off h).offset = off := rfl +theorem offset_pos {s : String} {off : Pos.Raw} {h} : (s.pos off h).offset = off := (rfl) /-- Constructs a valid position on `t` from a valid position on `s` and a proof that `s.copy = t.copy`. -/ @@ -1969,7 +1969,7 @@ theorem Pos.get_toSlice {s : String} {p : s.Pos} {h} : rfl theorem Pos.get_eq_get_toSlice {s : String} {p : s.Pos} {h} : - p.get h = p.toSlice.get (ne_of_apply_ne Pos.ofToSlice (by simp [h])) := rfl + p.get h = p.toSlice.get (ne_of_apply_ne Pos.ofToSlice (by simp [h])) := (rfl) @[simp] theorem Pos.offset_next {s : String} (p : s.Pos) (h : p ≠ s.endPos) : @@ -2136,7 +2136,7 @@ theorem Slice.Pos.next_eq_nextFast : @Slice.Pos.next = @Slice.Pos.nextFast := by omega /-- The slice from the beginning of `s` up to `p` (exclusive). -/ -@[inline, expose] +@[inline, expose, instance_reducible] def sliceTo (s : String) (p : s.Pos) : Slice := s.toSlice.sliceTo p.toSlice @@ -2167,7 +2167,7 @@ theorem Pos.Raw.isValidForSlice_stringSliceTo {s : String} {p : s.Pos} {q : Pos. rw [sliceTo, isValidForSlice_sliceTo, Pos.offset_toSlice, isValidForSlice_toSlice_iff] /-- The slice from `p` (inclusive) up to the end of `s`. -/ -@[inline, expose] +@[inline, expose, instance_reducible] def sliceFrom (s : String) (p : s.Pos) : Slice := s.toSlice.sliceFrom p.toSlice @@ -2221,7 +2221,7 @@ the two positions. This happens to be equivalent to the constructor of `String.Slice`. -/ -@[inline, expose] -- For the defeq `(s.slice p₁ p₂).str = s` +@[inline, expose, instance_reducible] -- For the defeq `(s.slice p₁ p₂).str = s` def slice (s : String) (startInclusive endExclusive : s.Pos) (h : startInclusive ≤ endExclusive) : String.Slice := s.toSlice.slice startInclusive.toSlice endExclusive.toSlice (by simpa) diff --git a/src/Init/Data/String/Bootstrap.lean b/src/Init/Data/String/Bootstrap.lean index ba62e40a0df2..7f478a9ff94a 100644 --- a/src/Init/Data/String/Bootstrap.lean +++ b/src/Init/Data/String/Bootstrap.lean @@ -29,7 +29,7 @@ Examples: * `"abc".push 'd' = "abcd"` * `"".push 'a' = "a"` -/ -@[extern "lean_string_push", expose] +@[extern "lean_string_push", expose, implicit_reducible] def push : String → Char → String | ⟨b, h⟩, c => ⟨b.append (List.utf8Encode [c]), ?pf⟩ where finally @@ -48,7 +48,7 @@ Examples: * `String.singleton '"' = "\""` * `String.singleton '𝒫' = "𝒫"` -/ -@[inline, expose] def singleton (c : Char) : String := +@[inline, expose, implicit_reducible] def singleton (c : Char) : String := "".push c end String @@ -219,7 +219,7 @@ Examples: * `'L'.toString = "L"` * `'"'.toString = "\""` -/ -@[inline, expose] protected def toString (c : Char) : String := +@[inline, expose, implicit_reducible] protected def toString (c : Char) : String := String.singleton c end Char diff --git a/src/Init/Data/String/Decode.lean b/src/Init/Data/String/Decode.lean index 6b780e2e42f6..364be3029292 100644 --- a/src/Init/Data/String/Decode.lean +++ b/src/Init/Data/String/Decode.lean @@ -255,7 +255,7 @@ public inductive FirstByte where | twoMore : FirstByte | threeMore : FirstByte -@[inline, expose] +@[inline, expose, implicit_reducible] public def parseFirstByte (b : UInt8) : FirstByte := if b &&& 0x80 == 0 then .done @@ -468,7 +468,7 @@ theorem helper₅ {w : UInt8} (h : parseFirstByte w = .done) : w < 128 := by rw [BitVec.toNat_append] simpa using Nat.mod_lt _ (by decide) -@[inline, expose] +@[inline, expose, implicit_reducible] public def assemble₁ (w : UInt8) (h : parseFirstByte w = .done) : Option Char := some ⟨w.toUInt32, ?done⟩ where finally @@ -1004,7 +1004,7 @@ Decodes and returns the `Char` whose UTF-8 encoding begins at `i` in `bytes`. Returns `none` if `i` is not the start of a valid UTF-8 encoding of a character. -/ -@[inline, expose] +@[inline, expose, implicit_reducible] public def ByteArray.utf8DecodeChar? (bytes : ByteArray) (i : Nat) : Option Char := if h₀ : i < bytes.size then match h : parseFirstByte bytes[i] with diff --git a/src/Init/Data/String/Defs.lean b/src/Init/Data/String/Defs.lean index b9d5fa5acbf7..e57cc964ffd0 100644 --- a/src/Init/Data/String/Defs.lean +++ b/src/Init/Data/String/Defs.lean @@ -90,7 +90,7 @@ Examples: * `"abc" ++ "def" = "abcdef"` * `"" ++ "" = ""` -/ -@[extern "lean_string_append", expose] +@[extern "lean_string_append", expose, implicit_reducible] def String.append (s : String) (t : @& String) : String where toByteArray := s.toByteArray ++ t.toByteArray isValidUTF8 := s.isValidUTF8.append t.isValidUTF8 @@ -422,7 +422,7 @@ instance : Inhabited Slice where /-- Returns a slice that contains the entire string. -/ -@[inline, expose] -- expose for the defeq `s.toSlice.str = s`. +@[inline, expose, instance_reducible] -- expose for the defeq `s.toSlice.str = s`. def toSlice (s : String) : Slice where str := s startInclusive := s.startPos @@ -471,7 +471,7 @@ theorem Pos.Raw.byteIdx_sub_slice {p : Pos.Raw} {s : Slice} : (p - s).byteIdx = p.byteIdx - s.utf8ByteSize := rfl /-- The end position of a slice, as a `Pos.Raw`. -/ -@[expose, inline] +@[expose, inline, instance_reducible] def Slice.rawEndPos (s : Slice) : Pos.Raw where byteIdx := s.utf8ByteSize diff --git a/src/Init/Data/String/Lemmas/Iter.lean b/src/Init/Data/String/Lemmas/Iter.lean index 62f4253a2ebd..12bb4a2bff89 100644 --- a/src/Init/Data/String/Lemmas/Iter.lean +++ b/src/Init/Data/String/Lemmas/Iter.lean @@ -43,7 +43,7 @@ public theorem intercalateString_eq {α β : Type} [Std.Iterator α Id β] [Std. match m with | [] => simp | x::xs => - simp only [reduceCtorEq, ↓reduceIte, List.cons_append, Option.some.injEq] + simp only [List.cons_append, Option.some.injEq, reduceCtorEq, ↓reduceIte] rw [← List.cons_append, String.intercalate_append_of_ne_nil (by simp) (by simp), String.intercalate_singleton] diff --git a/src/Init/Data/String/Lemmas/Iterate.lean b/src/Init/Data/String/Lemmas/Iterate.lean index 32bd888af7d5..8d79894fc75f 100644 --- a/src/Init/Data/String/Lemmas/Iterate.lean +++ b/src/Init/Data/String/Lemmas/Iterate.lean @@ -113,6 +113,8 @@ theorem Pos.Splits.mem_toList_left_iff {s : Slice} {pos : s.Pos} {t u : String} by simpa [← Pos.ofSliceTo_inj] using Std.ne_of_lt hlt, by rw [Slice.Pos.get_eq_get_ofSliceTo]; simpa using hget⟩ +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem Pos.Splits.mem_toList_right_iff {s : Slice} {pos : s.Pos} {t u : String} {c : Char} (hs : pos.Splits t u) : c ∈ u.toList ↔ ∃ pos', ∃ (_ : pos ≤ pos') (h : pos' ≠ s.endPos), pos'.get h = c := by @@ -274,6 +276,8 @@ theorem mem_toList_iff_exists_get {s : String} {c : Char} : c ∈ s.toList ↔ ∃ (p : s.Pos) (h : p ≠ s.endPos), p.get h = c := by simp [← Model.map_get_positionsFrom_startPos] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem Pos.Splits.mem_toList_left_iff {s : String} {pos : s.Pos} {t u : String} {c : Char} (hs : pos.Splits t u) : c ∈ t.toList ↔ ∃ pos', ∃ (h : pos' < pos), pos'.get (Pos.ne_endPos_of_lt h) = c := by @@ -288,6 +292,8 @@ theorem Pos.Splits.mem_toList_left_iff {s : String} {pos : s.Pos} {t u : String} fun h => Std.ne_of_lt hlt (by simpa using congrArg Pos.ofSliceTo h), by rw [Pos.get_eq_get_ofSliceTo]; simpa using hget⟩ +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem Pos.Splits.mem_toList_right_iff {s : String} {pos : s.Pos} {t u : String} {c : Char} (hs : pos.Splits t u) : c ∈ u.toList ↔ ∃ pos', ∃ (_ : pos ≤ pos') (h : pos' ≠ s.endPos), pos'.get h = c := by diff --git a/src/Init/Data/String/Lemmas/Pattern/Basic.lean b/src/Init/Data/String/Lemmas/Pattern/Basic.lean index 738b9eb2c945..00e8c358f93b 100644 --- a/src/Init/Data/String/Lemmas/Pattern/Basic.lean +++ b/src/Init/Data/String/Lemmas/Pattern/Basic.lean @@ -925,7 +925,7 @@ theorem LawfulToForwardSearcherModel.defaultImplementation {pat : ρ} [ForwardPa intro pos induction pos using WellFounded.induction Slice.Pos.wellFounded_gt with | h pos ih rw [Std.Iter.toList_eq_match_step, Std.Iter.step_eq] - simp only [Std.Iter.toIterM, ne_eq] + simp only [Std.Iter.toIterM_mk, Std.IterM.internalState_mk, ne_eq] by_cases h : pos = s.endPos · simpa [h] using IsValidSearchFrom.endPos · simp only [h, ↓reduceDIte] @@ -1036,7 +1036,7 @@ theorem LawfulToBackwardSearcherModel.defaultImplementation {pat : ρ} [Backward intro pos induction pos using WellFounded.induction Slice.Pos.wellFounded_lt with | h pos ih rw [Std.Iter.toList_eq_match_step, Std.Iter.step_eq] - simp only [Std.Iter.toIterM, ne_eq] + simp only [Std.Iter.toIterM_mk, Std.IterM.internalState_mk, ne_eq] by_cases h : pos = s.startPos · simpa [h] using IsValidRevSearchFrom.startPos · simp only [h, ↓reduceDIte] diff --git a/src/Init/Data/String/Lemmas/Pattern/Find/Char.lean b/src/Init/Data/String/Lemmas/Pattern/Find/Char.lean index fb55bb6f4fa6..0ba887264708 100644 --- a/src/Init/Data/String/Lemmas/Pattern/Find/Char.lean +++ b/src/Init/Data/String/Lemmas/Pattern/Find/Char.lean @@ -52,6 +52,8 @@ theorem Pos.find?_char_eq_some_iff {c : Char} {s : Slice} {pos pos' : s.Pos} : ∀ pos'', pos ≤ pos'' → (h' : pos'' < pos') → pos''.get (Pos.ne_endPos_of_lt h') ≠ c := by grind [Pattern.Model.posFind?_eq_some_iff, Pattern.Model.Char.matchesAt_iff] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem Pos.find?_char_eq_some_iff_splits {c : Char} {s : Slice} {pos : s.Pos} {t u : String} (hs : pos.Splits t u) {pos' : s.Pos} : pos.find? c = some pos' ↔ ∃ v w, pos'.Splits (t ++ v) (singleton c ++ w) ∧ c ∉ v.toList := by diff --git a/src/Init/Data/String/Lemmas/Pattern/Find/Pred.lean b/src/Init/Data/String/Lemmas/Pattern/Find/Pred.lean index 40c3009bec1a..d91e7f16f54a 100644 --- a/src/Init/Data/String/Lemmas/Pattern/Find/Pred.lean +++ b/src/Init/Data/String/Lemmas/Pattern/Find/Pred.lean @@ -77,6 +77,8 @@ theorem Pos.find?_bool_eq_some_iff {p : Char → Bool} {s : Slice} {pos pos' : s p (pos''.get (Pos.ne_endPos_of_lt h')) = false := by grind [Pattern.Model.posFind?_eq_some_iff, Pattern.Model.CharPred.matchesAt_iff] +-- TODO: We should be able to remove this flag after a stage0 update. +set_option backward.isDefEq.respectTransparency.types false in theorem Pos.find?_bool_eq_some_iff_splits {p : Char → Bool} {s : Slice} {pos : s.Pos} {t u : String} (hs : pos.Splits t u) {pos' : s.Pos} : pos.find? p = some pos' ↔ diff --git a/src/Init/Data/String/Lemmas/Pattern/String/ForwardSearcher.lean b/src/Init/Data/String/Lemmas/Pattern/String/ForwardSearcher.lean index 50d1d1d85210..7a985eb43faa 100644 --- a/src/Init/Data/String/Lemmas/Pattern/String/ForwardSearcher.lean +++ b/src/Init/Data/String/Lemmas/Pattern/String/ForwardSearcher.lean @@ -325,8 +325,8 @@ theorem isTable_buildTableGo {pat : Slice} {table : Array Nat} {ht₀ ht h} fun_induction buildTable.go with | case1 t ht₀ ht h hlt patByte dist ih => refine ih (ht'.push (by simp; omega) ?_) - simp only [getUTF8Byte_eq_getUTF8Byte_copy, String.getUTF8Byte, ht'.eq_prefixFunction, dist, - patByte] + simp only [getUTF8Byte_eq_getUTF8Byte_copy, String.getUTF8Byte_eq_getElem, + ht'.eq_prefixFunction, dist, patByte] rw [computeDistance_eq_prefixFunctionRecurrence _ _ rfl _ ht', prefixFunctionRecurrence_eq_prefixFunction] · exact prefixFunction_le_prefixFunction_sub_one_add_one ht₀ diff --git a/src/Init/Data/String/PosRaw.lean b/src/Init/Data/String/PosRaw.lean index 9f808632b956..fb516ecb8cad 100644 --- a/src/Init/Data/String/PosRaw.lean +++ b/src/Init/Data/String/PosRaw.lean @@ -108,6 +108,9 @@ At runtime, this function is implemented by efficient, constant-time code. def getUTF8Byte (s : @& String) (p : Pos.Raw) (h : p < s.rawEndPos) : UInt8 := s.toByteArray[p.byteIdx] +theorem getUTF8Byte_eq_getElem {s : String} {p : Pos.Raw} {h} : + s.getUTF8Byte p h = s.toByteArray[p.byteIdx] := (rfl) + @[deprecated getUTF8Byte (since := "2025-10-01"), extern "lean_string_get_byte_fast"] abbrev getUtf8Byte (s : String) (p : Pos.Raw) (h : p < s.rawEndPos) : UInt8 := s.getUTF8Byte p h diff --git a/src/Init/Data/UInt/Basic.lean b/src/Init/Data/UInt/Basic.lean index 15f465333366..439c0a04f33b 100644 --- a/src/Init/Data/UInt/Basic.lean +++ b/src/Init/Data/UInt/Basic.lean @@ -29,7 +29,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_add"] +@[extern "lean_uint8_add", implicit_reducible] protected def UInt8.add (a b : UInt8) : UInt8 := ⟨a.toBitVec + b.toBitVec⟩ /-- Subtracts one 8-bit unsigned integer from another, wrapping around on underflow. Usually accessed @@ -37,7 +37,7 @@ via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_sub"] +@[extern "lean_uint8_sub", implicit_reducible] protected def UInt8.sub (a b : UInt8) : UInt8 := ⟨a.toBitVec - b.toBitVec⟩ /-- Multiplies two 8-bit unsigned integers, wrapping around on overflow. Usually accessed via the `*` @@ -45,7 +45,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_mul"] +@[extern "lean_uint8_mul", implicit_reducible] protected def UInt8.mul (a b : UInt8) : UInt8 := ⟨a.toBitVec * b.toBitVec⟩ /-- Unsigned division for 8-bit unsigned integers, discarding the remainder. Usually accessed @@ -55,7 +55,7 @@ This operation is sometimes called “floor division.” Division by zero is def This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_div"] +@[extern "lean_uint8_div", implicit_reducible] protected def UInt8.div (a b : UInt8) : UInt8 := ⟨BitVec.udiv a.toBitVec b.toBitVec⟩ /-- The power operation, raising an 8-bit unsigned integer to a natural number power, @@ -81,7 +81,7 @@ Examples: * `UInt8.mod 4 2 = 0` * `UInt8.mod 4 0 = 4` -/ -@[extern "lean_uint8_mod"] +@[extern "lean_uint8_mod", implicit_reducible] protected def UInt8.mod (a b : UInt8) : UInt8 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩ -- Note: This is deprecated, but still used in the `HMod` instance below. @@ -95,7 +95,7 @@ Each bit of the resulting integer is set if the corresponding bits of both input This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_land"] +@[extern "lean_uint8_land", implicit_reducible] protected def UInt8.land (a b : UInt8) : UInt8 := ⟨a.toBitVec &&& b.toBitVec⟩ /-- Bitwise or for 8-bit unsigned integers. Usually accessed via the `|||` operator. @@ -200,7 +200,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_add"] +@[extern "lean_uint16_add", implicit_reducible] protected def UInt16.add (a b : UInt16) : UInt16 := ⟨a.toBitVec + b.toBitVec⟩ /-- Subtracts one 16-bit unsigned integer from another, wrapping around on underflow. Usually accessed @@ -208,7 +208,7 @@ via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_sub"] +@[extern "lean_uint16_sub", implicit_reducible] protected def UInt16.sub (a b : UInt16) : UInt16 := ⟨a.toBitVec - b.toBitVec⟩ /-- Multiplies two 16-bit unsigned integers, wrapping around on overflow. Usually accessed via the `*` @@ -216,7 +216,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_mul"] +@[extern "lean_uint16_mul", implicit_reducible] protected def UInt16.mul (a b : UInt16) : UInt16 := ⟨a.toBitVec * b.toBitVec⟩ /-- Unsigned division for 16-bit unsigned integers, discarding the remainder. Usually accessed @@ -226,7 +226,7 @@ This operation is sometimes called “floor division.” Division by zero is def This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_div"] +@[extern "lean_uint16_div", implicit_reducible] protected def UInt16.div (a b : UInt16) : UInt16 := ⟨BitVec.udiv a.toBitVec b.toBitVec⟩ /-- The power operation, raising a 16-bit unsigned integer to a natural number power, @@ -252,7 +252,7 @@ Examples: * `UInt16.mod 4 2 = 0` * `UInt16.mod 4 0 = 4` -/ -@[extern "lean_uint16_mod"] +@[extern "lean_uint16_mod", implicit_reducible] protected def UInt16.mod (a b : UInt16) : UInt16 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩ -- Note: This is deprecated, but still used in the `HMod` instance below. @@ -410,7 +410,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_mul"] +@[extern "lean_uint32_mul", implicit_reducible] protected def UInt32.mul (a b : UInt32) : UInt32 := ⟨a.toBitVec * b.toBitVec⟩ /-- Unsigned division for 32-bit unsigned integers, discarding the remainder. Usually accessed @@ -420,7 +420,7 @@ This operation is sometimes called “floor division.” Division by zero is def This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_div"] +@[extern "lean_uint32_div", implicit_reducible] protected def UInt32.div (a b : UInt32) : UInt32 := ⟨BitVec.udiv a.toBitVec b.toBitVec⟩ /-- The power operation, raising a 32-bit unsigned integer to a natural number power, @@ -446,7 +446,7 @@ Examples: * `UInt32.mod 4 2 = 0` * `UInt32.mod 4 0 = 4` -/ -@[extern "lean_uint32_mod"] +@[extern "lean_uint32_mod", implicit_reducible] protected def UInt32.mod (a b : UInt32) : UInt32 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩ -- Note: This is deprecated, but still used in the `HMod` instance below. @@ -565,7 +565,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_add"] +@[extern "lean_uint64_add", implicit_reducible] protected def UInt64.add (a b : UInt64) : UInt64 := ⟨a.toBitVec + b.toBitVec⟩ /-- Subtracts one 64-bit unsigned integer from another, wrapping around on underflow. Usually accessed @@ -573,7 +573,7 @@ via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_sub"] +@[extern "lean_uint64_sub", implicit_reducible] protected def UInt64.sub (a b : UInt64) : UInt64 := ⟨a.toBitVec - b.toBitVec⟩ /-- Multiplies two 64-bit unsigned integers, wrapping around on overflow. Usually accessed via the `*` @@ -581,7 +581,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_mul"] +@[extern "lean_uint64_mul", implicit_reducible] protected def UInt64.mul (a b : UInt64) : UInt64 := ⟨a.toBitVec * b.toBitVec⟩ /-- Unsigned division for 64-bit unsigned integers, discarding the remainder. Usually accessed @@ -591,7 +591,7 @@ This operation is sometimes called “floor division.” Division by zero is def This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_div"] +@[extern "lean_uint64_div", implicit_reducible] protected def UInt64.div (a b : UInt64) : UInt64 := ⟨BitVec.udiv a.toBitVec b.toBitVec⟩ /-- The power operation, raising a 64-bit unsigned integer to a natural number power, @@ -617,7 +617,7 @@ Examples: * `UInt64.mod 4 2 = 0` * `UInt64.mod 4 0 = 4` -/ -@[extern "lean_uint64_mod"] +@[extern "lean_uint64_mod", implicit_reducible] protected def UInt64.mod (a b : UInt64) : UInt64 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩ -- Note: This is deprecated, but still used in the `HMod` instance below. diff --git a/src/Init/Data/UInt/BasicAux.lean b/src/Init/Data/UInt/BasicAux.lean index a6589e5a65e6..854c93790b4b 100644 --- a/src/Init/Data/UInt/BasicAux.lean +++ b/src/Init/Data/UInt/BasicAux.lean @@ -63,7 +63,7 @@ Converts an 8-bit unsigned integer to an arbitrary-precision natural number. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_to_nat", tagged_return] +@[extern "lean_uint8_to_nat", tagged_return, implicit_reducible] def UInt8.toNat (n : UInt8) : Nat := n.toBitVec.toNat instance UInt8.instOfNat : OfNat UInt8 n := ⟨UInt8.ofNat n⟩ @@ -82,7 +82,7 @@ Examples: * `UInt16.ofNat 32770 = 32770` * `UInt16.ofNat 65537 = 1` -/ -@[extern "lean_uint16_of_nat"] +@[extern "lean_uint16_of_nat", implicit_reducible] def UInt16.ofNat (n : @& Nat) : UInt16 := ⟨BitVec.ofNat 16 n⟩ /-- Converts a natural number to a 16-bit unsigned integer, returning the largest representable value if @@ -118,7 +118,7 @@ Converts a 16-bit unsigned integer to an arbitrary-precision natural number. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_to_nat", tagged_return] +@[extern "lean_uint16_to_nat", tagged_return, implicit_reducible] def UInt16.toNat (n : UInt16) : Nat := n.toBitVec.toNat /-- Converts 16-bit unsigned integers to 8-bit unsigned integers. Wraps around on overflow. @@ -150,7 +150,7 @@ Examples: * `UInt32.ofNat 65539 = 65539` * `UInt32.ofNat 4_294_967_299 = 3` -/ -@[extern "lean_uint32_of_nat"] +@[extern "lean_uint32_of_nat", implicit_reducible] def UInt32.ofNat (n : @& Nat) : UInt32 := ⟨BitVec.ofNat 32 n⟩ /-- @@ -199,7 +199,7 @@ Converts 8-bit unsigned integers to 32-bit unsigned integers. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_to_uint32"] +@[extern "lean_uint8_to_uint32", implicit_reducible] def UInt8.toUInt32 (a : UInt8) : UInt32 := ⟨⟨a.toNat, Nat.lt_trans a.toBitVec.isLt (by decide)⟩⟩ /-- Converts 16-bit unsigned integers to 32-bit unsigned integers. @@ -228,7 +228,7 @@ operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_add"] +@[extern "lean_uint32_add", implicit_reducible] protected def UInt32.add (a b : UInt32) : UInt32 := ⟨a.toBitVec + b.toBitVec⟩ /-- @@ -237,7 +237,7 @@ via the `-` operator. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_sub"] +@[extern "lean_uint32_sub", implicit_reducible] protected def UInt32.sub (a b : UInt32) : UInt32 := ⟨a.toBitVec - b.toBitVec⟩ instance : Add UInt32 := ⟨UInt32.add⟩ @@ -257,7 +257,7 @@ Examples: * `UInt64.ofNat 4_294_967_299 = 4_294_967_299` * `UInt64.ofNat 18_446_744_073_709_551_620 = 4` -/ -@[extern "lean_uint64_of_nat"] +@[extern "lean_uint64_of_nat", implicit_reducible] def UInt64.ofNat (n : @& Nat) : UInt64 := ⟨BitVec.ofNat 64 n⟩ /-- Converts a natural number to a 64-bit unsigned integer, returning the largest representable value if @@ -291,7 +291,7 @@ Converts a 64-bit unsigned integer to an arbitrary-precision natural number. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_to_nat"] +@[extern "lean_uint64_to_nat", implicit_reducible] def UInt64.toNat (n : UInt64) : Nat := n.toBitVec.toNat /-- Converts 64-bit unsigned integers to 8-bit unsigned integers. Wraps around on overflow. diff --git a/src/Init/Data/Vector/Attach.lean b/src/Init/Data/Vector/Attach.lean index 579b1b408d93..add6f7376476 100644 --- a/src/Init/Data/Vector/Attach.lean +++ b/src/Init/Data/Vector/Attach.lean @@ -139,11 +139,18 @@ theorem attachWith_congr {xs ys : Vector α n} (w : xs = ys) {P : α → Prop} { subst w simp +@[congr] +theorem mk_congr {xs ys : Array α} (h : xs = ys) {h' : xs.size = n} : + mk xs h' = mk ys (h ▸ h') := by + subst h + simp + @[simp] theorem attach_push {a : α} {xs : Vector α n} : (xs.push a).attach = (xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_push_of_mem a h⟩)).push ⟨a, by simp⟩ := by rcases xs with ⟨xs, rfl⟩ - simp [Array.map_attach_eq_pmap] + apply Vector.ext + simp [Array.attachWith_eq_map_attach, Array.getElem_push] @[simp] theorem attachWith_push {a : α} {xs : Vector α n} {P : α → Prop} {H : ∀ x ∈ xs.push a, P x} : (xs.push a).attachWith P H = @@ -359,7 +366,10 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs : Vector ys.attach.map (fun ⟨y, h⟩ => (⟨y, mem_append_right xs h⟩ : { y // y ∈ xs ++ ys })) := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, rfl⟩ - simp [Array.map_attach_eq_pmap]; rfl + apply Vector.ext + intro i hi + rw [Vector.getElem_append] + simp [Array.attachWith_eq_map_attach, Array.getElem_append] @[simp] theorem attachWith_append {P : α → Prop} {xs : Vector α n} {ys : Vector α m} {H : ∀ (a : α), a ∈ xs ++ ys → P a} : diff --git a/src/Init/Data/Vector/Basic.lean b/src/Init/Data/Vector/Basic.lean index ab5914c8b429..15a82fd38f6e 100644 --- a/src/Init/Data/Vector/Basic.lean +++ b/src/Init/Data/Vector/Basic.lean @@ -64,7 +64,7 @@ recommended_spelling "empty" for "#v[]" in [Vector.mk, «term#v[_,]»] recommended_spelling "singleton" for "#v[x]" in [Vector.mk, «term#v[_,]»] /-- Convert a vector to a list. -/ -@[expose] +@[expose, instance_reducible] def toList (xs : Vector α n) : List α := xs.toArray.toList /-- Custom eliminator for `Vector α n` through `Array α` -/ @@ -238,7 +238,7 @@ We immediately simplify this to the `extract` operation, so there is no verifica simp [shrink, take] /-- Maps elements of a vector using the function `f`. -/ -@[inline, expose] def map (f : α → β) (xs : Vector α n) : Vector β n := +@[inline, expose, instance_reducible] def map (f : α → β) (xs : Vector α n) : Vector β n := ⟨xs.toArray.map f, by simp⟩ /-- Maps elements of a vector using the function `f`, which also receives the index of the element. -/ diff --git a/src/Init/Data/Vector/DecidableEq.lean b/src/Init/Data/Vector/DecidableEq.lean index 8e78e9f7e52f..7917103eb09c 100644 --- a/src/Init/Data/Vector/DecidableEq.lean +++ b/src/Init/Data/Vector/DecidableEq.lean @@ -26,7 +26,7 @@ theorem isEqv_eq_decide (xs ys : Vector α n) (r) : Vector.isEqv xs ys r = decide (∀ (i : Nat) (h' : i < n), r xs[i] ys[i]) := by rcases xs with ⟨xs, rfl⟩ rcases ys with ⟨ys, h⟩ - simp [Array.isEqv_eq_decide, h] + simp -implicitDefEqProofs [Array.isEqv_eq_decide, h] @[simp] theorem isEqv_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray.isEqv ys.toArray r) = (xs.isEqv ys r) := by simp [isEqv_eq_decide, Array.isEqv_eq_decide] diff --git a/src/Init/Data/Vector/Monadic.lean b/src/Init/Data/Vector/Monadic.lean index 4f1e5f7e122d..3b8233fbd0d0 100644 --- a/src/Init/Data/Vector/Monadic.lean +++ b/src/Init/Data/Vector/Monadic.lean @@ -158,7 +158,7 @@ theorem idRun_forIn'_yield_eq_foldl {xs : Vector α n} (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) : forIn' (xs.map g) init f = forIn' xs init fun a h y => f (g a) (mem_map_of_mem h) y := by rcases xs with ⟨xs, rfl⟩ - simp + simp [map_mk, forIn'_mk, Array.forIn'_map] /-- We can express a for loop over a vector as a fold, diff --git a/src/Init/GetElem.lean b/src/Init/GetElem.lean index 7d6300b1d5fe..8dfa79e532c0 100644 --- a/src/Init/GetElem.lean +++ b/src/Init/GetElem.lean @@ -322,6 +322,7 @@ theorem getElem_cons_drop_succ_eq_drop {as : List α} {i : Nat} (h : i < as.leng /-- Internal implementation of `as[i]?`. Do not use directly. -/ -- We still keep it public for reduction purposes +@[instance_reducible] def get?Internal : (as : List α) → (i : Nat) → Option α | a::_, 0 => some a | _::as, n+1 => get?Internal as n @@ -408,7 +409,7 @@ instance : LawfulGetElem (Array α) Nat α fun xs i => i < xs.size where split <;> rfl @[simp] theorem getInternal_eq_getElem (a : Array α) (i : Nat) (h) : - a.getInternal i h = a[i] := rfl + a.getInternal i h = a[i] := id rfl @[simp] theorem get!Internal_eq_getElem! [Inhabited α] (a : Array α) (i : Nat) : a.get!Internal i = a[i]! := by diff --git a/src/Init/Grind/Module/Envelope.lean b/src/Init/Grind/Module/Envelope.lean index d0b4345d9c89..62bb84c4f645 100644 --- a/src/Init/Grind/Module/Envelope.lean +++ b/src/Init/Grind/Module/Envelope.lean @@ -32,7 +32,7 @@ local instance : Std.Commutative (· + · : α → α → α) where @[local simp] def r : (α × α) → (α × α) → Prop | (a, b), (c, d) => ∃ k, a + d + k = b + c + k -def Q := Quot (r α) +@[expose, instance_reducible] def Q := Quot (r α) variable {α} diff --git a/src/Init/Grind/Ring/Envelope.lean b/src/Init/Grind/Ring/Envelope.lean index d6a42064e264..4c44c1436d32 100644 --- a/src/Init/Grind/Ring/Envelope.lean +++ b/src/Init/Grind/Ring/Envelope.lean @@ -35,6 +35,7 @@ local instance : Std.Associative (· * · : α → α → α) where @[local simp] def r : (α × α) → (α × α) → Prop | (a, b), (c, d) => ∃ k, a + d + k = b + c + k +@[instance_reducible] def Q := Quot (r α) variable {α} diff --git a/src/Init/Internal/Order/Basic.lean b/src/Init/Internal/Order/Basic.lean index 10e5888e1e43..fda656c20bdd 100644 --- a/src/Init/Internal/Order/Basic.lean +++ b/src/Init/Internal/Order/Basic.lean @@ -767,6 +767,23 @@ This is intended to be used in the construction of `partial_fixpoint`, and not m -/ @[expose] def FlatOrder {α : Sort u} (b : α) := α +def FlatOrder.mk {α : Sort u} (b : α) (x : α) : FlatOrder b := x + +def FlatOrder.inner {α : Sort u} {b : α} (x : FlatOrder b) : α := x + +theorem FlatOrder.mk_inner {α : Sort u} {b : α} {x : FlatOrder b} : + FlatOrder.mk b x.inner = x := + (rfl) + +theorem FlatOrder.inner_mk {α : Sort u} {b : α} {x : α} : + (FlatOrder.mk b x).inner = x := + (rfl) + +@[simp] +theorem FlatOrder.mk_inj {α : Sort u} {b : α} {x y : α} : + FlatOrder.mk b x = FlatOrder.mk b y ↔ x = y := + Iff.rfl + variable {b : α} /-- @@ -793,7 +810,7 @@ private theorem Classical.some_spec₂ {α : Sort _} {p : α → Prop} {h : ∃ noncomputable def flat_csup (c : FlatOrder b → Prop) : FlatOrder b := by by_cases h : ∃ (x : FlatOrder b), c x ∧ x ≠ b · exact Classical.choose h - · exact b + · exact .mk b b theorem flat_csup_is_sup (c : FlatOrder b → Prop) (hc : chain c) : is_sup c (flat_csup c) := by @@ -838,7 +855,7 @@ theorem flat_csup_eq (c : FlatOrder b → Prop) (hchain : chain c) : · apply flat_csup_is_sup _ hchain · apply CCPO.csup_spec -theorem admissible_flatOrder (P : FlatOrder b → Prop) (hnot : P b) : admissible P := by +theorem admissible_flatOrder (P : FlatOrder b → Prop) (hnot : P (.mk b b)) : admissible P := by intro c hchain h by_cases h' : ∃ (x : FlatOrder b), c x ∧ x ≠ b · simp [← flat_csup_eq, flat_csup, h'] @@ -889,6 +906,7 @@ instance : MonoBind Option where theorem Option.admissible_eq_some (P : Prop) (y : α) : admissible (fun (x : Option α) => x = some y → P) := by + change admissible fun x : FlatOrder none => x = .mk _ (some y) → P apply admissible_flatOrder; simp instance [inst : ∀ α, PartialOrder (m α)] : PartialOrder (ExceptT ε m α) := inst _ diff --git a/src/Init/Prelude.lean b/src/Init/Prelude.lean index f89914fe4e22..e68d82213cdc 100644 --- a/src/Init/Prelude.lean +++ b/src/Init/Prelude.lean @@ -128,7 +128,7 @@ difference for typeclass inference, since `T` and `T'` may have different typeclass instances on them. `show T' from e` is sugar for an `@id T' e` expression. -/ -@[inline] def id {α : Sort u} (a : α) : α := a +@[inline, instance_reducible] def id {α : Sort u} (a : α) : α := a /-- Function composition, usually written with the infix operator `∘`. A new function is created from @@ -138,7 +138,7 @@ Examples: * `Function.comp List.reverse (List.drop 2) [3, 2, 4, 1] = [1, 4]` * `(List.reverse ∘ List.drop 2) [3, 2, 4, 1] = [1, 4]` -/ -@[inline] def Function.comp {α : Sort u} {β : Sort v} {δ : Sort w} (f : β → δ) (g : α → β) : α → δ := +@[inline, instance_reducible] def Function.comp {α : Sort u} {β : Sort v} {δ : Sort w} (f : β → δ) (g : α → β) : α → δ := fun x => f (g x) /-- @@ -314,7 +314,7 @@ so if your goal is `¬p` you can use `intro h` to turn the goal into and `(hn h).elim` will prove anything. For more information: [Propositional Logic](https://lean-lang.org/theorem_proving_in_lean4/propositions_and_proofs.html#propositional-logic) -/ -def Not (a : Prop) : Prop := a → False +@[implicit_reducible] def Not (a : Prop) : Prop := a → False /-- `False.elim : False → C` says that from `False`, any desired proposition @@ -407,7 +407,7 @@ definitionally sometimes there isn't anything better you can do. For more information: [Equality](https://lean-lang.org/theorem_proving_in_lean4/quantifiers_and_equality.html#equality) -/ -@[macro_inline] def cast {α β : Sort u} (h : Eq α β) (a : α) : β := +@[macro_inline, instance_reducible] def cast {α β : Sort u} (h : Eq α β) (a : α) : β := h.rec a /-- @@ -980,7 +980,7 @@ Converts a decidable proposition into a `Bool`. If `p : Prop` is decidable, then `decide p : Bool` is the Boolean value that is `true` if `p` is true and `false` if `p` is false. -/ -@[inline_if_reduce, nospecialize] def Decidable.decide (p : Prop) [h : Decidable p] : Bool := +@[inline_if_reduce, nospecialize, implicit_reducible] def Decidable.decide (p : Prop) [h : Decidable p] : Bool := h.casesOn (fun _ => false) (fun _ => true) export Decidable (isTrue isFalse decide) @@ -1030,11 +1030,25 @@ theorem of_decide_eq_true [inst : Decidable p] : Eq (decide p) true → p := fun | isTrue h₁ => h₁ | isFalse h₁ => absurd h (ne_true_of_eq_false (decide_eq_false h₁)) +/-- +Variant of `of_decide_eq_true` that takes `Decidable` as an implicit argument, intended for +forward reasoning. +-/ +theorem of_decide_eq_true_forward {inst : Decidable p} : Eq (decide p) true → p := + of_decide_eq_true + theorem of_decide_eq_false [inst : Decidable p] : Eq (decide p) false → Not p := fun h => match (generalizing := false) inst with | isTrue h₁ => absurd h (ne_false_of_eq_true (decide_eq_true h₁)) | isFalse h₁ => h₁ +/-- +Variant of `of_decide_eq_false` that takes `Decidable` as an implicit argument, intended for +forward reasoning. +-/ +theorem of_decide_eq_false_forward {inst : Decidable p} : Eq (decide p) false → Not p := + of_decide_eq_false + theorem of_decide_eq_self_eq_true [inst : DecidableEq α] (a : α) : Eq (decide (Eq a a)) true := match (generalizing := false) inst a a with | isTrue _ => rfl @@ -1046,7 +1060,7 @@ Decides whether two Booleans are equal. This function should normally be called via the `DecidableEq Bool` instance that it exists to support. -/ -@[inline] def Bool.decEq (a b : Bool) : Decidable (Eq a b) := +@[inline, instance_reducible] def Bool.decEq (a b : Bool) : Decidable (Eq a b) := match a, b with | false, false => isTrue rfl | false, true => isFalse (fun h => Bool.noConfusion h) @@ -1091,7 +1105,8 @@ to avoid the bounds check inside the if branch. (Of course in this case we have lifted the check into an explicit `if`, but we could also use this proof multiple times or derive `i < arr.size` from some other proposition that we are checking in the `if`.) -/ -@[macro_inline] def dite {α : Sort u} (c : Prop) [h : Decidable c] (t : c → α) (e : Not c → α) : α := +@[macro_inline, instance_reducible] +def dite {α : Sort u} (c : Prop) [h : Decidable c] (t : c → α) (e : Not c → α) : α := h.casesOn e t /-! # if-then-else -/ @@ -1116,7 +1131,8 @@ the definition of the function uses `fun _ => t` and `fun _ => e` so this recove the expected "lazy" behavior of `if`: the `t` and `e` arguments delay evaluation until `c` is known. -/ -@[macro_inline] def ite {α : Sort u} (c : Prop) [h : Decidable c] (t e : α) : α := +@[macro_inline, instance_reducible] +def ite {α : Sort u} (c : Prop) [h : Decidable c] (t e : α) : α := h.casesOn (fun _ => e) (fun _ => t) @[macro_inline] instance {p q} [dp : Decidable p] [dq : Decidable q] : Decidable (And p q) := @@ -1157,7 +1173,7 @@ Just like `ite`, `cond` is declared `@[macro_inline]`, which causes applications unfolded. As a result, `x` and `y` are not evaluated at runtime until one of them is selected, and only the selected branch is evaluated. -/ -@[macro_inline] def cond {α : Sort u} (c : Bool) (x y : α) : α := +@[macro_inline, instance_reducible] def cond {α : Sort u} (c : Bool) (x y : α) : α := match c with | true => x | false => y @@ -1192,7 +1208,7 @@ operator. The Boolean `or` is a `@[macro_inline]` function in order to give it short-circuiting evaluation: if `x` is `true` then `y` is not evaluated at runtime. -/ -@[macro_inline] def Bool.or (x y : Bool) : Bool := +@[macro_inline, implicit_reducible] def Bool.or (x y : Bool) : Bool := match x with | true => true | false => y @@ -1206,7 +1222,7 @@ operator. The Boolean `and` is a `@[macro_inline]` function in order to give it short-circuiting evaluation: if `x` is `false` then `y` is not evaluated at runtime. -/ -@[macro_inline] def Bool.and (x y : Bool) : Bool := +@[macro_inline, implicit_reducible] def Bool.and (x y : Bool) : Bool := match x with | false => false | true => y @@ -1217,7 +1233,7 @@ Boolean negation, also known as Boolean complement. `not x` can be written `!x`. This is a function that maps the value `true` to `false` and the value `false` to `true`. The propositional connective is `Not : Prop → Prop`. -/ -@[inline] def Bool.not : Bool → Bool +@[inline, implicit_reducible] def Bool.not : Bool → Bool | true => false | false => true @@ -1895,7 +1911,7 @@ Strict inequality of natural numbers, usually accessed via the `<` operator. It is defined as `n < m = n + 1 ≤ m`. -/ -protected def Nat.lt (n m : Nat) : Prop := +@[instance_reducible] protected def Nat.lt (n m : Nat) : Prop := Nat.le (succ n) m instance instLTNat : LT Nat where @@ -1954,7 +1970,7 @@ The predecessor of a natural number is one less than it. The predecessor of `0` This definition is overridden in the compiler with an efficient implementation. This definition is the logical model. -/ -@[extern "lean_nat_pred"] +@[extern "lean_nat_pred", instance_reducible] def Nat.pred : (@& Nat) → Nat | 0 => 0 | succ a => a @@ -2346,7 +2362,7 @@ Returns `a` modulo `n` as a `Fin n`. This function exists for bootstrapping purposes. Use `Fin.ofNat` instead. -/ -protected def Fin.Internal.ofNat (n : Nat) (hn : LT.lt 0 n) (a : Nat) : Fin n := +@[instance_reducible] protected def Fin.Internal.ofNat (n : Nat) (hn : LT.lt 0 n) (a : Nat) : Fin n := ⟨HMod.hMod a n, Nat.mod_lt _ hn⟩ /-- @@ -2371,6 +2387,7 @@ This should be used via the instance `DecidableEq (BitVec w)`. -- We manually derive the `DecidableEq` instances for `BitVec` because -- we want to have builtin support for bit-vector literals, and we -- need a name for this function to implement `canUnfoldAtMatcher` at `WHNF.lean`. +@[implicit_reducible] def BitVec.decEq (x y : BitVec w) : Decidable (Eq x y) := match x, y with | ⟨n⟩, ⟨m⟩ => @@ -2381,14 +2398,14 @@ def BitVec.decEq (x y : BitVec w) : Decidable (Eq x y) := instance : DecidableEq (BitVec w) := BitVec.decEq /-- The `BitVec` with value `i`, given a proof that `i < 2^w`. -/ -@[match_pattern] +@[match_pattern, implicit_reducible] protected def BitVec.ofNatLT {w : Nat} (i : Nat) (p : LT.lt i (hPow 2 w)) : BitVec w where toFin := ⟨i, p⟩ /-- The bitvector with value `i mod 2^n`. -/ -@[match_pattern] +@[match_pattern, implicit_reducible] protected def BitVec.ofNat (n : Nat) (i : Nat) : BitVec n where toFin := Fin.Internal.ofNat (HPow.hPow 2 n) (Nat.pow_pos (Nat.zero_lt_succ _)) i @@ -2397,6 +2414,7 @@ Return the underlying `Nat` that represents a bitvector. This is O(1) because `BitVec` is a (zero-cost) wrapper around a `Nat`. -/ +@[instance_reducible] protected def BitVec.toNat (x : BitVec w) : Nat := x.toFin.val instance : LT (BitVec w) where lt := (LT.lt ·.toNat ·.toNat) @@ -2435,7 +2453,7 @@ enough to be representable without overflow; it must be smaller than `2^8`. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint8_of_nat"] +@[extern "lean_uint8_of_nat", implicit_reducible] def UInt8.ofNatLT (n : @& Nat) (h : LT.lt n UInt8.size) : UInt8 where toBitVec := BitVec.ofNatLT n h @@ -2451,7 +2469,7 @@ Examples: * `UInt8.ofNat 259 = 3` * `UInt8.ofNat 32770 = 2` -/ -@[extern "lean_uint8_of_nat"] +@[extern "lean_uint8_of_nat", implicit_reducible] def UInt8.ofNat (n : @& Nat) : UInt8 := ⟨BitVec.ofNat 8 n⟩ set_option bootstrap.genMatcherCode false in @@ -2466,7 +2484,7 @@ Examples: * `(if (6 : UInt8) = 7 then "yes" else "no") = "no"` * `show (7 : UInt8) = 7 by decide` -/ -@[extern "lean_uint8_dec_eq"] +@[extern "lean_uint8_dec_eq", implicit_reducible] def UInt8.decEq (a b : UInt8) : Decidable (Eq a b) := match a, b with | ⟨n⟩, ⟨m⟩ => @@ -2553,7 +2571,7 @@ enough to be representable without overflow; it must be smaller than `2^16`. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint16_of_nat"] +@[extern "lean_uint16_of_nat", implicit_reducible] def UInt16.ofNatLT (n : @& Nat) (h : LT.lt n UInt16.size) : UInt16 where toBitVec := BitVec.ofNatLT n h @@ -2570,7 +2588,7 @@ Examples: * `(if (6 : UInt16) = 7 then "yes" else "no") = "no"` * `show (7 : UInt16) = 7 by decide` -/ -@[extern "lean_uint16_dec_eq"] +@[extern "lean_uint16_dec_eq", implicit_reducible] def UInt16.decEq (a b : UInt16) : Decidable (Eq a b) := match a, b with | ⟨n⟩, ⟨m⟩ => @@ -2611,7 +2629,7 @@ enough to be representable without overflow; it must be smaller than `2^32`. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_of_nat"] +@[extern "lean_uint32_of_nat", implicit_reducible] def UInt32.ofNatLT (n : @& Nat) (h : LT.lt n UInt32.size) : UInt32 where toBitVec := BitVec.ofNatLT n h @@ -2620,7 +2638,7 @@ Converts a 32-bit unsigned integer to an arbitrary-precision natural number. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint32_to_nat"] +@[extern "lean_uint32_to_nat", implicit_reducible] def UInt32.toNat (n : UInt32) : Nat := n.toBitVec.toNat set_option bootstrap.genMatcherCode false in @@ -2635,7 +2653,7 @@ Examples: * `(if (6 : UInt32) = 7 then "yes" else "no") = "no"` * `show (7 : UInt32) = 7 by decide` -/ -@[extern "lean_uint32_dec_eq"] +@[extern "lean_uint32_dec_eq", implicit_reducible] def UInt32.decEq (a b : UInt32) : Decidable (Eq a b) := match a, b with | ⟨n⟩, ⟨m⟩ => @@ -2716,7 +2734,7 @@ enough to be representable without overflow; it must be smaller than `2^64`. This function is overridden at runtime with an efficient implementation. -/ -@[extern "lean_uint64_of_nat"] +@[extern "lean_uint64_of_nat", implicit_reducible] def UInt64.ofNatLT (n : @& Nat) (h : LT.lt n UInt64.size) : UInt64 where toBitVec := BitVec.ofNatLT n h @@ -2733,7 +2751,7 @@ Examples: * `(if (6 : UInt64) = 7 then "yes" else "no") = "no"` * `show (7 : UInt64) = 7 by decide` -/ -@[extern "lean_uint64_dec_eq"] +@[extern "lean_uint64_dec_eq", implicit_reducible] def UInt64.decEq (a b : UInt64) : Decidable (Eq a b) := match a, b with | ⟨n⟩, ⟨m⟩ => @@ -2850,7 +2868,7 @@ private theorem isValidChar_UInt32 {n : Nat} (h : n.isValidChar) : LT.lt n UInt3 Pack a `Nat` encoding a valid codepoint into a `Char`. This function is overridden with a native implementation. -/ -@[extern "lean_uint32_of_nat"] +@[extern "lean_uint32_of_nat", implicit_reducible] def Char.ofNatAux (n : @& Nat) (h : n.isValidChar) : Char where val := ⟨BitVec.ofNatLT n -- We would conventionally use `by exact` here to enter a private context, but `exact` does not @@ -2862,7 +2880,7 @@ def Char.ofNatAux (n : @& Nat) (h : n.isValidChar) : Char where Converts a `Nat` into a `Char`. If the `Nat` does not encode a valid Unicode scalar value, `'\0'` is returned instead. -/ -@[noinline, match_pattern] +@[noinline, match_pattern, implicit_reducible] def Char.ofNat (n : Nat) : Char := dite (n.isValidChar) (fun h => Char.ofNatAux n h) @@ -2887,6 +2905,7 @@ instance : DecidableEq Char := | isFalse h => isFalse (Char.ne_of_val_ne h) /-- Returns the number of bytes required to encode this `Char` in UTF-8. -/ +@[implicit_reducible] def Char.utf8Size (c : Char) : Nat := let v := c.val ite (LE.le v (UInt32.ofNatLT 0x7F (of_decide_eq_true rfl))) 1 @@ -2923,7 +2942,7 @@ Examples: * `(some "hello").getD "goodbye" = "hello"` * `none.getD "goodbye" = "goodbye"` -/ -@[macro_inline] def Option.getD (opt : Option α) (dflt : α) : α := +@[macro_inline, instance_reducible] def Option.getD (opt : Option α) (dflt : α) : α := match opt with | some x => x | none => dflt @@ -2938,7 +2957,7 @@ Examples: * `(none : Option Nat).map (· + 1) = none` * `(some 3).map (· + 1) = some 4` -/ -@[inline] protected def Option.map (f : α → β) : Option α → Option β +@[inline, instance_reducible] protected def Option.map (f : α → β) : Option α → Option β | some x => some (f x) | none => none @@ -3055,6 +3074,7 @@ Examples: * `["spring", "summer", "fall", "winter"].get (2 : Fin 4) = "fall"` * `["spring", "summer", "fall", "winter"].get (0 : Fin 4) = "spring"` -/ +@[instance_reducible] def List.get {α : Type u} : (as : List α) → Fin as.length → α | cons a _, ⟨0, _⟩ => a | cons _ as, ⟨Nat.succ i, h⟩ => get as ⟨i, Nat.le_of_succ_le_succ h⟩ @@ -3096,6 +3116,7 @@ Examples: * `List.concat [1, 2, 3] 4 = [1, 2, 3, 4]` * `List.concat [] () = [()]` -/ +@[implicit_reducible] def List.concat {α : Type u} : List α → α → List α | nil, b => cons b nil | cons a as, b => cons a (concat as b) @@ -3110,6 +3131,7 @@ Examples: * `[] ++ [4, 5] = [4, 5]`. * `[1, 2, 3] ++ [] = [1, 2, 3]`. -/ +@[implicit_reducible] protected def List.append : (xs ys : List α) → List α | nil, bs => bs | cons a as, bs => cons a (List.append as bs) @@ -3123,6 +3145,7 @@ Examples: * `[["a"], ["b", "c"]].flatten = ["a", "b", "c"]` * `[["a"], [], ["b", "c"], ["d", "e", "f"]].flatten = ["a", "b", "c", "d", "e", "f"]` -/ +@[implicit_reducible] noncomputable def List.flatten : List (List α) → List α | nil => nil | cons l L => List.append l (flatten L) @@ -3138,7 +3161,7 @@ Examples: * `["one", "two", "three"].map (·.length) = [3, 3, 5]` * `["one", "two", "three"].map (·.reverse) = ["eno", "owt", "eerht"]` -/ -@[specialize] def List.map (f : α → β) : (l : List α) → List β +@[specialize, implicit_reducible] def List.map (f : α → β) : (l : List α) → List β | nil => nil | cons a as => cons (f a) (map f as) @@ -3150,7 +3173,7 @@ Examples: * `[2, 3, 2].flatMap List.range = [0, 1, 0, 1, 2, 0, 1]` * `["red", "blue"].flatMap String.toList = ['r', 'e', 'd', 'b', 'l', 'u', 'e']` -/ -@[inline] noncomputable def List.flatMap {α : Type u} {β : Type v} (b : α → List β) (as : List α) : List β := flatten (map b as) +@[inline, implicit_reducible] noncomputable def List.flatMap {α : Type u} {β : Type v} (b : α → List β) (as : List α) : List β := flatten (map b as) /-- `Array α` is the type of [dynamic arrays](https://en.wikipedia.org/wiki/Dynamic_array) with elements @@ -3214,7 +3237,7 @@ def Array.mkEmpty {α : Type u} (c : @& Nat) : Array α where /-- Constructs a new empty array with initial capacity `c`. -/ -@[extern "lean_mk_empty_array_with_capacity"] +@[extern "lean_mk_empty_array_with_capacity", implicit_reducible] def Array.emptyWithCapacity {α : Type u} (c : @& Nat) : Array α where toList := List.nil @@ -3223,7 +3246,7 @@ Constructs a new empty array with initial capacity `0`. Use `Array.emptyWithCapacity` to create an array with a greater initial capacity. -/ -@[inline] +@[inline, implicit_reducible] def Array.empty {α : Type u} : Array α := emptyWithCapacity 0 /-- @@ -3256,7 +3279,7 @@ This function does not use `get_elem_tactic` to automatically find the proof tha the index is in bounds. This is because the tactic itself needs to look up values in arrays. -/ -@[extern "lean_array_fget"] +@[extern "lean_array_fget", instance_reducible] def Array.getInternal {α : Type u} (a : @& Array α) (i : @& Nat) (h : LT.lt i a.size) : α := a.toList.get ⟨i, h⟩ @@ -3288,7 +3311,7 @@ Use the indexing notation `a[i]!` instead. Access an element from an array, or panic if the index is out of bounds. -/ -@[extern "lean_array_get"] +@[extern "lean_array_get", implicit_reducible] def Array.get!Internal {α : Type u} [@&Inhabited α] (a : @& Array α) (i : @& Nat) : α := Array.getD a i default @@ -3302,7 +3325,7 @@ Examples: * `#[].push "apple" = #["apple"]` * `#["apple"].push "orange" = #["apple", "orange"]` -/ -@[extern "lean_array_push"] +@[extern "lean_array_push", implicit_reducible] def Array.push {α : Type u} (a : Array α) (v : α) : Array α where toList := List.concat a.toList v @@ -3405,7 +3428,7 @@ attribute [extern "lean_byte_array_data"] ByteArray.data /-- Constructs a new empty byte array with initial capacity `c`. -/ -@[extern "lean_mk_empty_byte_array"] +@[extern "lean_mk_empty_byte_array", implicit_reducible] def ByteArray.emptyWithCapacity (c : @& Nat) : ByteArray := { data := Array.empty } @@ -3414,6 +3437,7 @@ Constructs a new empty byte array with initial capacity `0`. Use `ByteArray.emptyWithCapacity` to create an array with a greater initial capacity. -/ +@[implicit_reducible] def ByteArray.empty : ByteArray := emptyWithCapacity 0 /-- @@ -3422,15 +3446,16 @@ array. If there are no other references to the array, then it is modified in-pla This takes amortized `O(1)` time because `ByteArray` is represented by a dynamic array. -/ -@[extern "lean_byte_array_push"] +@[extern "lean_byte_array_push", implicit_reducible] def ByteArray.push : ByteArray → UInt8 → ByteArray | ⟨bs⟩, b => ⟨bs.push b⟩ /-- Converts a list of bytes into a `ByteArray`. -/ +@[implicit_reducible] def List.toByteArray (bs : List UInt8) : ByteArray := - let rec loop + let rec @[implicit_reducible] loop | nil, r => r | cons b bs, r => loop bs (r.push b) loop bs ByteArray.empty @@ -3441,13 +3466,14 @@ Returns the number of bytes in the byte array. This is the number of bytes actually in the array, as distinct from its capacity, which is the amount of memory presently allocated for the array. -/ -@[extern "lean_byte_array_size", tagged_return] +@[extern "lean_byte_array_size", tagged_return, instance_reducible] def ByteArray.size : (@& ByteArray) → Nat | ⟨bs⟩ => bs.size /-- Returns the sequence of bytes in a character's UTF-8 encoding. -/ +@[implicit_reducible] def String.utf8EncodeChar (c : Char) : List UInt8 := let v := c.val.toNat ite (LE.le v 0x7f) @@ -3478,6 +3504,7 @@ def String.utf8EncodeChar (c : Char) : List UInt8 := /-- Encode a list of characters (Unicode scalar value) in UTF-8. This is an inefficient model implementation. Use `List.asString` instead. -/ +@[implicit_reducible] noncomputable def List.utf8Encode (l : List Char) : ByteArray := l.flatMap String.utf8EncodeChar |>.toByteArray @@ -3520,7 +3547,7 @@ Examples: * `String.ofList [] = ""` * `String.ofList ['a', 'a', 'a'] = "aaa"` -/ -@[extern "lean_string_mk"] +@[extern "lean_string_mk", implicit_reducible] def String.ofList (data : List Char) : String := ⟨List.utf8Encode data, .intro data rfl⟩ @@ -3530,7 +3557,7 @@ Decides whether two strings are equal. Normally used via the `DecidableEq String At runtime, this function is overridden with an efficient native implementation. -/ -@[extern "lean_string_dec_eq"] +@[extern "lean_string_dec_eq", implicit_reducible] def String.decEq (s₁ s₂ : @& String) : Decidable (Eq s₁ s₂) := match s₁, s₂ with | ⟨⟨⟨s₁⟩⟩, _⟩, ⟨⟨⟨s₂⟩⟩, _⟩ => @@ -3600,7 +3627,7 @@ The number of bytes used by the string's UTF-8 encoding. At runtime, this function takes constant time because the byte length of strings is cached. -/ -@[extern "lean_string_utf8_byte_size", tagged_return] +@[extern "lean_string_utf8_byte_size", tagged_return, instance_reducible] def String.utf8ByteSize (s : @& String) : Nat := s.toByteArray.size @@ -3610,7 +3637,7 @@ A UTF-8 byte position that points at the end of a string, just after the last ch * `"abc".rawEndPos = ⟨3⟩` * `"L∃∀N".rawEndPos = ⟨8⟩` -/ -@[inline] def String.rawEndPos (s : String) : String.Pos.Raw where +@[inline, instance_reducible] def String.rawEndPos (s : String) : String.Pos.Raw where byteIdx := utf8ByteSize s /-- @@ -4101,7 +4128,7 @@ overridden by `withReader`, but it cannot be mutated. Actions in the resulting monad are functions that take the local value as a parameter, returning ordinary actions in `m`. -/ -def ReaderT (ρ : Type u) (m : Type u → Type v) (α : Type u) : Type (max u v) := +@[instance_reducible] def ReaderT (ρ : Type u) (m : Type u → Type v) (α : Type u) : Type (max u v) := (a : @&ρ) → m α /-- @@ -5025,7 +5052,7 @@ def Syntax.node8 (info : SourceInfo) (kind : SyntaxNodeKind) (a₁ a₂ a₃ a Singleton `SyntaxNodeKinds` are extremely common. They are written as name literals, rather than as lists; list syntax is required only for empty or non-singleton sets of kinds. -/ -@[expose] def SyntaxNodeKinds := List SyntaxNodeKind +@[expose, instance_reducible] def SyntaxNodeKinds := List SyntaxNodeKind /-- Typed syntax, which tracks the potential kinds of the `Syntax` it contains. diff --git a/src/Init/WF.lean b/src/Init/WF.lean index 1eb80f8a1cff..ead7402f57c4 100644 --- a/src/Init/WF.lean +++ b/src/Init/WF.lean @@ -475,6 +475,7 @@ variable (h : α → Nat) variable (F : (x : α) → ((y : α) → InvImage (· < ·) h y x → motive y) → motive x) /-- Helper gadget that prevents reduction of `Nat.eager n` unless `n` evaluates to a ground term. -/ +@[implicit_reducible] def Nat.eager (n : Nat) : Nat := if Nat.beq n n = true then n else n @@ -489,6 +490,7 @@ In contrast to `WellFounded.fix`, this fixpoint operator reduces on closed terms when `h x` evaluates to a ground value) -/ +@[implicit_reducible] def Nat.fix : (x : α) → motive x := let rec go : ∀ (fuel : Nat) (x : α), (h x < fuel) → motive x := Nat.rec @@ -496,6 +498,9 @@ def Nat.fix : (x : α) → motive x := (fun _ ih x hfuel => F x (fun y hy => ih y (by exact Nat.lt_of_lt_of_le hy (Nat.le_of_lt_add_one hfuel)))) fun x => go (Nat.eager (h x + 1)) x (Nat.eager_eq _ ▸ Nat.lt_add_one _) +-- Workaround: `@[implicit_reducible]` causes inlining as if it was an instance +attribute [implicit_reducible] Nat.fix.go + protected theorem Nat.fix.go_congr (x : α) (fuel₁ fuel₂ : Nat) (h₁ : h x < fuel₁) (h₂ : h x < fuel₂) : Nat.fix.go h F fuel₁ x h₁ = Nat.fix.go h F fuel₂ x h₂ := by induction fuel₁ generalizing x fuel₂ with @@ -519,7 +524,7 @@ The `wfParam` gadget is used internally during the construction of recursive fun wellfounded recursion, to keep track of the parameter for which the automatic introduction of `List.attach` (or similar) is plausible. -/ -def wfParam {α : Sort u} (a : α) : α := a +@[instance_reducible] def wfParam {α : Sort u} (a : α) : α := a /-- Reverse direction of `dite_eq_ite`. Used by the well-founded definition preprocessor to extend the diff --git a/src/Lean/Elab/BuiltinTerm.lean b/src/Lean/Elab/BuiltinTerm.lean index fe4da771f66d..2aa71a36fd03 100644 --- a/src/Lean/Elab/BuiltinTerm.lean +++ b/src/Lean/Elab/BuiltinTerm.lean @@ -368,6 +368,42 @@ private def resynthInstImplicitArgs (type : Expr) : TermElabM Expr := do let args := mvars ++ args.drop mvars.size instantiateMVars (mkAppN fn args) +/-- +Best-effort unification of the user-supplied `type` against the `expectedType` to resolve +user-placed `_` placeholders. We decompose both sides as applications of a common head and +unify arguments position-by-position, skipping instance-implicit positions. + +Instance-implicit arguments of `type` are fresh synthetic class metavariables introduced by +`elabType` that will be discarded by `resynthInstImplicitArgs`. Routing them through `isDefEq` +serves no purpose and can spuriously fail: assigning a synthetic class metavariable triggers +a transparency cap at `.instances` in the type-equality check (see +`backward.isDefEq.respectTransparency.instances`), which prevents non-`[reducible]` definitions +from unfolding — so, e.g., `Neg (Nat ⧸ n) =?= Neg (Zmod n)` fails even though `Zmod` reduces +to `Nat ⧸ n` at `.default` transparency. The outer `isDefEq` then fails and rolls back the +useful assignments made to user `_` placeholders. + +When the two sides do not share a common-shape head, we fall back to a plain `isDefEq`. +Per-argument `isDefEq` calls are best-effort: a failure at one position does not roll back +successes at others. +-/ +private def unifyTypeForInferInstanceAs (type expectedType : Expr) : TermElabM Unit := do + let typeFn := type.getAppFn + let expectedFn := expectedType.getAppFn + let typeArgs := type.getAppArgs + let expectedArgs := expectedType.getAppArgs + unless typeFn.isConst && expectedFn.isConst + && typeFn.constName! == expectedFn.constName! + && typeArgs.size == expectedArgs.size do + discard <| isDefEq type expectedType + return + unless (← isDefEq typeFn expectedFn) do + return + let (_, bis, _) ← forallMetaTelescope (← inferType typeFn) + for i in [:typeArgs.size] do + if i < bis.size && bis[i]!.isInstImplicit then + continue + discard <| isDefEq typeArgs[i]! expectedArgs[i]! + @[builtin_term_elab Lean.Parser.Term.inferInstanceAs] def elabInferInstanceAs : TermElab := fun stx expectedType? => do -- The type argument is the last child (works for both `inferInstanceAs T` and `inferInstanceAs <| T`) let typeStx := stx[stx.getNumArgs - 1]! @@ -382,7 +418,7 @@ private def resynthInstImplicitArgs (type : Expr) : TermElabM Expr := do let type ← withSynthesize do let type ← elabType typeStx -- Unify with expected type to resolve metavariables (e.g., `_` placeholders) - discard <| isDefEq type expectedType + unifyTypeForInferInstanceAs type expectedType return type -- Re-infer instance-implicit args, so that synthesis is not influenced by the expected type's -- instance choices. diff --git a/src/Lean/Linter/TacticTypeCheck.lean b/src/Lean/Linter/TacticTypeCheck.lean index 34cb46737fb1..fd694fffbf46 100644 --- a/src/Lean/Linter/TacticTypeCheck.lean +++ b/src/Lean/Linter/TacticTypeCheck.lean @@ -17,16 +17,16 @@ open Lean Elab Command open Lean.Linter (logLint) /-- -Warn when the goal target is not type-correct at `.instances` transparency. +Warn when the goal target is not type-correct at `.implicit` transparency. This can happen when e.g. `unfold` leaves hypotheses whose types still refer to the pre-unfolded definition, preventing `rw`/`simp` from matching patterns. -/ register_builtin_option linter.tacticCheckInstances : Bool := { defValue := false - descr := "enable the linter that type-checks every tactic goal at `.instances` transparency" + descr := "enable the linter that type-checks every tactic goal at `.implicit` transparency" } -/-- A linter that runs `Meta.check _ .instances` on every tactic goal. -/ +/-- A linter that runs `Meta.check _ .implicit` on every tactic goal. -/ def tacticCheckInstances : Linter where run _cmdStx := do -- Do *not* check `linter.all` here, this linter is purely for debugging @@ -52,9 +52,9 @@ def tacticCheckInstances : Linter where -- -- For each goal, we run `check` first at `.default` transparency -- (bailing out if it fails — that's a more fundamental problem), then - -- (after resetting the unfold counter) at `.instances`. If the - -- `.instances` check fails, the defs unfolded at `.default` but not at - -- `.instances` are the candidates for `@[implicit_reducible]` and get + -- (after resetting the unfold counter) at `.implicit`. If the + -- `.implicit` check fails, the defs unfolded at `.default` but not at + -- `.implicit` are the candidates for `@[implicit_reducible]` and get -- reported to the user. The pattern mirrors `mkUnfoldAxiomsNote` in -- `Lean.Meta.Check`. -- `kind` selects the wording of the warning: @@ -72,10 +72,10 @@ def tacticCheckInstances : Linter where -- this is a different (more fundamental) problem. try Meta.check target .default catch _ => return none let counterDefault := (← get).diag.unfoldCounter - -- Reset and try at `.instances`. + -- Reset and try at `.implicit`. modify ({ · with diag := origDiag }) try - Meta.check target .instances + Meta.check target .implicit return none catch _ => let counterInst := (← get).diag.unfoldCounter @@ -93,7 +93,7 @@ def tacticCheckInstances : Linter where | "initial" => "consider rephrasing the goal or marking" | _ => "consider using propositional rewriting or marking" return some m!"{kind} tactic goal is not type-correct at \ - `.instances` transparency; {remedy} some of the following as \ + `.implicit` transparency; {remedy} some of the following as \ `@[implicit_reducible]`:\ {indentD (.joinSep candidates Format.line)}" -- Always restore the original diagnostics snapshot. diff --git a/src/Lean/Meta/Check.lean b/src/Lean/Meta/Check.lean index 672af2e711d8..2caecbf26372 100644 --- a/src/Lean/Meta/Check.lean +++ b/src/Lean/Meta/Check.lean @@ -348,11 +348,11 @@ prior tactics (such as `unfold`) leaving the goal in a state that's type-correct def withInstancesTypeCheckNote [MonadControlT MetaM m] [Monad m] (e : Expr) (x : m α) : m α := do let typeCheckNote := MessageData.ofLazyM (es := #[e]) do try - check e .instances + check e .implicit return .nil catch _ => return MessageData.note m!"The target expression is not type-correct \ - under the `instances` transparency level, which may have triggered the failure. \ + under the `implicit` transparency level, which may have triggered the failure. \ This is usually caused by unfolding of semireducible definitions in prior tactic steps. \ Use `set_option linter.tacticCheckInstances true` to investigate the source of the issue." Meta.mapError x (· ++ typeCheckNote) diff --git a/src/Lean/Meta/ExprDefEq.lean b/src/Lean/Meta/ExprDefEq.lean index fa035156d41f..bb1cd1131ed0 100644 --- a/src/Lean/Meta/ExprDefEq.lean +++ b/src/Lean/Meta/ExprDefEq.lean @@ -53,11 +53,24 @@ Controls the transparency used to check whether the type of metavariable matches term being assigned to it. -/ register_builtin_option backward.isDefEq.respectTransparency.types : Bool := { - defValue := false -- TODO: replace with `true` after we fix stage0 + defValue := true descr := "if true, do not bump transparency to `.default` \ when checking whether the type of a metavariable matches the type of the term being assigned to it." } +/-- +Controls whether, when checking the type of an assignment to an instance-implicit (`[..]`) +metavariable, the transparency is capped at `.instances` so an ambient `.default`/`.all` +does not let semireducible definitions be unfolded. + +This option only has an effect when `backward.isDefEq.respectTransparency.types` is `true`. +-/ +register_builtin_option backward.isDefEq.respectTransparency.instances : Bool := { + defValue := true + descr := "if true (the default), cap transparency at `.instances` when checking the type \ + of an assignment to an instance-implicit metavariable" +} + /-- Controls whether *all* implicit arguments (not just instance-implicit `[..]`) get their transparency bumped to `TransparencyMode.instances` during `isDefEq`. @@ -79,6 +92,11 @@ register_builtin_option backward.isDefEq.implicitBump : Bool := { not just instance-implicit ones" } +register_builtin_option trace.Meta.isDefEq.printTransparency : Bool := { + defValue := false + descr := "if true, prefix `Meta.isDefEq` `=?=` trace messages with the current transparency level" +} + /-- Return `true` if `e` is of the form `fun (x_1 ... x_n) => ?m y_1 ... y_k)`, and `?m` is unassigned. Remark: `n`, `k` may be 0. @@ -350,7 +368,11 @@ struct arguments. Bumps transparency to at least `.instances` so type class inst (`[instance_reducible]`) unfold; `[implicit_reducible]` does **not** unfold here. For example, we must be able to unfold instances, `beta := true`, `proj := .yesWithDelta` are essential. -/ -@[inline] def withInstanceConfig (x : MetaM α) : MetaM α := +@[inline] def withInstanceConfig (x : MetaM α) : MetaM α := do + let old ← getTransparency + if old.lt .instances then + trace[Meta.isDefEq.transparency] + "raising transparency {toString old} → instances (checking instance-implicit argument)" withAtLeastTransparency .instances do let cfg ← getConfig if cfg.beta && cfg.iota && cfg.zeta && cfg.zetaHave && cfg.zetaDelta && cfg.proj == .yesWithDelta then @@ -364,7 +386,11 @@ implicit *value* arguments and assigned mvar types. Bumps transparency to at lea so both `[instance_reducible]` and `[implicit_reducible]` unfold. Used for non-instance implicit arguments where definitions like `Nat.add` / `Array.size` need to reduce to make types match. -/ -@[inline] def withImplicitConfig (x : MetaM α) : MetaM α := +@[inline] def withImplicitConfig (x : MetaM α) : MetaM α := do + let old ← getTransparency + if old.lt .implicit then + trace[Meta.isDefEq.transparency] + "raising transparency {toString old} → implicit (checking implicit value argument or assigned metavariable type)" withAtLeastTransparency .implicit do let cfg ← getConfig if cfg.beta && cfg.iota && cfg.zeta && cfg.zetaHave && cfg.zetaDelta && cfg.proj == .yesWithDelta then @@ -510,7 +536,21 @@ private def checkTypesAndAssign (mvar : Expr) (v : Expr) : MetaM Bool := let mvarType ← inferType mvar let vType ← inferType v if (← respectTransparencyAtTypes) then - withImplicitConfig do + -- For instance metavariables — those created for an instance-implicit (`[..]`) parameter, + -- identified by `.synthetic` kind together with a class type — cap the transparency at + -- exactly `.instances` so an ambient `.default`/`.all` does not let semireducible + -- definitions be unfolded while checking the type of an instance assignment. This + -- intentionally does not apply to ordinary implicit (`{..}`) metavariables that happen + -- to have a class type, which are created with `.natural` kind. + let isInstance ← + if backward.isDefEq.respectTransparency.instances.get (← getOptions) && + (← mvar.mvarId!.getKind) matches .synthetic then + pure (← isClass? mvarType).isSome + else + pure false + let capInstance (x : MetaM Bool) : MetaM Bool := + if isInstance then withTransparency .instances x else x + capInstance <| withImplicitConfig do if (← Meta.isExprDefEqAux mvarType vType) then mvar.mvarId!.assign v return true @@ -2293,7 +2333,11 @@ private def whnfCoreAtDefEq (e : Expr) : MetaM Expr := do set_option compiler.ignoreBorrowAnnotation true in @[export lean_is_expr_def_eq] partial def isExprDefEqAuxImpl (t : Expr) (s : Expr) : MetaM Bool := withIncRecDepth do - withTraceNodeBefore `Meta.isDefEq (fun _ => return m!"{t} =?= {s}") do + withTraceNodeBefore `Meta.isDefEq (fun _ => do + if trace.Meta.isDefEq.printTransparency.get (← getOptions) then + return m!"[{toString (← getTransparency)}] {t} =?= {s}" + else + return m!"{t} =?= {s}") do checkSystem "isDefEq" whenUndefDo (isDefEqQuick t s) do whenUndefDo (isDefEqProofIrrel t s) do @@ -2383,5 +2427,6 @@ builtin_initialize registerTraceClass `Meta.isDefEq.assign.occursCheck (inherited := true) registerTraceClass `Meta.isDefEq.assign.readOnlyMVarWithBiggerLCtx (inherited := true) registerTraceClass `Meta.isDefEq.eta.struct + registerTraceClass `Meta.isDefEq.transparency (inherited := true) end Lean.Meta diff --git a/src/Lean/Meta/SynthInstance.lean b/src/Lean/Meta/SynthInstance.lean index 76220bcc48ae..3d9213d55d30 100644 --- a/src/Lean/Meta/SynthInstance.lean +++ b/src/Lean/Meta/SynthInstance.lean @@ -31,6 +31,28 @@ register_builtin_option backward.synthInstance.canonInstances : Bool := { descr := "use optimization that relies on 'morally canonical' instances during type class resolution" } +/-- +Controls the transparency used by the post-synthesis check that unifies the original goal type +with the synthesized result's type when the class has `outParam`s. + +When `true` (the default), the check uses `.instances` transparency, matching the transparency +used by the rest of typeclass resolution. This means a non-reducible `def Bar := Nat` is *not* +unfolded, so e.g. `#synth Foo Nat Bar` cannot be satisfied by `instance : Foo Nat Nat`. + +When `false`, the check bumps transparency to `.default`, which unfolds semireducible +definitions. This was the historical behavior, retained because patterns like Mathlib's +`def OrderDual (α : Type) : Type := α` rely on `OrderDual α` and `α` being defEq at `.default` +during the outParam check. + +See `assignOutParams` for the implementation. +-/ +register_builtin_option backward.isDefEq.respectTransparency.outParams : Bool := { + defValue := true + descr := "if true (the default), do not bump transparency to `.default` \ + when checking that a synthesized instance's type matches the original goal type \ + for classes with `outParam`s" +} + namespace SynthInstance def getMaxHeartbeats (opts : Options) : Nat := @@ -795,8 +817,14 @@ private def assignOutParams (type : Expr) (result : Expr) : MetaM Bool := do ``` Mathlib developers are currently trying to refactor the `OrderDual` declaration, but it will take time. We will try to remove the `withDefault` again after the refactoring. + + The `backward.isDefEq.respectTransparency.outParams` option (defaulting to `true`) keeps the + check at `.instances` transparency. Setting it to `false` restores the historical `withDefault` + behavior. -/ - let defEq ← withDefault <| withAssignableSyntheticOpaque <| isDefEq type resultType + let bumpTransparency := !backward.isDefEq.respectTransparency.outParams.get (← getOptions) + let defEq ← (if bumpTransparency then withDefault else id) <| + withAssignableSyntheticOpaque <| isDefEq type resultType unless defEq do trace[Meta.synthInstance] "{crossEmoji} result type{indentExpr resultType}\nis not definitionally equal to{indentExpr type}" return defEq diff --git a/src/Lean/Meta/TransparencyMode.lean b/src/Lean/Meta/TransparencyMode.lean index 96980814b47e..8455a1f302cc 100644 --- a/src/Lean/Meta/TransparencyMode.lean +++ b/src/Lean/Meta/TransparencyMode.lean @@ -24,6 +24,16 @@ def hash : TransparencyMode → UInt64 instance : Hashable TransparencyMode := ⟨hash⟩ +protected def toString : TransparencyMode → String + | all => "all" + | default => "default" + | reducible => "reducible" + | instances => "instances" + | implicit => "implicit" + | none => "none" + +instance : ToString TransparencyMode := ⟨TransparencyMode.toString⟩ + def lt : TransparencyMode → TransparencyMode → Bool | _, none => false | none, _ => true diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index ddf61c724821..00f1e46a2b3f 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -359,6 +359,7 @@ def get? [BEq α] [LawfulBEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Opt buckets[i].getCast? a /-- Internal implementation detail of the hash map -/ +@[instance_reducible] def contains [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Bool := let ⟨⟨_, buckets⟩, h⟩ := m let ⟨i, h⟩ := mkIdx buckets.size h (hash a) diff --git a/src/Std/Data/DHashMap/Internal/Model.lean b/src/Std/Data/DHashMap/Internal/Model.lean index 5739c4b108b6..fdbf7f596fb3 100644 --- a/src/Std/Data/DHashMap/Internal/Model.lean +++ b/src/Std/Data/DHashMap/Internal/Model.lean @@ -45,6 +45,7 @@ open Std.Internal /-! # Setting up the infrastructure -/ /-- Internal implementation detail of the hash map -/ +@[instance_reducible] def bucket [Hashable α] (self : Array (AssocList α β)) (h : 0 < self.size) (k : α) : AssocList α β := let ⟨i, h⟩ := mkIdx self.size h (hash k) @@ -289,6 +290,7 @@ def getKey?ₘ [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Option α := (bucket m.1.buckets m.2 a).getKey? a /-- Internal implementation detail of the hash map -/ +@[instance_reducible] def containsₘ [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Bool := (bucket m.1.buckets m.2 a).contains a @@ -528,22 +530,16 @@ theorem contains_eq_containsₘ [BEq α] [Hashable α] (m : Raw₀ α β) (a : theorem insert_eq_insertₘ [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) (b : β a) : m.insert a b = m.insertₘ a b := by - rw [insert, insertₘ, containsₘ, bucket] - dsimp only [Array.ugetElem_eq_getElem, Array.uset] - split - · simp only [replaceₘ, Subtype.mk.injEq, Raw.mk.injEq, true_and] - rw [Array.set_set, updateBucket] - simp only [Array.uset, Array.ugetElem_eq_getElem] - · rfl + simp [insert, insertₘ, containsₘ, bucket, replaceₘ, updateBucket, consₘ] theorem alter_eq_alterₘ [BEq α] [Hashable α] [LawfulBEq α] (m : Raw₀ α β) (a : α) (f : Option (β a) → Option (β a)) : m.alter a f = m.alterₘ a f := by - simp only [alter, alterₘ, containsₘ, ← bucket_eq] - split - · congr 2 - · simp only [withComputedSize, bucket_updateBucket, AssocList.contains_eq] - · simp only [Array.uset, bucket, Array.ugetElem_eq_getElem, Array.set_set, updateBucket] - · congr + simp only [alter, alterₘ, containsₘ, ← bucket_eq] + simp only [AssocList.contains_eq, Array.uset_eq_set, Array.set_set, buckets_withComputedSize, + bucket_updateBucket] + split + · rfl + · rfl theorem modify_eq_alter [BEq α] [Hashable α] [LawfulBEq α] (m : Raw₀ α β) (a : α) (f : β a → β a) : m.modify a f = m.alter a (·.map f) := by @@ -573,7 +569,7 @@ theorem alter_eq_alterₘ [BEq α] [Hashable α] [EquivBEq α] (m : Raw₀ α (f · congr 2 · simp only [withComputedSize, bucket_updateBucket, AssocList.contains_eq] · simp only [Array.uset, bucket, Array.ugetElem_eq_getElem, Array.set_set, updateBucket] - · congr + · rfl theorem modify_eq_alter [BEq α] [Hashable α] [EquivBEq α] (m : Raw₀ α (fun _ => β)) (a : α) (f : β → β) : Const.modify m a f = Const.alter m a (·.map f) := by diff --git a/src/Std/Data/DTreeMap/Internal/Def.lean b/src/Std/Data/DTreeMap/Internal/Def.lean index e907afe2ae30..920b4ee14f25 100644 --- a/src/Std/Data/DTreeMap/Internal/Def.lean +++ b/src/Std/Data/DTreeMap/Internal/Def.lean @@ -37,7 +37,7 @@ def delta : Nat := 3 /-- The "ratio" parameter of the size-bounded tree. Controls how aggressive the rebalancing operations are. -/ -@[inline, Std.Internal.tree_tac] +@[inline, Std.Internal.tree_tac, instance_reducible] def ratio : Nat := 2 variable {α : Type u} {β : α → Type v} @@ -52,7 +52,7 @@ In contrast to other functions, `size` is defined here because it is required to -/ /-- The size information stored in the tree. -/ -@[inline] +@[inline, instance_reducible] def size : Impl α β → Nat | inner sz _ _ _ _ => sz | leaf => 0 diff --git a/src/Std/Data/DTreeMap/Internal/Operations.lean b/src/Std/Data/DTreeMap/Internal/Operations.lean index 94c3962aa704..caf5b77278d6 100644 --- a/src/Std/Data/DTreeMap/Internal/Operations.lean +++ b/src/Std/Data/DTreeMap/Internal/Operations.lean @@ -668,6 +668,7 @@ structure BalancedTree where attribute [Std.Internal.tree_tac] BalancedTree.balanced_impl /-- Transforms an element of `SizedBalancedTree` into a `BalancedTree`. -/ +@[instance_reducible] def SizedBalancedTree.toBalancedTree {lb ub} (t : SizedBalancedTree α β lb ub) : BalancedTree α β := ⟨t.impl, t.balanced_impl⟩ diff --git a/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean b/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean index 4da99092f0c9..872d3992d13f 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean @@ -52,7 +52,7 @@ it.drop 3 ------⊥ Currently, this combinator incurs an additional O(1) cost with each output of `it`, even when the iterator does not drop any elements anymore. -/ -@[always_inline, inline] +@[always_inline, inline, instance_reducible] def IterM.drop (n : Nat) (it : IterM (α := α) m β) := (⟨Iterators.Types.Drop.mk n it⟩ : IterM m β) diff --git a/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean b/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean index c2cc457ba13b..dda56d8c2c29 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean @@ -56,7 +56,7 @@ created directly with `IterM.dropWhileWithPostcondition` but only with `Intermediate.dropWhileWithPostcondition` is meant to be used only for internally or for verification purposes. -/ -@[always_inline, inline] +@[always_inline, inline, instance_reducible] def IterM.Intermediate.dropWhileWithPostcondition (P : β → PostconditionT m (ULift Bool)) (dropping : Bool) (it : IterM (α := α) m β) := (⟨Iterators.Types.DropWhile.mk (P := P) dropping it⟩ : IterM m β) @@ -80,7 +80,7 @@ directly with `IterM.dropWhile` but only with `Intermediate.dropWhile`. `Intermediate.dropWhile` is meant to be used only for internally or for verification purposes. -/ -@[always_inline, inline] +@[always_inline, inline, instance_reducible] def IterM.Intermediate.dropWhile [Monad m] (P : β → Bool) (dropping : Bool) (it : IterM (α := α) m β) := (IterM.Intermediate.dropWhileWithPostcondition (pure ∘ ULift.up ∘ P) dropping it : IterM m β) diff --git a/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean b/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean index 540dea988814..84505bbf172f 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean @@ -155,7 +155,7 @@ In this case, the `Finite` (or `Productive`) instance needs to be proved manuall This combinator calls `P` on each output of `it` until the predicate evaluates to false. Then it terminates. -/ -@[always_inline, inline] +@[always_inline, inline, instance_reducible] def IterM.takeWhile [Monad m] (P : β → Bool) (it : IterM (α := α) m β) := (it.takeWhileWithPostcondition (pure ∘ ULift.up ∘ P) : IterM m β) diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean index 9c030f916e7f..e5d84f008a1c 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean @@ -37,8 +37,19 @@ theorem Iter.step_drop {α β} [Iterator α Id β] {n : Nat} | .done h => .done (.done h)) := by simp only [drop_eq, step, toIterM_toIter, IterM.step_drop, Id.run_bind] generalize it.toIterM.step.run = step - cases step.inflate using PlausibleIterStep.casesOn <;> cases n <;> - simp [PlausibleIterStep.yield, PlausibleIterStep.skip, PlausibleIterStep.done] + cases step.inflate using PlausibleIterStep.casesOn <;> cases n --<;> + · simp only [PlausibleIterStep.yield, Id.run_pure, Shrink.inflate_deflate, + IterM.Step.toPure_yield, toIter_toIterM, toIterM_toIter] + · simp only [PlausibleIterStep.skip, Id.run_pure, Shrink.inflate_deflate, IterM.Step.toPure_skip, + IterM.Step.toPure_yield, PlausibleIterStep.yield, toIter_toIterM, toIterM_toIter] + · simp only [PlausibleIterStep.skip, Id.run_pure, Shrink.inflate_deflate, IterM.Step.toPure_skip, + toIter_toIterM, toIterM_toIter] + · simp only [PlausibleIterStep.skip, Id.run_pure, Shrink.inflate_deflate, IterM.Step.toPure_skip, + toIter_toIterM, toIterM_toIter] + · simp only [PlausibleIterStep.done, Id.run_pure, Shrink.inflate_deflate, IterM.Step.toPure_done, + toIter_toIterM] + · simp only [PlausibleIterStep.done, Id.run_pure, Shrink.inflate_deflate, IterM.Step.toPure_done, + toIter_toIterM] theorem Iter.atIdxSlow?_drop {α β} [Iterator α Id β] [Productive α Id] {k l : Nat} diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean index 1dcc8fa98d87..3890a4cf5dbc 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean @@ -24,6 +24,7 @@ cannot be created directly with `IterM.zip`. `Intermediate.zip` is meant to be used only for verification purposes. -/ +@[instance_reducible] noncomputable def IterM.Intermediate.zip [Iterator α₁ m β₁] (it₁ : IterM (α := α₁) m β₁) (memo : (Option { out : β₁ // ∃ it : IterM (α := α₁) m β₁, it.IsPlausibleOutput out })) diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/TakeWhile.lean b/src/Std/Data/Iterators/Lemmas/Combinators/TakeWhile.lean index 19a969ad431c..0431b9f406d3 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/TakeWhile.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/TakeWhile.lean @@ -48,10 +48,11 @@ theorem Iter.val_step_takeWhile {α β} [Iterator α Id β] {P} | false => .done | .skip it' => .skip (it'.takeWhile P) | .done => .done) := by - simp [Iter.takeWhile_eq, Iter.step, toIterM_toIter, IterM.step_takeWhile] + simp only [takeWhile_eq, step, toIterM_toIter, IterM.step_takeWhile, PlausibleIterStep.yield, + PlausibleIterStep.done, PlausibleIterStep.skip, Id.run_bind, IterM.Step.val_toPure] generalize it.toIterM.step.run = step cases step.inflate using PlausibleIterStep.casesOn - · simp only [IterM.Step.toPure_yield, PlausibleIterStep.yield, toIter_toIterM, toIterM_toIter] + · simp only [IterStep.mapIterator_yield, toIterM_toIter] split <;> split <;> (try exfalso; simp_all; done) <;> simp_all · simp · simp diff --git a/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean b/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean index 320bee2c34f3..40f93c4fc289 100644 --- a/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean +++ b/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean @@ -64,6 +64,7 @@ A noncomputable variant of `IterM.step` using the `HetT` monad. It is used in the definition of the equivalence relations on iterators, namely `IterM.Equiv` and `Iter.Equiv`. -/ +@[instance_reducible] noncomputable def IterM.stepAsHetT [Iterator α m β] [Monad m] (it : IterM (α := α) m β) : HetT m (IterStep (IterM (α := α) m β) β) := ⟨it.IsPlausibleStep, inferInstance, (fun step => .deflate step.inflate) <$> it.step⟩ diff --git a/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean b/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean index 824e886a82c5..663e7103f2d7 100644 --- a/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean +++ b/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean @@ -187,6 +187,7 @@ attribute [-simp] HetT.mk.injEq /-- Converts `PostconditionT m α` to `HetT m α`, preserving the postcondition property. -/ +@[instance_reducible] noncomputable def HetT.ofPostconditionT [Monad m] (x : PostconditionT m α) : HetT m α := ⟨x.Property, inferInstance, USquash.deflate <$> x.operation⟩ @@ -198,6 +199,7 @@ Lifts `x : m α` into `HetT m α` with the trivial postcondition. Caution: This is not a lawful monad lifting function -/ +@[instance_reducible] noncomputable def HetT.lift {α : Type w} {m : Type w → Type w'} [Monad m] (x : m α) : HetT m α := x @@ -206,14 +208,14 @@ noncomputable def HetT.lift {α : Type w} {m : Type w → Type w'} [Monad m] (x A universe-heterogeneous version of `Pure.pure`. Given `a : α`, it returns an element of `HetT m α` with the postcondition `(a = ·)`. -/ -protected noncomputable def HetT.pure {m : Type w → Type w'} [Pure m] {α : Type v} +@[instance_reducible] protected noncomputable def HetT.pure {m : Type w → Type w'} [Pure m] {α : Type v} (a : α) : HetT m α := ⟨(a = ·), inferInstance, pure (.deflate ⟨a, rfl⟩)⟩ /-- A generalization of `HetT.map` that provides the postcondition property to the mapping function. -/ -protected noncomputable def HetT.pmap {m : Type w → Type w'} [Functor m] {α : Type u} {β : Type v} +@[instance_reducible] protected noncomputable def HetT.pmap {m : Type w → Type w'} [Functor m] {α : Type u} {β : Type v} (x : HetT m α) (f : (a : α) → x.Property a → β) : HetT m β := have : Small.{w} (Subtype x.Property) := x.small have := Small.map x.Property f @@ -222,13 +224,14 @@ protected noncomputable def HetT.pmap {m : Type w → Type w'} [Functor m] {α : /-- A universe-heterogeneous version of `Functor.map`. -/ -protected noncomputable def HetT.map {m : Type w → Type w'} [Functor m] {α : Type u} {β : Type v} +@[instance_reducible] protected noncomputable def HetT.map {m : Type w → Type w'} [Functor m] {α : Type u} {β : Type v} (f : α → β) (x : HetT m α) : HetT m β := x.pmap (fun a _ => f a) /-- A generalization of `HetT.bind` that provides the postcondition property to the mapping function. -/ +@[instance_reducible] protected noncomputable def HetT.pbind {m : Type w → Type w'} [Monad m] {α : Type u} {β : Type v} (x : HetT m α) (f : (a : α) → x.Property a → HetT m β) : HetT m β := have := x.small @@ -241,7 +244,7 @@ protected noncomputable def HetT.pbind {m : Type w → Type w'} [Monad m] {α : /-- A universe-heterogeneous version of `Bind.bind`. -/ -protected noncomputable def HetT.bind {m : Type w → Type w'} [Monad m] {α : Type u} {β : Type v} +@[instance_reducible] protected noncomputable def HetT.bind {m : Type w → Type w'} [Monad m] {α : Type u} {β : Type v} (x : HetT m α) (f : α → HetT m β) : HetT m β := have := x.small have := fun a => (f a).small @@ -290,6 +293,7 @@ theorem HetT.prun_ofPostconditionT [Monad m] [LawfulMonad m] {x : PostconditionT /-- If the monad `m` is liftable to `n`, lifts `HetT m α` to `HetT n α`. -/ +@[instance_reducible] noncomputable def HetT.liftInner {m : Type w → Type w'} (n : Type w → Type w'') [MonadLiftT m n] (x : HetT m α) : HetT n α := ⟨x.Property, x.small, x.operation⟩ diff --git a/src/Std/Do/PostCond.lean b/src/Std/Do/PostCond.lean index ddc76b50b266..802233683d8c 100644 --- a/src/Std/Do/PostCond.lean +++ b/src/Std/Do/PostCond.lean @@ -104,7 +104,7 @@ example : ExceptConds (.arg σ (.except ε .pure)) = ((ε → ULift Prop) × Uni example : ExceptConds (.except ε (.arg σ .pure)) = ((ε → σ → ULift Prop) × Unit) := rfl ``` -/ -def ExceptConds : PostShape.{u} → Type u +@[instance_reducible] def ExceptConds : PostShape.{u} → Type u | .pure => PUnit | .arg _ ps => ExceptConds ps | .except ε ps => (ε → Assertion ps) × ExceptConds ps diff --git a/src/Std/Do/WP/Basic.lean b/src/Std/Do/WP/Basic.lean index dc6e035271c8..ca1acacd29a7 100644 --- a/src/Std/Do/WP/Basic.lean +++ b/src/Std/Do/WP/Basic.lean @@ -152,7 +152,7 @@ theorem Except.of_wp_eq {ε α : Type u} {x prog : Except ε α} (h : prog = x) (⊢ₛ wp⟦prog⟧ post⟨fun a => ⌜P (.ok a)⌝, fun e => ⌜P (.error e)⌝⟩) → P x := by subst h intro hspec - simp only [wp, ExceptT.run, Id.run, PredTrans.apply_pushExcept, PredTrans.apply_Pure_pure, instWP._aux_1] at hspec + simp only [wp, ExceptT.run, Id.run, PredTrans.apply_pushExcept, PredTrans.apply_Pure_pure] at hspec split at hspec <;> exact hspec True.intro /-- @@ -164,7 +164,7 @@ Useful if you want to prove a property about an expression `prog : Except ε α` theorem Except.of_wp {ε α : Type u} {prog : Except ε α} (P : Except ε α → Prop) : (⊢ₛ wp⟦prog⟧ post⟨fun a => ⌜P (.ok a)⌝, fun e => ⌜P (.error e)⌝⟩) → P prog := by intro hspec - simp only [wp, ExceptT.run, Id.run, PredTrans.apply_pushExcept, PredTrans.apply_Pure_pure, instWP._aux_1] at hspec + simp only [wp, ExceptT.run, Id.run, PredTrans.apply_pushExcept, PredTrans.apply_Pure_pure] at hspec split at hspec <;> exact hspec True.intro /-- @@ -176,7 +176,7 @@ theorem Option.of_wp_eq {α : Type u} {x prog : Option α} (h : prog = x) (P : O (⊢ₛ wp⟦prog⟧ post⟨fun a => ⌜P (some a)⌝, fun _ => ⌜P none⌝⟩) → P x := by subst h intro hspec - simp only [wp, OptionT.run, Id.run, PredTrans.apply_pushOption, PredTrans.apply_Pure_pure, instWP._aux_1] at hspec + simp only [wp, OptionT.run, Id.run, PredTrans.apply_pushOption, PredTrans.apply_Pure_pure] at hspec split at hspec <;> exact hspec True.intro /-- diff --git a/src/Std/Do/WP/SimpLemmas.lean b/src/Std/Do/WP/SimpLemmas.lean index b2ae319e9092..875833376967 100644 --- a/src/Std/Do/WP/SimpLemmas.lean +++ b/src/Std/Do/WP/SimpLemmas.lean @@ -422,7 +422,7 @@ theorem throwThe [MonadExceptOf ε m] [WP m ps] : @[simp] theorem throw_Except : wp⟦MonadExceptOf.throw e : Except ε α⟧ Q = Q.2.1 e := by - simp [wp, MonadExceptOf.throw, Id.run, ExceptT.run, Except.instWP._aux_1] + simp [wp, MonadExceptOf.throw, Id.run, ExceptT.run] @[simp] theorem throw_ExceptT [Monad m] [WPMonad m ps] : @@ -432,7 +432,7 @@ theorem throw_ExceptT [Monad m] [WPMonad m ps] : @[simp] theorem throw_Option : wp⟦MonadExceptOf.throw e : Option α⟧ Q = Q.2.1 e := by - simp [wp, MonadExceptOf.throw, Id.run, OptionT.run, Option.instWP._aux_1] + simp [wp, MonadExceptOf.throw, Id.run, OptionT.run] @[simp] theorem throw_OptionT [Monad m] [WPMonad m ps] : @@ -484,7 +484,7 @@ theorem tryCatchThe [MonadExceptOf ε m] [WP m ps] : @[simp] theorem tryCatch_Except : wp⟦MonadExceptOf.tryCatch x h : Except ε α⟧ Q = wp⟦x⟧ (Q.1, fun e => wp⟦h e⟧ Q, Q.2.2) := by - simp only [wp, Except.instWP._aux_1, ExceptT.run, Id.run, MonadExceptOf.tryCatch, Except.tryCatch, + simp only [wp, ExceptT.run, Id.run, MonadExceptOf.tryCatch, Except.tryCatch, PredTrans.apply_pushExcept] cases x <;> simp @@ -501,7 +501,7 @@ theorem tryCatch_ExceptT [Monad m] [WPMonad m ps] : @[simp] theorem tryCatch_Option : wp⟦MonadExceptOf.tryCatch x h : Option α⟧ Q = wp⟦x⟧ (Q.1, fun e => wp⟦h e⟧ Q, Q.2.2) := by - simp only [wp, Option.instWP._aux_1, Id.run, OptionT.run, MonadExceptOf.tryCatch, Option.tryCatch, + simp only [wp, Id.run, OptionT.run, MonadExceptOf.tryCatch, Option.tryCatch, PredTrans.apply_pushOption] cases x <;> simp @@ -590,7 +590,7 @@ theorem orElse_ExceptT [Monad m] [WPMonad m ps] : @[simp] theorem orElse_Option : wp⟦OrElse.orElse x h : Option α⟧ Q = wp⟦x⟧ (Q.1, fun _ => wp⟦h ()⟧ Q, Q.2.2) := by - cases x <;> simp [OrElse.orElse, Option.orElse, wp, Id.run, OptionT.run, Option.instWP._aux_1] + cases x <;> simp [OrElse.orElse, Option.orElse, wp, Id.run, OptionT.run] @[simp] theorem orElse_OptionT [Monad m] [WPMonad m ps] : diff --git a/src/Std/Sat/AIG/Basic.lean b/src/Std/Sat/AIG/Basic.lean index 71803618d516..f6cc20ddc774 100644 --- a/src/Std/Sat/AIG/Basic.lean +++ b/src/Std/Sat/AIG/Basic.lean @@ -249,7 +249,7 @@ def Cache.get? (cache : Cache α decls) (decl : Decl α) : Option (CacheHit decl An `Array Decl` is a Direct Acyclic Graph (DAG) if a gate at index `i` only points to nodes with index lower than `i`. -/ def IsDAG (α : Type) (decls : Array (Decl α)) : Prop := - ∀ {i lhs rhs} (h : i < decls.size), + ∀ ⦃i lhs rhs⦄ (h : i < decls.size), decls[i] = .gate lhs rhs → lhs.gate < i ∧ rhs.gate < i /-- @@ -321,7 +321,7 @@ structure Ref (aig : AIG α) where /-- A `Ref` into `aig1` is also valid for `aig2` if `aig1` is smaller than `aig2`. -/ -@[inline] +@[inline, instance_reducible] def Ref.cast {aig1 aig2 : AIG α} (ref : Ref aig1) (h : aig1.decls.size ≤ aig2.decls.size) : Ref aig2 := { ref with hgate := by have := ref.hgate; omega } @@ -534,7 +534,7 @@ def mkGate (aig : AIG α) (input : BinaryInput aig) : Entrypoint α := let cache := aig.cache.noUpdate have hdag := by intro i lhs' rhs' h1 h2 - simp only [Array.getElem_push] at h2 + simp only [decls, Array.getElem_push] at h2 split at h2 · apply aig.hdag <;> assumption · injection h2 with hl hr @@ -556,7 +556,7 @@ def mkAtom (aig : AIG α) (n : α) : Entrypoint α := let cache := aig.cache.noUpdate have hdag := by intro i lhs rhs h1 h2 - simp only [Array.getElem_push] at h2 + simp only [decls, Array.getElem_push] at h2 split at h2 · apply aig.hdag <;> assumption · contradiction @@ -574,7 +574,7 @@ def mkConst (aig : AIG α) (val : Bool) : Entrypoint α := let cache := aig.cache.noUpdate have hdag := by intro i lhs rhs h1 h2 - simp only [Array.getElem_push] at h2 + simp only [decls, Array.getElem_push] at h2 split at h2 · apply aig.hdag <;> assumption · contradiction diff --git a/src/Std/Sat/AIG/Cached.lean b/src/Std/Sat/AIG/Cached.lean index bbeab847c7f5..f88e0f42444a 100644 --- a/src/Std/Sat/AIG/Cached.lean +++ b/src/Std/Sat/AIG/Cached.lean @@ -40,7 +40,7 @@ def mkAtomCached (aig : AIG α) (n : α) : Entrypoint α := let decls := decls.push decl have hdag := by intro i lhs rhs h1 h2 - simp only [Array.getElem_push] at h2 + simp only [decls, Array.getElem_push] at h2 split at h2 · apply hdag <;> assumption · contradiction @@ -116,7 +116,7 @@ where let decls := decls.push decl have hdag := by intro i lhs rhs h1 h2 - simp only [Array.getElem_push] at h2 + simp only [decls, Array.getElem_push] at h2 simp_all split at h2 · apply hdag <;> assumption diff --git a/src/Std/Sat/AIG/If.lean b/src/Std/Sat/AIG/If.lean index bab08411832b..42dd2976533a 100644 --- a/src/Std/Sat/AIG/If.lean +++ b/src/Std/Sat/AIG/If.lean @@ -64,16 +64,14 @@ def mkIfCached (aig : AIG α) (input : TernaryInput aig) : Entrypoint α := instance : LawfulOperator α TernaryInput mkIfCached where le_size := by intros - unfold mkIfCached - dsimp only + simp only [mkIfCached] apply LawfulOperator.le_size_of_le_aig_size (f := mkOrCached) apply LawfulOperator.le_size_of_le_aig_size (f := mkAndCached) apply LawfulOperator.le_size_of_le_aig_size (f := mkNotCached) apply LawfulOperator.le_size (f := mkAndCached) decl_eq := by intros - unfold mkIfCached - dsimp only + simp only [mkIfCached] rw [LawfulOperator.decl_eq (f := mkOrCached)] rw [LawfulOperator.decl_eq (f := mkAndCached)] rw [LawfulOperator.decl_eq (f := mkNotCached)] @@ -98,18 +96,21 @@ theorem denote_mkIfCached {aig : AIG α} {input : TernaryInput aig} : = if ⟦aig, input.discr, assign⟧ then ⟦aig, input.lhs, assign⟧ else ⟦aig, input.rhs, assign⟧ := by rw [if_as_bool] - unfold mkIfCached - dsimp only - simp only [TernaryInput.cast, Ref.cast_eq, denote_mkOrCached, - denote_projected_entry, denote_mkAndCached, denote_mkNotCached] + simp only [mkIfCached] + simp only [TernaryInput.cast, Ref.cast_eq, Ref.cast, denote_mkOrCached, denote_projected_entry, + denote_mkAndCached, denote_mkNotCached] congr 2 - · rw [LawfulOperator.denote_mem_prefix (LawfulOperator.lt_size ..)] + · rw [LawfulOperator.denote_mem_prefix] rw [LawfulOperator.denote_mem_prefix] · simp · simp [Ref.hgate] + · apply LawfulOperator.lt_size_of_lt_aig_size (f := mkNotCached) + simp [Ref.hgate] + · rw [LawfulOperator.denote_mem_prefix] · rw [LawfulOperator.denote_mem_prefix] - · rw [LawfulOperator.denote_mem_prefix (LawfulOperator.lt_size_of_lt_aig_size _ _ input.rhs.hgate)] rw [LawfulOperator.denote_mem_prefix] + · apply LawfulOperator.lt_size_of_lt_aig_size (f := mkAndCached) + simp [Ref.hgate] namespace RefVec @@ -180,7 +181,7 @@ instance : LawfulVecOperator α IfInput ite where apply ite.go_le_size decl_eq := by intros - unfold ite + simp only [ite] rw [ite.go_decl_eq] namespace ite @@ -200,7 +201,7 @@ theorem go_get_aux {w : Nat} (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (d intros rw [go_get_aux (hidx := Nat.lt_succ_of_lt hidx) (hfoo := go_le_size ..)] rw [AIG.RefVec.get_push_ref_lt (hidx := hidx)] - simp only [Ref.cast, Ref.mk.injEq] + simp only [Ref.cast] rw [AIG.RefVec.get_cast] simp · rw [← hgo] @@ -253,7 +254,7 @@ theorem denote_go {w : Nat} (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (di intro idx hidx1 hidx2 generalize hgo : go aig curr hcurr discr lhs rhs s = res unfold go at hgo - dsimp only at hgo + simp only at hgo split at hgo · cases Nat.eq_or_lt_of_le hidx2 with | inl heq => @@ -262,8 +263,8 @@ theorem denote_go {w : Nat} (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (di rw [go_get]; case hidx => omega rw [AIG.RefVec.get_push_ref_eq'] · rw [go_denote_mem_prefix] - · simp - · simp [Ref.hgate] + · simp [Ref.cast] + · simp [Ref.cast, Ref.hgate] · omega | inr heq => rw [← hgo] diff --git a/src/Std/Sat/AIG/RefVec.lean b/src/Std/Sat/AIG/RefVec.lean index a5a46eddd13d..bbe1e56eafe5 100644 --- a/src/Std/Sat/AIG/RefVec.lean +++ b/src/Std/Sat/AIG/RefVec.lean @@ -34,7 +34,7 @@ def emptyWithCapacity (c : Nat) : RefVec aig 0 where theorem emptyWithCapacity_eq : emptyWithCapacity (aig := aig) c = empty := by rfl -@[inline] +@[inline, instance_reducible] def cast' {aig1 aig2 : AIG α} (s : RefVec aig1 len) (h : (∀ {i : Nat} (h : i < len), s.refs[i].gate < aig1.decls.size) @@ -48,7 +48,7 @@ def cast' {aig1 aig2 : AIG α} (s : RefVec aig1 len) apply s.hrefs } -@[inline] +@[inline, instance_reducible] def cast {aig1 aig2 : AIG α} (s : RefVec aig1 len) (h : aig1.decls.size ≤ aig2.decls.size) : RefVec aig2 len := s.cast' <| by @@ -107,7 +107,7 @@ theorem get_cast {aig1 aig2 : AIG α} (s : RefVec aig1 len) (idx : Nat) (hidx : (s.cast hcast).get idx hidx = (s.get idx hidx).cast hcast := by - simp [cast, cast', get] + simp [get, cast, cast'] @[inline] def append (lhs : RefVec aig lw) (rhs : RefVec aig rw) : RefVec aig (lw + rw) := diff --git a/src/Std/Sat/AIG/RefVecOperator/Fold.lean b/src/Std/Sat/AIG/RefVecOperator/Fold.lean index 94c07ea1301c..f1734354b02a 100644 --- a/src/Std/Sat/AIG/RefVecOperator/Fold.lean +++ b/src/Std/Sat/AIG/RefVecOperator/Fold.lean @@ -89,8 +89,7 @@ theorem fold_decl_eq {aig : AIG α} (vec : RefVec aig len) = aig.decls[idx]'h1 := by intros - unfold fold - dsimp only + simp only [fold] rw [fold.go_decl_eq] theorem fold_lt_size_of_lt_aig_size (aig : AIG α) (vec : RefVec aig len) diff --git a/src/Std/Sat/AIG/RelabelNat.lean b/src/Std/Sat/AIG/RelabelNat.lean index 40de5d64b1d6..f2f586ee19a0 100644 --- a/src/Std/Sat/AIG/RelabelNat.lean +++ b/src/Std/Sat/AIG/RelabelNat.lean @@ -333,7 +333,7 @@ theorem relabelNat_size_eq_size {aig : AIG α} : aig.relabelNat.decls.size = aig theorem relabelNat_unsat_iff_of_NonEmpty [Nonempty α] {aig : AIG α} {hidx1} {hidx2} : (aig.relabelNat).UnsatAt idx invert hidx1 ↔ aig.UnsatAt idx invert hidx2 := by - dsimp only [relabelNat, relabelNat'] + simp only [relabelNat, relabelNat'] rw [relabel_unsat_iff] intro x y hx hy heq split at heq diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Carry.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Carry.lean index 06dad774daa4..98c02fdb457a 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Carry.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Carry.lean @@ -85,13 +85,11 @@ termination_by w - curr instance : AIG.LawfulOperator α OverflowInput mkOverflowBit where le_size := by intros - unfold mkOverflowBit - dsimp only + simp only [mkOverflowBit] apply go_le_size decl_eq := by intros - unfold mkOverflowBit - dsimp only + simp only [mkOverflowBit] rw [go_decl_eq] end mkOverflowBit diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Add.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Add.lean index fb5e48ff543d..cb7b95e6449d 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Add.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Add.lean @@ -74,14 +74,12 @@ def mkFullAdderOut (aig : AIG α) (input : FullAdderInput aig) : AIG.Entrypoint instance : AIG.LawfulOperator α FullAdderInput mkFullAdderOut where le_size := by intros - unfold mkFullAdderOut - dsimp only + simp only [mkFullAdderOut] apply AIG.LawfulOperator.le_size_of_le_aig_size apply AIG.LawfulOperator.le_size decl_eq := by intros - unfold mkFullAdderOut - dsimp only + simp only [mkFullAdderOut] rw [AIG.LawfulOperator.decl_eq] rw [AIG.LawfulOperator.decl_eq] apply AIG.LawfulOperator.lt_size_of_lt_aig_size @@ -116,8 +114,7 @@ def mkFullAdderCarry (aig : AIG α) (input : FullAdderInput aig) : AIG.Entrypoin instance : AIG.LawfulOperator α FullAdderInput mkFullAdderCarry where le_size := by intros - unfold mkFullAdderCarry - dsimp only + simp only [mkFullAdderCarry] apply AIG.LawfulOperator.le_size_of_le_aig_size (f := AIG.mkOrCached) apply AIG.LawfulOperator.le_size_of_le_aig_size (f := AIG.mkAndCached) apply AIG.LawfulOperator.le_size_of_le_aig_size (f := AIG.mkAndCached) @@ -125,8 +122,7 @@ instance : AIG.LawfulOperator α FullAdderInput mkFullAdderCarry where decl_eq := by intros - unfold mkFullAdderCarry - dsimp only + simp only [mkFullAdderCarry] rw [AIG.LawfulOperator.decl_eq] rw [AIG.LawfulOperator.decl_eq] rw [AIG.LawfulOperator.decl_eq] @@ -230,7 +226,7 @@ theorem go_decl_eq (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (cin : AIG.R apply AIG.LawfulOperator.lt_size_of_lt_aig_size exact h3 rw [go_decl_eq (w := w) (curr := curr + 1) (h1 := h4)] - unfold mkFullAdder + simp only [mkFullAdder] rw [AIG.LawfulOperator.decl_eq (f := mkFullAdderCarry) (h1 := h3)] rw [AIG.LawfulOperator.decl_eq (f := mkFullAdderOut)] · simp [← hgo] @@ -239,13 +235,11 @@ termination_by w - curr instance : AIG.LawfulVecOperator α AIG.BinaryRefVec blast where le_size := by intros - unfold blast - dsimp only + simp only [blast] apply go_le_size decl_eq := by intros - unfold blast - dsimp only + simp only [blast] rw [go_decl_eq] end blastAdd diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Cpop.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Cpop.lean index 605cf8c8156e..802aacbbd33a 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Cpop.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Cpop.lean @@ -51,15 +51,13 @@ def blastExtractAndExtendBit (aig : AIG α) (target : ExtractAndExtendBitTarget instance : AIG.LawfulVecOperator α ExtractAndExtendBitTarget blastExtractAndExtendBit where le_size := by intros - unfold blastExtractAndExtendBit - dsimp only + simp only [blastExtractAndExtendBit] apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := blastZeroExtend) apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := blastExtract) omega decl_eq := by intros - unfold blastExtractAndExtendBit - dsimp only + simp only [blastExtractAndExtendBit] rw [AIG.LawfulVecOperator.decl_eq (f := blastZeroExtend), AIG.LawfulVecOperator.decl_eq (f := blastExtract)] apply AIG.LawfulVecOperator.lt_size_of_lt_aig_size diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Eq.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Eq.lean index b653adfa915d..44d0f8777bd0 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Eq.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Eq.lean @@ -31,14 +31,12 @@ def mkEq (aig : AIG α) (pair : AIG.BinaryRefVec aig w) : AIG.Entrypoint α := instance {w : Nat} : AIG.LawfulOperator α (AIG.BinaryRefVec · w) mkEq where le_size := by intros - unfold mkEq - dsimp only + simp only [mkEq] apply AIG.RefVec.fold_le_size_of_le_aig_size apply AIG.RefVec.zip_le_size decl_eq := by intros - unfold mkEq - dsimp only + simp only [mkEq] rw [AIG.RefVec.fold_decl_eq] rw [AIG.RefVec.zip_decl_eq] apply AIG.RefVec.zip_lt_size_of_lt_aig_size diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Neg.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Neg.lean index c9b8ec88397f..4445744b88a9 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Neg.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Neg.lean @@ -37,14 +37,12 @@ def blastNeg (aig : AIG α) (input : AIG.RefVec aig w) : AIG.RefVecEntry α w := instance : AIG.LawfulVecOperator α AIG.RefVec blastNeg where le_size := by intros - unfold blastNeg - dsimp only + simp only [blastNeg] apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := blastAdd) apply AIG.LawfulVecOperator.le_size (f := blastNot) decl_eq := by intros - unfold blastNeg - dsimp only + simp only [blastNeg] rw [AIG.LawfulVecOperator.decl_eq (f := blastAdd)] rw [AIG.LawfulVecOperator.decl_eq (f := blastNot)] · apply AIG.LawfulVecOperator.lt_size_of_lt_aig_size (f := blastNot) diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Sub.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Sub.lean index 517f8fc78c47..8020b8d1a24d 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Sub.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Sub.lean @@ -35,12 +35,12 @@ def blastSub (aig : AIG α) (input : AIG.BinaryRefVec aig w) : AIG.RefVecEntry instance : AIG.LawfulVecOperator α AIG.BinaryRefVec blastSub where le_size := by intros - unfold blastSub + simp only [blastSub] apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := blastAdd) apply AIG.LawfulVecOperator.le_size (f := blastNeg) decl_eq := by intros - unfold blastSub + simp only [blastSub] rw [AIG.LawfulVecOperator.decl_eq (f := blastAdd)] rw [AIG.LawfulVecOperator.decl_eq (f := blastNeg)] apply AIG.LawfulVecOperator.lt_size_of_lt_aig_size (f := blastNeg) diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Udiv.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Udiv.lean index 2e96c8758d9c..39e640013276 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Udiv.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Udiv.lean @@ -44,13 +44,11 @@ def blastShiftConcat (aig : AIG α) (input : ShiftConcatInput aig w) : AIG.RefVe instance : AIG.LawfulVecOperator α ShiftConcatInput blastShiftConcat where le_size := by intros - unfold blastShiftConcat - dsimp only + simp only [blastShiftConcat] apply AIG.LawfulVecOperator.le_size (f := blastZeroExtend) decl_eq := by intros - unfold blastShiftConcat - dsimp only + simp only [blastShiftConcat] rw [AIG.LawfulVecOperator.decl_eq (f := blastZeroExtend)] structure BlastDivSubtractShiftOutput (old : AIG α) (w : Nat) where @@ -279,13 +277,13 @@ def blastUdiv (aig : AIG α) (input : AIG.BinaryRefVec aig w) : AIG.RefVecEntry instance : AIG.LawfulVecOperator α AIG.BinaryRefVec blastUdiv where le_size := by intros - unfold blastUdiv + simp only [blastUdiv] apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := AIG.RefVec.ite) refine Nat.le_trans ?_ (by apply blastUdiv.go_le_size) apply AIG.LawfulOperator.le_size (f := BVPred.mkEq) decl_eq := by intros - unfold blastUdiv + simp only [blastUdiv] rw [AIG.LawfulVecOperator.decl_eq (f := AIG.RefVec.ite)] rw [blastUdiv.go_decl_eq] rw [AIG.LawfulOperator.decl_eq (f := BVPred.mkEq)] diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Ult.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Ult.lean index 16cf64d2003b..f73e91e9db5c 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Ult.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Ult.lean @@ -41,15 +41,13 @@ def mkUlt (aig : AIG α) (pair : AIG.BinaryRefVec aig w) : AIG.Entrypoint α := instance {w : Nat} : AIG.LawfulOperator α (AIG.BinaryRefVec · w) mkUlt where le_size := by intros - unfold mkUlt - dsimp only + simp only [mkUlt] apply AIG.LawfulOperator.le_size_of_le_aig_size (f := AIG.mkNotCached) apply AIG.LawfulOperator.le_size_of_le_aig_size (f := BVExpr.bitblast.mkOverflowBit) apply AIG.LawfulVecOperator.le_size (f := BVExpr.bitblast.blastNot) decl_eq := by intros - unfold mkUlt - dsimp only + simp only [mkUlt] rw [AIG.LawfulOperator.decl_eq (f := AIG.mkNotCached)] rw [AIG.LawfulOperator.decl_eq (f := BVExpr.bitblast.mkOverflowBit)] rw [AIG.LawfulVecOperator.decl_eq (f := BVExpr.bitblast.blastNot)] diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Umod.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Umod.lean index 24688b4309da..b37b8daf38d9 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Umod.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Operations/Umod.lean @@ -48,13 +48,13 @@ def blastUmod (aig : AIG α) (input : AIG.BinaryRefVec aig w) : AIG.RefVecEntry instance : AIG.LawfulVecOperator α AIG.BinaryRefVec blastUmod where le_size := by intros - unfold blastUmod + simp only [blastUmod] apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := AIG.RefVec.ite) refine Nat.le_trans ?_ (by apply blastUdiv.go_le_size) apply AIG.LawfulOperator.le_size (f := BVPred.mkEq) decl_eq := by intros - unfold blastUmod + simp only [blastUmod] rw [AIG.LawfulVecOperator.decl_eq (f := AIG.RefVec.ite)] rw [blastUdiv.go_decl_eq] rw [AIG.LawfulOperator.decl_eq (f := BVPred.mkEq)] diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Pred.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Pred.lean index 94d51d73ad1e..e77c8c840a5a 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Pred.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Impl/Pred.lean @@ -66,7 +66,7 @@ theorem bitblast_decl_eq (aig : AIG BVBit) (input : BVExpr.WithCache BVPred aig) ∀ (idx : Nat) (h1) (h2), (bitblast aig input).result.val.aig.decls[idx]'h2 = aig.decls[idx]'h1 := by intro idx h1 h2 rcases input with ⟨pred, cache⟩ - unfold BVPred.bitblast + simp only [BVPred.bitblast] cases pred with | bin lhs op rhs => cases op with diff --git a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Lemmas/Expr.lean b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Lemmas/Expr.lean index 9289e6d209b1..102b1e7e0e63 100644 --- a/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Lemmas/Expr.lean +++ b/src/Std/Tactic/BVDecide/Bitblast/BVExpr/Circuit/Lemmas/Expr.lean @@ -87,7 +87,7 @@ theorem Inv_insert (cache : Cache aig) (expr : BVExpr w) (refs : AIG.RefVec aig · exact hk · simp [heq] have : ((cache.insert expr refs).map.get k hk) = cache.map.get k hmem := by - unfold Cache.insert + simp only [Cache.insert] rw [Std.DHashMap.get_insert] simp [heq] specialize hinv k hmem i hi diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RatAddSound.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RatAddSound.lean index 8768924f6520..d8a32630706a 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RatAddSound.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RatAddSound.lean @@ -65,6 +65,7 @@ theorem entails_of_irrelevant_assignment {n : Nat} {p : (PosFin n) → Bool} {c · simp [Clause.toList, delete_iff, negl_ne_v, v_in_c_del_l] · grind +open Classical in theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) (hf : f.ratUnits = #[] ∧ AssignmentsInvariant f) (units : CNF.Clause (PosFin n)) : AssignmentsInvariant (insertRatUnits f units).1 := by @@ -74,13 +75,13 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) intro i b hb p hp simp only [(· ⊨ ·), Clause.eval] at hp simp only [toList, List.append_assoc, - List.any_eq_true, Prod.exists, Bool.exists_bool, Bool.decide_coe, + List.any_eq_true, Prod.exists, Bool.exists_bool, decide_eq_true_eq, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, List.mem_map] at hp have pf : p ⊨ f := by simp only [(· ⊨ ·), Clause.eval] simp only [toList, List.append_assoc, List.any_eq_true, Prod.exists, Bool.exists_bool, - Bool.decide_coe, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, List.mem_map] + decide_eq_true_eq, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, List.mem_map] intro c cf rcases cf with cf | cf | cf · specialize hp c (Or.inl cf) @@ -108,8 +109,7 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) constructor · have h1 : (insertRatUnits f units).fst.ratUnits[j] = (i, true) := by rw [hb'] at h1 - simp only [h1, Prod.mk.injEq, and_true] - rfl + simp [h1] rw [← h1] apply Array.getElem_mem_toList · rfl @@ -119,8 +119,7 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) constructor · have h1 : (insertRatUnits f units).fst.ratUnits[j] = (i, false) := by rw [hb'] at h1 - simp only [h1, Prod.mk.injEq, and_true] - rfl + simp [h1] rw [← h1] apply Array.getElem_mem_toList · rfl @@ -132,7 +131,7 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) rcases hp with ⟨hp1, hp2⟩ | ⟨hp1, hp2⟩ · simp only [b_eq_b', ← hp1.2, (· ⊨ ·)] rw [hp1.1] at hp2 - exact of_decide_eq_true hp2 + exact hp2 · simp only [b_eq_b', ← hp1.2, (· ⊨ ·)] rw [hp1.1] at hp2 exact hp2 @@ -151,8 +150,6 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) constructor · have h1 : (insertRatUnits f units).fst.ratUnits[j1] = (i, true) := by rw [h1] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h1] apply Array.getElem_mem_toList · rfl @@ -167,8 +164,6 @@ theorem assignmentsInvariant_insertRatUnits {n : Nat} (f : DefaultFormula n) constructor · have h2 : (insertRatUnits f units).fst.ratUnits[j2] = (i, false) := by rw [h2] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h2] apply Array.getElem_mem_toList · rfl @@ -411,11 +406,13 @@ theorem existsRatHint_of_ratHintsExhaustive {n : Nat} (f : DefaultFormula n) List.mem_filterMap, id_eq, exists_eq_right] at c'_in_f rw [List.mem_iff_getElem] at c'_in_f rcases c'_in_f with ⟨i, hi, c'_in_f⟩ + -- The following `simp only` leaves behind a term containing a `decide` where the embedded + -- `Decidable` instances does not typecheck at `instances` transparency. simp only [ratHintsExhaustive, getRatClauseIndices] at ratHintsExhaustive_eq_true have i_in_bounds : i < Array.size (Array.range (Array.size f.clauses)) := by grind have i_lt_f_clauses_size : i < f.clauses.size := by grind have h : i ∈ (ratHints.map (fun x => x.1)).toList := by - rw [← of_decide_eq_true ratHintsExhaustive_eq_true] + simp only [← of_decide_eq_true_forward ratHintsExhaustive_eq_true] have i_eq_range_i : i = (Array.range f.clauses.size)[i]'i_in_bounds := by grind rw [i_eq_range_i] rw [Array.mem_toList_iff] @@ -471,6 +468,7 @@ theorem performRatCheck_success_of_performRatCheck_fold_success {n : Nat} (f : D have h := (Array.foldl_induction motive h_base h_inductive).2 performRatCheck_fold_success i simpa [getElem!_def, i.2, dite_true] using h +open Classical in theorem safe_insert_of_performRatCheck_fold_success {n : Nat} (f : DefaultFormula n) (f_readyForRatAdd : ReadyForRatAdd f) (c : DefaultClause n) (pivot : Literal (PosFin n)) (rupHints : Array Nat) (ratHints : Array (Nat × Array Nat)) @@ -543,7 +541,7 @@ theorem safe_insert_of_performRatCheck_fold_success {n : Nat} (f : DefaultFormul apply h c' hc' p simp only [(· ⊨ ·), Clause.eval] simp only [List.any_eq_true, Prod.exists, Bool.exists_bool, - Bool.decide_coe, List.all_eq_true, decide_eq_true_eq] + decide_eq_true_eq, List.all_eq_true, decide_eq_true_eq] intro c'' hc'' simp only [toList, clauses_performRupCheck, rupUnits_performRupCheck, ratUnits_performRupCheck] at hc'' @@ -567,8 +565,7 @@ theorem safe_insert_of_performRatCheck_fold_success {n : Nat} (f : DefaultFormul simp only [Bool.not_eq_true] at h assumption · simp only [(· ⊨ ·), Clause.eval] at pf - simp only [List.any_eq_true, Prod.exists, Bool.exists_bool, Bool.decide_coe, List.all_eq_true] at pf - simp only [Bool.decide_eq_false, Bool.not_eq_true'] at pf + simp only [List.any_eq_true, Prod.exists, Bool.exists_bool, decide_eq_true_eq, List.all_eq_true] at pf apply pf assumption have p'_entails_c'_del_negPivot : p' ⊨ c'.delete (Literal.negate pivot) := entails_of_irrelevant_assignment h diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean index 2eb33c594c33..fda1d724bbfd 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean @@ -116,23 +116,22 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen ⟨units.size, units_size_lt_updatedUnits_size⟩ have i_gt_zero : i.1 > 0 := by rw [i_eq_l]; exact l.1.2.1 refine ⟨mostRecentUnitIdx, l.2, i_gt_zero, ?_⟩ - simp +zetaDelta only [insertUnit, h3, ite_false, Array.getElem_push_eq, i_eq_l, reduceCtorEq] + simp +zetaDelta only [insertUnit, h3, ite_false, Array.getElem_push_eq, i_eq_l, + reduceCtorEq, true_and] constructor - · rfl + · grind · constructor · grind - · constructor - · grind - · intro k hk - have k_in_bounds : k.1 < units.size := by - apply Nat.lt_of_le_of_ne - · have k_property := k.2 - grind - · intro h - simp only [← h, not_true] at hk - rw [Array.getElem_push_lt k_in_bounds] - rw [i_eq_l] at h2 - exact h2 ⟨k.1, k_in_bounds⟩ + · intro k hk + have k_in_bounds : k.1 < units.size := by + apply Nat.lt_of_le_of_ne + · have k_property := k.2 + grind + · intro h + simp only [← h, not_true] at hk + rw [Array.getElem_push_lt k_in_bounds] + rw [i_eq_l] at h2 + exact h2 ⟨k.1, k_in_bounds⟩ next i_ne_l => apply Or.inl simp only [insertUnit, h3, ite_false, reduceCtorEq] @@ -188,7 +187,6 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen · rw [Array.getElem_push_lt j.2, h1] · constructor · simp +zetaDelta [i_eq_l, ← hl] - rfl · constructor · simp only [i_eq_l] rw [Array.getElem_modify_self] @@ -223,7 +221,6 @@ theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignmen simp only [insertUnit, h5, Bool.false_eq_true, ↓reduceIte, mostRecentUnitIdx] constructor · simp +zetaDelta [i_eq_l, ← hl] - rfl · constructor · rw [Array.getElem_push_lt j.2, h1] · constructor @@ -525,13 +522,11 @@ theorem clear_insert_inductive_case {n : Nat} (f : DefaultFormula n) (f_assignme next h2 => have k_ne_j1 : k ≠ j1 := by grind have h3 := units_nodup k j1 k_ne_j1 - simp only [Fin.getElem_fin, ih1, ← h1, ← h2, ne_eq] at h3 - exact h3 rfl + simp [ih1, ← h1, ← h2, ne_eq] at h3 next h2 => have h3 := units_nodup k j2 k_ne_j2 simp only [Bool.not_eq_true] at h2 - simp only [Fin.getElem_fin, ih2, ← h1, ← h2, ne_eq] at h3 - exact h3 rfl + simp [ih2, ← h1, ← h2, ne_eq] at h3 next idx_ne_j1 => by_cases idx = j2 next idx_eq_j2 => @@ -557,14 +552,12 @@ theorem clear_insert_inductive_case {n : Nat} (f : DefaultFormula n) (f_assignme by_cases units[k.1].2 next h2 => have h3 := units_nodup k j1 k_ne_j1 - simp only [Fin.getElem_fin, ih1, ← h1, ← h2, ne_eq] at h3 - exact h3 rfl + simp [Fin.getElem_fin, ih1, ← h1, ← h2, ne_eq] at h3 next h2 => have k_ne_j2 : k ≠ j2 := by grind have h3 := units_nodup k j2 k_ne_j2 simp only [Bool.not_eq_true] at h2 - simp only [Fin.getElem_fin, ih2, ← h1, ← h2, ne_eq] at h3 - exact h3 rfl + simp [ih2, ← h1, ← h2, ne_eq] at h3 next idx_ne_j2 => refine Or.inr <| Or.inr <| ⟨j1, j2,i_gt_zero, ?_⟩ constructor diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean index 80cfab7431b7..d1fbb81ac740 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean @@ -232,6 +232,7 @@ theorem safe_insert_of_insertRup {n : Nat} (f : DefaultFormula n) (f_readyForRup · simp only [formulaEntails_def, List.all_eq_true, decide_eq_true_eq] at pf exact pf c' c'_in_f +open Classical in theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f : DefaultFormula n) (f_readyForRupAdd : ReadyForRupAdd f) (units : CNF.Clause (PosFin n)) : AssignmentsInvariant (insertRupUnits f units).1 := by @@ -241,12 +242,12 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f intro i b hb p hp simp only [(· ⊨ ·), Clause.eval] at hp simp only [toList, List.append_assoc, List.any_eq_true, Prod.exists, - Bool.exists_bool, Bool.decide_coe, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, - exists_eq_right, List.mem_map] at hp + Bool.exists_bool, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, + List.mem_map, decide_eq_true_eq] at hp have pf : p ⊨ f := by simp only [(· ⊨ ·), Clause.eval] simp only [toList, List.append_assoc, List.any_eq_true, Prod.exists, Bool.exists_bool, - Bool.decide_coe, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, List.mem_map] + decide_eq_true_eq, List.all_eq_true, List.mem_append, List.mem_filterMap, id_eq, exists_eq_right, List.mem_map] intro c cf rcases cf with cf | cf | cf · specialize hp c (Or.inl cf) @@ -275,8 +276,6 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f · have h1 : (insertRupUnits f units).fst.rupUnits[j] = (i, true) := by rw [hb'] at h1 rw [h1] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h1] apply Array.getElem_mem_toList · rfl @@ -287,8 +286,6 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f · have h1 : (insertRupUnits f units).fst.rupUnits[j] = (i, false) := by rw [hb'] at h1 rw [h1] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h1] apply Array.getElem_mem_toList · rfl @@ -301,7 +298,7 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f rcases hp with ⟨hp1, hp2⟩ | ⟨hp1, hp2⟩ · simp only [b_eq_b', ← hp1.2, Entails.eval] rw [hp1.1] at hp2 - exact of_decide_eq_true hp2 + exact hp2 · simp only [b_eq_b', ← hp1.2, Entails.eval] rw [hp1.1] at hp2 exact hp2 @@ -321,8 +318,6 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f constructor · have h1 : (insertRupUnits f units).fst.rupUnits[j1] = (i, true) := by rw [h1] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h1] apply Array.getElem_mem_toList · rfl @@ -337,8 +332,6 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f constructor · have h2 : (insertRupUnits f units).fst.rupUnits[j2] = (i, false) := by rw [h2] - simp only [Prod.mk.injEq, and_true] - rfl rw [← h2] apply Array.getElem_mem_toList · rfl @@ -350,9 +343,8 @@ theorem assignmentsInvariant_insertRupUnits_of_assignmentsInvariant {n : Nat} (f simp only [Fin.getElem_fin] at h1 simp only [Fin.getElem_fin] at h2 simp only [Clause.toList, h1, unit_eq, List.mem_cons, Prod.mk.injEq, Bool.false_eq_true, - and_false, List.not_mem_nil, or_self, Bool.decide_eq_false, Bool.not_eq_eq_eq_not, - Bool.not_true, false_and, and_true, or_false, false_or, h2, Bool.true_eq_false, - ] at hp1 hp2 + and_false, List.not_mem_nil, or_self, false_and, and_true, or_false, false_or, h2, + Bool.true_eq_false] at hp1 hp2 simp only [hp2.1, ← hp1.1, true_and] at hp2 simp [hp1.2] at hp2 diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/PosFin.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/PosFin.lean index 1c6889b13eed..135a6bf022ef 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/PosFin.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/PosFin.lean @@ -14,19 +14,7 @@ namespace Std.Tactic.BVDecide namespace LRAT namespace Internal -def PosFin (n : Nat) := {x : Nat // 0 < x ∧ x < n} - -instance : DecidableEq (PosFin n) := - inferInstanceAs (DecidableEq {x : Nat // 0 < x ∧ x < n}) - -instance : CoeOut (PosFin n) Nat where - coe p := p.val - -instance {n} : Hashable (PosFin n) where - hash p := hash p.val - -instance : ToString (PosFin n) where - toString p := toString p.val +abbrev PosFin (n : Nat) := {x : Nat // 0 < x ∧ x < n} end Internal end LRAT diff --git a/src/Std/Time/Date/Unit/Year.lean b/src/Std/Time/Date/Unit/Year.lean index a8fd4b0350e5..d8d47fe49f68 100644 --- a/src/Std/Time/Date/Unit/Year.lean +++ b/src/Std/Time/Date/Unit/Year.lean @@ -36,7 +36,7 @@ instance : ToString Era where /-- `Offset` represents a year offset, defined as an `Int`. -/ -@[expose] def Offset : Type := Int +@[expose, instance_reducible] def Offset : Type := Int deriving Repr, DecidableEq, Inhabited, Add, Sub, Neg, LE, LT, ToString set_option backward.inferInstanceAs.wrap.instances false in diff --git a/src/Std/Time/Format/Basic.lean b/src/Std/Time/Format/Basic.lean index 01834412c8b6..dc25fecd1dd6 100644 --- a/src/Std/Time/Format/Basic.lean +++ b/src/Std/Time/Format/Basic.lean @@ -1164,13 +1164,13 @@ private def parseWith (config : FormatConfig) : (mod : Modifier) → Parser (Typ | .y format => match format with | .any => Int.ofNat <$> parseAtLeastNum 1 - | .twoDigit => (2000 + ·) <$> Int.ofNat <$> parseNum 2 + | .twoDigit => (fun x => (2000 + x : Int)) <$> Int.ofNat <$> parseNum 2 | .fourDigit => Int.ofNat <$> parseNum 4 | .extended n => Int.ofNat <$> parseNum n | .u format => match format with | .any => parseSigned <| parseAtLeastNum 1 - | .twoDigit => (2000 + ·) <$> Int.ofNat <$> parseNum 2 + | .twoDigit => (fun x => (2000 + x : Int)) <$> Int.ofNat <$> parseNum 2 | .fourDigit => parseSigned <| parseNum 4 | .extended n => parseSigned <| parseNum n | .D format => Sigma.mk true <$> parseNatToBounded (parseFlexibleNum format.padding) diff --git a/stage0/src/stdlib_flags.h b/stage0/src/stdlib_flags.h index e44444704908..223763431f74 100644 --- a/stage0/src/stdlib_flags.h +++ b/stage0/src/stdlib_flags.h @@ -12,6 +12,7 @@ options get_default_options() { // switch to `true` for ABI-breaking changes affecting meta code; // see also next option! opts = opts.update({"interpreter", "prefer_native"}, false); + opts = opts.update({"backward", "isDefEq", "respectTransparency", "types"}, true); // switch to `false` when enabling `prefer_native` should also affect use // of built-in parsers in quotations; this is usually the case, but setting // both to `true` may be necessary for handling non-builtin parsers with diff --git a/tests/elab/1385.lean b/tests/elab/1385.lean index dffa4d1d3c90..23ede6c1719f 100644 --- a/tests/elab/1385.lean +++ b/tests/elab/1385.lean @@ -1,6 +1,6 @@ -def S := List Nat +abbrev S := List Nat opaque TSpec : NonemptyType -def T (s : S) : Type := TSpec.type +abbrev T (s : S) : Type := TSpec.type instance (s : S) : Nonempty (T s) := TSpec.property diff --git a/tests/elab/2552.lean b/tests/elab/2552.lean index bfb3f05fd31e..42eef737988b 100644 --- a/tests/elab/2552.lean +++ b/tests/elab/2552.lean @@ -1,4 +1,4 @@ -@[inline] def decidable_of_iff'' {b : Prop} (a : Prop) (h : a ↔ b) [Decidable a] : Decidable b := +@[instance_reducible] def decidable_of_iff'' {b : Prop} (a : Prop) (h : a ↔ b) [Decidable a] : Decidable b := decidable_of_decidable_of_iff h theorem LE.le.lt_or_eq_dec {a b : Nat} (hab : a ≤ b) : a < b ∨ a = b := diff --git a/tests/elab/2901.lean b/tests/elab/2901.lean index f972cbe12b30..17b124a8769e 100644 --- a/tests/elab/2901.lean +++ b/tests/elab/2901.lean @@ -1,4 +1,4 @@ -def Vector' (α : Type u) (n : Nat) := +abbrev Vector' (α : Type u) (n : Nat) := { l : List α // l.length = n } inductive HVect : (n : Nat) -> (Vector' (Type v) n) -> Type (v+1) where diff --git a/tests/elab/3524.lean b/tests/elab/3524.lean index e63efe1b9d2b..0982c0a2ada3 100644 --- a/tests/elab/3524.lean +++ b/tests/elab/3524.lean @@ -1,3 +1,4 @@ +set_option maxRecDepth 1024 -- TODO: investigate why we had to increase it example (a : Nat) : ((2 ^ 7) + a) - 2 ^ 7 = 0 := by generalize 0 - 0 = x sorry diff --git a/tests/elab/3524.lean.out.expected b/tests/elab/3524.lean.out.expected index 27a6378d42ea..52db2666793f 100644 --- a/tests/elab/3524.lean.out.expected +++ b/tests/elab/3524.lean.out.expected @@ -1 +1 @@ -3524.lean:1:0-1:7: warning: declaration uses `sorry` +3524.lean:2:0-2:7: warning: declaration uses `sorry` diff --git a/tests/elab/6090.lean b/tests/elab/6090.lean index f4312077572e..daa5df72d2fd 100644 --- a/tests/elab/6090.lean +++ b/tests/elab/6090.lean @@ -10,7 +10,7 @@ section #guard_msgs in #check @id -- '#print' was unaffected, but throw in a test anyway. /-- -info: def id.{u} : {α : Sort u} → α → α := +info: @[instance_reducible] def id.{u} : {α : Sort u} → α → α := fun {α} a => a -/ #guard_msgs in #print id @@ -23,7 +23,7 @@ set_option pp.raw true #guard_msgs in #check @id -- '#print' was unaffected, but throw in a test anyway. /-- -info: def id.{u} : forall {α : Sort.{u}}, α -> α := +info: @[instance_reducible] def id.{u} : forall {α : Sort.{u}}, α -> α := fun {α : Sort.{u}} (a : α) => a -/ #guard_msgs in #print id diff --git a/tests/elab/async_tcp_half.lean b/tests/elab/async_tcp_half.lean index d17a05f2388a..a5430a14a4d0 100644 --- a/tests/elab/async_tcp_half.lean +++ b/tests/elab/async_tcp_half.lean @@ -20,14 +20,14 @@ def runJoe (addr: SocketAddress) : Async Unit := do client.shutdown def listenClose : IO Unit := do - let addr := SocketAddressV4.mk (.ofParts 127 0 0 1) 8080 + let addr := SocketAddressV4.mk (.ofParts 127 0 0 1) 8787 let server ← TCP.Socket.Server.mk server.bind addr server.listen 128 def acceptClose : IO Unit := do - let addr := SocketAddressV4.mk (.ofParts 127 0 0 1) 8081 + let addr := SocketAddressV4.mk (.ofParts 127 0 0 1) 8781 let server ← TCP.Socket.Server.mk server.bind addr diff --git a/tests/elab/delabMatch.lean b/tests/elab/delabMatch.lean index a03f180b4d78..15274c6dca6d 100644 --- a/tests/elab/delabMatch.lean +++ b/tests/elab/delabMatch.lean @@ -8,7 +8,7 @@ import Lean Basic functionality -/ /-- -info: def Nat.pred : Nat → Nat := +info: @[instance_reducible] def Nat.pred : Nat → Nat := fun x => match x with | 0 => 0 diff --git a/tests/elab/dsimpBackwardDefEqTrace.lean b/tests/elab/dsimpBackwardDefEqTrace.lean index ce193fa5f360..69df00ae4701 100644 --- a/tests/elab/dsimpBackwardDefEqTrace.lean +++ b/tests/elab/dsimpBackwardDefEqTrace.lean @@ -27,7 +27,7 @@ set_option trace.Meta.Tactic.simp.backwardDefEq true in #guard_msgs in example : slow 1 = 1 := by dsimp only [slow_eq] -@[implicit_reducible] def fastApp (f : Nat → Nat) (n : Nat) : Nat := f n +@[instance_reducible] def fastApp (f : Nat → Nat) (n : Nat) : Nat := f n @[defeq] theorem fastApp_eq (f : Nat → Nat) (n : Nat) : fastApp f n = f n := rfl diff --git a/tests/elab/eq_some_iff_get_eq_issue.lean b/tests/elab/eq_some_iff_get_eq_issue.lean index 20961edf86c4..137ff6d35e8a 100644 --- a/tests/elab/eq_some_iff_get_eq_issue.lean +++ b/tests/elab/eq_some_iff_get_eq_issue.lean @@ -3,4 +3,4 @@ namespace Option theorem eq_some_iff_get_eq' {o : Option α} {a : α} : o = some a ↔ ∃ h : o.isSome, Option.get _ h = a := by cases o; simp only [isSome_none, false_iff, reduceCtorEq]; intro h; cases h; contradiction - simp [exists_prop] + simp diff --git a/tests/elab/guessLex.lean b/tests/elab/guessLex.lean index 44df94ae1202..0ec34c883608 100644 --- a/tests/elab/guessLex.lean +++ b/tests/elab/guessLex.lean @@ -198,7 +198,7 @@ end MutualNotNat1 namespace MutualNotNat2 -- A type that is defeq to Nat, but with a different `sizeOf`, checking that the -- inferred argument uses `sizeOf` so that the types of the termination measure aligns. -def OddNat3 := Nat +@[instance_reducible] def OddNat3 := Nat instance : SizeOf OddNat3 := ⟨fun n => 42 - @id Nat n⟩ @[simp] theorem OddNat3.sizeOf_eq (n : OddNat3) : sizeOf n = 42 - @id Nat n := rfl mutual @@ -219,7 +219,7 @@ namespace MutualNotNat3 -- Previously `GuessLex` was inferring the `SizeOf` instance based on the type of the -- *concrete* parameter or argument, which was wrong. -- The inference needs to be based on the parameter type in the function's signature. -def OddNat3 := Nat +@[instance_reducible] def OddNat3 := Nat instance : SizeOf OddNat3 := ⟨fun n => 42 - @id Nat n⟩ @[simp] theorem OddNat3.sizeOf_eq (n : OddNat3) : sizeOf n = 42 - @id Nat n := rfl mutual diff --git a/tests/elab/heapSort.lean b/tests/elab/heapSort.lean index 5b65410eef2e..c6ee72c60d94 100644 --- a/tests/elab/heapSort.lean +++ b/tests/elab/heapSort.lean @@ -81,7 +81,7 @@ instance (lt) : EmptyCollection (BinaryHeap α lt) := ⟨empty _⟩ def singleton (lt) (x : α) : BinaryHeap α lt := ⟨#[x]⟩ /-- `O(1)`. Get the number of elements in a `BinaryHeap`. -/ -def size {lt} (self : BinaryHeap α lt) : Nat := self.1.size +@[instance_reducible] def size {lt} (self : BinaryHeap α lt) : Nat := self.1.size /-- `O(1)`. Get an element in the heap by index. -/ def get {lt} (self : BinaryHeap α lt) (i : Fin self.size) : α := self.1[i]'i.2 diff --git a/tests/elab/implicitReducibilityForDSimprocs.lean b/tests/elab/implicitReducibilityForDSimprocs.lean new file mode 100644 index 000000000000..099c03d0bad8 --- /dev/null +++ b/tests/elab/implicitReducibilityForDSimprocs.lean @@ -0,0 +1,395 @@ +import Lean.Meta.Basic +import Lean.Elab.Tactic.Basic + +syntax (name := Lean.Parser.Tactic.withImplicit) "with_implicit " tacticSeq : tactic + +@[tactic Lean.Parser.Tactic.withImplicit] def evalWithImplicit : Lean.Elab.Tactic.Tactic := fun stx => + Lean.Meta.withImplicit <| Lean.Elab.Tactic.evalTactic stx[1] + +set_option allowUnsafeReducibility true in +attribute [implicit_reducible] + Char.ofNat Char.ofNatAux + UInt32.ofNat UInt32.toNat + UInt64.ofNat UInt64.toNat + BitVec.ofNat BitVec.ofNatLT + Char.toNat + + -- for BitVec + BitVec.abs BitVec.allOnes BitVec.and BitVec.append BitVec.cast BitVec.clz BitVec.clzAuxRec BitVec.cpop BitVec.cpopNatRec BitVec.extractLsb' BitVec.getLsb BitVec.not BitVec.or BitVec.replicate BitVec.rotateLeft BitVec.rotateLeftAux + BitVec.rotateRight BitVec.rotateRightAux BitVec.setWidth BitVec.setWidth' BitVec.shiftLeft BitVec.shiftLeftZeroExtend BitVec.signExtend BitVec.sle BitVec.slt BitVec.smod BitVec.smtSDiv BitVec.smtUDiv BitVec.sshiftRight BitVec.ule + BitVec.ult BitVec.ushiftRight BitVec.xor BitVec.zeroExtend + Bool.toNat + Int.shiftRight + cond + + -- for SInt + BitVec.mul BitVec.add BitVec.sub BitVec.neg + BitVec.smod BitVec.srem BitVec.umod + BitVec.sdiv BitVec.getLsbD BitVec.getMsbD BitVec.msb BitVec.udiv + BitVec.ofInt BitVec.toInt + Int.add Int.neg Int.negOfNat Int.sub Int.subNatNat + Int.toNat Int.natAbs Int.emod + Int.bdiv Int.bmod Int.decEq Int.decNonneg Int.ediv Int.fdiv Int.fmod Int.mul Int.pow Int.tdiv Int.tmod + Int8.mul Int8.add Int8.sub Int8.div Int8.mod Int8.ofIntLE Int8.ofInt Int8.ofUInt8 + Int8.neg Int8.toInt Int8.toNatClampNeg + Int16.mul Int16.add Int16.sub Int16.div Int16.mod Int16.ofIntLE Int16.ofInt Int16.ofUInt16 + Int16.neg Int16.toInt Int16.toNatClampNeg + Int32.mul Int32.add Int32.sub Int32.div Int32.mod Int32.ofIntLE Int32.ofInt Int32.ofUInt32 + Int32.neg Int32.toInt Int32.toNatClampNeg + Int64.mul Int64.add Int64.sub Int64.div Int64.mod Int64.ofIntLE Int64.ofInt Int64.ofUInt64 + Int64.neg Int64.toInt Int64.toNatClampNeg + ISize.mul ISize.add ISize.sub ISize.div ISize.mod + ISize.neg ISize.toInt ISize.toNatClampNeg + + BitVec.add BitVec.decEq BitVec.mul BitVec.sub + UInt8.add UInt8.decEq UInt8.div UInt8.mod UInt8.mul UInt8.ofNat UInt8.ofNatLT UInt8.sub UInt8.toNat + UInt16.add UInt16.decEq UInt16.div UInt16.mod UInt16.mul UInt16.ofNat UInt16.ofNatLT UInt16.sub UInt16.toNat + UInt32.add UInt32.decEq UInt32.div UInt32.mod UInt32.mul UInt32.ofNat UInt32.ofNatLT UInt32.sub UInt32.toNat + UInt64.add UInt64.decEq UInt64.div UInt64.mod UInt64.mul UInt64.ofNat UInt64.ofNatLT UInt64.sub UInt64.toNat + + -- necessary for division + Bool.and Bool.not + Nat.testBit + decide bne + + Array.get!Internal Array.getInternal + List.get + + Array.empty Array.emptyWithCapacity Array.push + Bool.or + ByteArray.append ByteArray.empty ByteArray.emptyWithCapacity ByteArray.push + Char.isAlpha Char.isAlphanum Char.isDigit Char.isLower Char.isUpper Char.isWhitespace Char.ofNat Char.ofNatAux Char.toLower Char.toNat Char.toString Char.toUpper + Fin.add Fin.addNat Fin.castAdd Fin.castLE Fin.castLT Fin.castSucc Fin.div Fin.land Fin.last Fin.lor Fin.mod Fin.mul Fin.natAdd Fin.ofNat Fin.pred Fin.rev Fin.shiftLeft Fin.shiftRight Fin.sub Fin.subNat Fin.succ Fin.xor + List.append List.concat List.flatMap List.flatten List.map List.replicate List.toByteArray List.toByteArray.loop List.utf8Encode + String.append String.decEq String.ofList String.push String.singleton String.utf8EncodeChar + Array.toList ByteArray.get ByteArray.utf8Decode? ByteArray.utf8Decode?.go ByteArray.utf8Decode?.go._unary ByteArray.utf8DecodeChar? ByteArray.utf8DecodeChar?.assemble₁ ByteArray.utf8DecodeChar?.parseFirstByte Char.utf8Size + Option.get String.Internal.toArray String.toList UInt8.land UInt8.toUInt32 WellFounded.Nat.eager WellFounded.Nat.fix WellFounded.Nat.fix.go + +section Array + +example : #[1, 2, 3][1] = 2 := by with_implicit rfl +example : #[1, 2, 3][1]? = some 2 := by with_implicit rfl +example : #[1, 2, 3][1]! = 2 := by with_implicit rfl + +end Array + +section BitVec + +example : - 0#3 = 0#3 := by with_implicit rfl +example : ~~~ 0#3 = -1#3 := by with_implicit rfl +example : BitVec.abs (-1#3) = 1#3 := by with_implicit rfl +example : 3#3 &&& 5#3 = 1#3 := by with_implicit rfl +example : 3#3 ||| 5#3 = 7#3 := by with_implicit rfl +example : 3#3 ^^^ 5#3 = 6#3 := by with_implicit rfl +example : 3#8 + 5#8 = 8#8 := by with_implicit rfl +example : 5#8 - 3#8 = 2#8 := by with_implicit rfl +example : 3#8 * 5#8 = 15#8 := by with_implicit rfl +example : 13#8 / 5#8 = 2#8 := by with_implicit rfl +example : 13#8 % 5#8 = 3#8 := by with_implicit rfl +example : BitVec.udiv 13#8 5#8 = 2#8 := by with_implicit rfl +example : BitVec.umod 13#8 5#8 = 3#8 := by with_implicit rfl +example : BitVec.smtUDiv 13#8 5#8 = 2#8 := by with_implicit rfl +example : BitVec.smod 13#8 5#8 = 3#8 := by with_implicit rfl +example : BitVec.srem 13#8 5#8 = 3#8 := by with_implicit rfl +example : BitVec.sdiv 13#8 5#8 = 2#8 := by with_implicit rfl +example : BitVec.smtSDiv 13#8 5#8 = 2#8 := by with_implicit rfl +example : BitVec.getLsbD 13#8 0 = true := by with_implicit rfl +example : BitVec.getMsbD 13#8 0 = false := by with_implicit rfl +example : BitVec.clz 13#8 = 4#8 := by with_implicit rfl +example : BitVec.cpop 13#8 = 3#8 := by with_implicit rfl +example : (13#8)[0] = true := by with_implicit rfl +example : BitVec.shiftLeft 13#8 1 = 26#8 := by with_implicit rfl +example : BitVec.ushiftRight 13#8 1 = 6#8 := by with_implicit rfl +example : BitVec.sshiftRight 13#8 1 = 6#8 := by with_implicit rfl +example : 13#8 <<< 1 = 26#8 := by with_implicit rfl +example : 13#8 <<< 1#3 = 26#8 := by with_implicit rfl +example : 13#8 >>> 1 = 6#8 := by with_implicit rfl +example : 13#8 >>> 1#3 = 6#8 := by with_implicit rfl +example : BitVec.rotateLeft 13#8 1 = 26#8 := by with_implicit rfl +example : BitVec.rotateRight 13#8 1 = 134#8 := by with_implicit rfl +example : 1#4 ++ 1#4 = 17#8 := by with_implicit rfl +-- TODO: test case for `reduceCast`? +example : (13#8).toNat = 13 := by with_implicit rfl +example : (13#8).toInt = 13 := by with_implicit rfl +example : BitVec.ofInt 8 13 = 13#8 := by with_implicit rfl +example : BitVec.ofNat 8 13 = 13#8 := by with_implicit rfl +example : (13#8 == 12#8) = false := by with_implicit rfl +example : (13#8 != 12#8) = true := by with_implicit rfl +example : BitVec.ult 12#8 13#8 = true := by with_implicit rfl +example : BitVec.ule 12#8 13#8 = true := by with_implicit rfl +example : BitVec.slt (-1#8) (0#8) = true := by with_implicit rfl +example : BitVec.sle (-1#8) (0#8) = true := by with_implicit rfl +example : BitVec.setWidth' (show 2 ≤ 4 by grind) 1#2 = 1#4 := by with_implicit rfl +example : BitVec.shiftLeftZeroExtend 13#8 1 = 26#9 := by with_implicit rfl +example : BitVec.extractLsb' 1 1 13#8 = 0#1 := by with_implicit rfl +example : BitVec.replicate 8 1#1 = 255#8 := by with_implicit rfl +example : BitVec.setWidth 4 13#8 = 13#4 := by with_implicit rfl +example : BitVec.zeroExtend 8 15#4 = 15#8 := by with_implicit rfl +example : BitVec.signExtend 8 15#4 = 255#8 := by with_implicit rfl +example : BitVec.allOnes 8 = 255#8 := by with_implicit rfl +example : BitVec.ofFin (Fin.mk 3 (show 3 < 2 ^ 8 by grind)) = 3#8 := by with_implicit rfl +example : BitVec.toFin 3#8 = Fin.mk 3 (show 3 < 2 ^ 8 by grind) := by with_implicit rfl + +end BitVec + +section Char + +example : 'A'.toLower = 'a' := by with_implicit rfl +example : 'a'.toUpper = 'A' := by with_implicit rfl +example : 'A'.toNat = 65 := by with_implicit rfl +example : ' '.isWhitespace = true := by with_implicit rfl +example : 'A'.isUpper = true := by with_implicit rfl +example : 'a'.isLower = true := by with_implicit rfl +example : 'a'.isAlpha = true := by with_implicit rfl +example : '5'.isDigit = true := by with_implicit rfl +example : '5'.isAlphanum = true := by with_implicit rfl +example : toString 'A' = "A" := by with_implicit rfl +example : 'A'.val = 65 := by with_implicit rfl +example : ('A' == 'B') = false := by with_implicit rfl +example : ('A' != 'B') = true := by with_implicit rfl +example : Char.ofNat 65 = 'A' := by with_implicit rfl +example : Char.ofNatAux 65 (by decide) = 'A' := by with_implicit rfl +example : (default : Char) = 'A' := by with_implicit rfl + +-- This is the `rfl` lemma `Char.toNat_val`. +example (c : Char) : c.val.toNat = c.toNat := by with_implicit rfl + +end Char + +section Fin + +example : (2 : Fin 5).succ = 3 := by with_implicit rfl +example : (2 : Fin 5).rev = 2 := by with_implicit rfl +example : Fin.last 5 = 5 := by with_implicit rfl +example : (2 : Fin 5) + 3 = 0 := by with_implicit rfl +example : (2 : Fin 5) * 3 = 1 := by with_implicit rfl +example : (3 : Fin 5) - 1 = 2 := by with_implicit rfl +example : (4 : Fin 5) / 2 = 2 := by with_implicit rfl +example : (4 : Fin 5) % 3 = 1 := by with_implicit rfl +example : (3 : Fin 8) &&& 5 = 1 := by with_implicit rfl +example : (3 : Fin 8) ||| 5 = 7 := by with_implicit rfl +example : (3 : Fin 8) ^^^ 5 = 6 := by with_implicit rfl +example : (3 : Fin 8) <<< (1 : Fin 8) = 6 := by with_implicit rfl +example : (4 : Fin 8) >>> (1 : Fin 8) = 2 := by with_implicit rfl +example : ((3 : Fin 5) == 3) = true := by with_implicit rfl +example : ((3 : Fin 5) != 4) = true := by with_implicit rfl +example : (3 : Fin 5) = ⟨3, by decide⟩ := by with_implicit rfl +example : (Fin.mk 3 (by decide) : Fin 5) = 3 := by with_implicit rfl +example : Fin.ofNat 5 3 = (3 : Fin 5) := by with_implicit rfl +example : Fin.castSucc (3 : Fin 5) = 3 := by with_implicit rfl +example : Fin.castAdd 3 (2 : Fin 5) = 2 := by with_implicit rfl +example : Fin.addNat (2 : Fin 5) 3 = 5 := by with_implicit rfl +example : Fin.natAdd 3 (2 : Fin 5) = 5 := by with_implicit rfl +example : Fin.castLT (2 : Fin 5) (by decide) = (2 : Fin 3) := by with_implicit rfl +example : Fin.castLE (show 5 ≤ 8 by decide) (2 : Fin 5) = 2 := by with_implicit rfl +example : Fin.subNat 2 (5 : Fin 8) (by decide) = 3 := by with_implicit rfl +example : Fin.pred (3 : Fin 6) (by decide) = 2 := by with_implicit rfl + +end Fin + +section List + +example : List.replicate 3 5 = [5, 5, 5] := by with_implicit rfl + +end List + +section String + +example : "abc" ++ "def" = "abcdef" := by with_implicit rfl +example : String.ofList ['a', 'b', 'c'] = "abc" := by with_implicit rfl +example : "abc".toList = ['a', 'b', 'c'] := by with_implicit rfl +example : "ab".push 'c' = "abc" := by with_implicit rfl +example : String.singleton 'A' = "A" := by with_implicit rfl +example : "A" = String.singleton 'A' := by with_implicit rfl +example : ("A" == "B") = false := by with_implicit rfl +example : ("A" != "B") = true := by with_implicit rfl + +end String + +section Nat + +example : 3 + 5 = 8 := by with_implicit rfl +example : 5 - 3 = 2 := by with_implicit rfl +example : 3 * 5 = 15 := by with_implicit rfl +example : 13 / 5 = 2 := by with_implicit rfl +example : 13 % 5 = 3 := by with_implicit rfl +example : 3 ^ 2 = 9 := by with_implicit rfl +example : 3 &&& 5 = 1 := by with_implicit rfl +example : 3 ||| 5 = 7 := by with_implicit rfl +example : 3 ^^^ 5 = 6 := by with_implicit rfl +example : 3 <<< 1 = 6 := by with_implicit rfl +example : 3 >>> 1 = 1 := by with_implicit rfl +example : Nat.gcd 10 15 = 5 := by with_implicit rfl +example : (13 == 12) = false := by with_implicit rfl +example : (13 != 12) = true := by with_implicit rfl + +end Nat + +section Int + +example : -(-3) = (3 : Int) := by with_implicit rfl +example : 3 + 5 = (8 : Int) := by with_implicit rfl +example : 5 - 3 = (2 : Int) := by with_implicit rfl +example : 3 * 5 = (15 : Int) := by with_implicit rfl +example : 13 / 5 = (2 : Int) := by with_implicit rfl +example : Int.tdiv 13 5 = (2 : Int) := by with_implicit rfl +example : Int.fdiv 13 5 = (2 : Int) := by with_implicit rfl +example : Int.bdiv 13 5 = (3 : Int) := by with_implicit rfl +example : 13 % 5 = (3 : Int) := by with_implicit rfl +example : Int.tmod 13 5 = (3 : Int) := by with_implicit rfl +example : Int.fmod 13 5 = (3 : Int) := by with_implicit rfl +example : Int.bmod 13 5 = (-2 : Int) := by with_implicit rfl +example : 3 ^ 2 = (9 : Int) := by with_implicit rfl +example : ((13 : Int) == 12) = false := by with_implicit rfl +example : ((13 : Int) != 12) = true := by with_implicit rfl +example : Int.natAbs (-5) = 5 := by with_implicit rfl +example : Int.toNat (-5) = 0 := by with_implicit rfl +example : Int.negSucc 2 = -3 := by with_implicit rfl +example : Int.ofNat 3 = 3 := by with_implicit rfl +example : NatCast.natCast 3 = (3 : Int) := by with_implicit rfl +example : Nat.cast 3 = (3 : Int) := by with_implicit rfl + +end Int + +section SInt +/- +`Lean.Meta.Tactic.Simp.BuiltinSimprocs` defines dsimprocs for operations such as `toInt` reductions +arithmetic. +We need to make sure that these are `rfl` at implicit transparency. +-/ +example : Int8.minValue.toInt = - 2 ^ 7 := by with_implicit rfl +example : Int16.minValue.toInt = - 2 ^ 15 := by with_implicit rfl +example : Int32.minValue.toInt = - 2 ^ 31 := by with_implicit rfl +example : Int64.minValue.toInt = - 2 ^ 63 := by with_implicit rfl + +example : 3 * 5 = (15 : Int8) := by with_implicit rfl +example : 3 * 5 = (15 : Int16) := by with_implicit rfl +example : 3 * 5 = (15 : Int32) := by with_implicit rfl +example : 3 * 5 = (15 : Int64) := by with_implicit rfl + +example : 3 + 5 = (8 : Int8) := by with_implicit rfl +example : 3 + 5 = (8 : Int16) := by with_implicit rfl +example : 3 + 5 = (8 : Int32) := by with_implicit rfl +example : 3 + 5 = (8 : Int64) := by with_implicit rfl + +example : 3 - 5 = (-2 : Int8) := by with_implicit rfl +example : 3 - 5 = (-2 : Int16) := by with_implicit rfl +example : 3 - 5 = (-2 : Int32) := by with_implicit rfl +example : 3 - 5 = (-2 : Int64) := by with_implicit rfl + +example : 13 / 5 = (2 : Int8) := by with_implicit rfl +example : 13 / 5 = (2 : Int16) := by with_implicit rfl +example : 13 / 5 = (2 : Int32) := by with_implicit rfl +example : 13 / 5 = (2 : Int64) := by with_implicit rfl + +example : 13 % 5 = (3 : Int8) := by with_implicit rfl +example : 13 % 5 = (3 : Int16) := by with_implicit rfl +example : 13 % 5 = (3 : Int32) := by with_implicit rfl +example : 13 % 5 = (3 : Int64) := by with_implicit rfl + +section +set_option warn.sorry false +example : (13 : Int8) = Int8.ofIntLE 13 sorry sorry := by with_implicit rfl +example : (13 : Int16) = Int16.ofIntLE 13 sorry sorry := by with_implicit rfl +example : (13 : Int32) = Int32.ofIntLE 13 sorry sorry := by with_implicit rfl +example : (13 : Int64) = Int64.ofIntLE 13 sorry sorry := by with_implicit rfl +end + +example : (13 : Int8) = Int8.ofNat 13 := by with_implicit rfl +example : (13 : Int16) = Int16.ofNat 13 := by with_implicit rfl +example : (13 : Int32) = Int32.ofNat 13 := by with_implicit rfl +example : (13 : Int64) = Int64.ofNat 13 := by with_implicit rfl + +example : (13 : Nat) = (13 : Int8).toNatClampNeg := by with_implicit rfl +example : (0 : Nat) = (-13 : Int8).toNatClampNeg := by with_implicit rfl +example : (13 : Nat) = (13 : Int16).toNatClampNeg := by with_implicit rfl +example : (0 : Nat) = (-13 : Int16).toNatClampNeg := by with_implicit rfl +example : (13 : Nat) = (13 : Int32).toNatClampNeg := by with_implicit rfl +example : (0 : Nat) = (-13 : Int32).toNatClampNeg := by with_implicit rfl +example : (13 : Nat) = (13 : Int64).toNatClampNeg := by with_implicit rfl +example : (0 : Nat) = (-13 : Int64).toNatClampNeg := by with_implicit rfl + +example : (-13 : Int8) = Int8.ofInt (-13) := by with_implicit rfl +example : (-13 : Int16) = Int16.ofInt (-13) := by with_implicit rfl +example : (-13 : Int32) = Int32.ofInt (-13) := by with_implicit rfl +example : (-13 : Int64) = Int64.ofInt (-13) := by with_implicit rfl + +example : (-13 : Int) = (-13 : Int8).toInt := by with_implicit rfl +example : (-13 : Int) = (-13 : Int16).toInt := by with_implicit rfl +example : (-13 : Int) = (-13 : Int32).toInt := by with_implicit rfl +example : (-13 : Int) = (-13 : Int64).toInt := by with_implicit rfl + +end SInt + +section UInt + +example : 3 * 5 = (15 : UInt8) := by with_implicit rfl +example : 3 * 5 = (15 : UInt16) := by with_implicit rfl +example : 3 * 5 = (15 : UInt32) := by with_implicit rfl +example : 3 * 5 = (15 : UInt64) := by with_implicit rfl + +example : 3 + 5 = (8 : UInt8) := by with_implicit rfl +example : 3 + 5 = (8 : UInt16) := by with_implicit rfl +example : 3 + 5 = (8 : UInt32) := by with_implicit rfl +example : 3 + 5 = (8 : UInt64) := by with_implicit rfl + +example : 5 - 3 = (2 : UInt8) := by with_implicit rfl +example : 5 - 3 = (2 : UInt16) := by with_implicit rfl +example : 5 - 3 = (2 : UInt32) := by with_implicit rfl +example : 5 - 3 = (2 : UInt64) := by with_implicit rfl + +example : 13 / 5 = (2 : UInt8) := by with_implicit rfl +example : 13 / 5 = (2 : UInt16) := by with_implicit rfl +example : 13 / 5 = (2 : UInt32) := by with_implicit rfl +example : 13 / 5 = (2 : UInt64) := by with_implicit rfl + +example : 13 % 5 = (3 : UInt8) := by with_implicit rfl +example : 13 % 5 = (3 : UInt16) := by with_implicit rfl +example : 13 % 5 = (3 : UInt32) := by with_implicit rfl +example : 13 % 5 = (3 : UInt64) := by with_implicit rfl + +example : (13 : UInt8) = UInt8.ofNat 13 := by with_implicit rfl +example : (13 : UInt16) = UInt16.ofNat 13 := by with_implicit rfl +example : (13 : UInt32) = UInt32.ofNat 13 := by with_implicit rfl +example : (13 : UInt64) = UInt64.ofNat 13 := by with_implicit rfl + +example : (13 : Nat) = (13 : UInt8).toNat := by with_implicit rfl +example : (13 : Nat) = (13 : UInt16).toNat := by with_implicit rfl +example : (13 : Nat) = (13 : UInt32).toNat := by with_implicit rfl +example : (13 : Nat) = (13 : UInt64).toNat := by with_implicit rfl + +example : ((13 : UInt8) == 12) = false := by with_implicit rfl +example : ((13 : UInt8) != 12) = true := by with_implicit rfl +example : ((13 : UInt16) == 12) = false := by with_implicit rfl +example : ((13 : UInt16) != 12) = true := by with_implicit rfl +example : ((13 : UInt32) == 12) = false := by with_implicit rfl +example : ((13 : UInt32) != 12) = true := by with_implicit rfl +example : ((13 : UInt64) == 12) = false := by with_implicit rfl +example : ((13 : UInt64) != 12) = true := by with_implicit rfl + +section +set_option warn.sorry false +example : UInt8.ofNatLT 13 sorry = 13 := by with_implicit rfl +example : UInt16.ofNatLT 13 sorry = 13 := by with_implicit rfl +example : UInt32.ofNatLT 13 sorry = 13 := by with_implicit rfl +example : UInt64.ofNatLT 13 sorry = 13 := by with_implicit rfl +end + +example : UInt8.ofNat 13 = 13 := by with_implicit rfl +example : UInt16.ofNat 13 = 13 := by with_implicit rfl +example : UInt32.ofNat 13 = 13 := by with_implicit rfl +example : UInt64.ofNat 13 = 13 := by with_implicit rfl + +example : UInt8.toNat 13 = 13 := by with_implicit rfl +example : UInt16.toNat 13 = 13 := by with_implicit rfl +example : UInt32.toNat 13 = 13 := by with_implicit rfl +example : UInt64.toNat 13 = 13 := by with_implicit rfl + +end UInt + +theorem toLower_eq_of_not_isUpper {c : Char} (h : ¬ c.isUpper) : c.toLower = c := by + -- squashed: simp_all [isUpper, UInt32.le_iff_toNat_le, toLower] + simp_all only [Char.isUpper, ↓Char.isValue, Char.reduceVal, ge_iff_le, UInt32.le_iff_toNat_le, + UInt32.reduceToNat, Char.toNat_val, Bool.decide_and, Bool.and_eq_true, decide_eq_true_eq, not_and, + Nat.not_le, Char.toLower, UInt32.reduceSub, dite_eq_right_iff] + omega diff --git a/tests/elab/ind_whnf.lean b/tests/elab/ind_whnf.lean index 21ba1c557639..c44843a3cd56 100644 --- a/tests/elab/ind_whnf.lean +++ b/tests/elab/ind_whnf.lean @@ -1,4 +1,6 @@ -inductive Expr : id Type +abbrev id' (α : Sort u) := α + +inductive Expr : id' Type | var : Nat → Expr | app : String → List Expr → Expr diff --git a/tests/elab/inferInstanceAs2.lean b/tests/elab/inferInstanceAs2.lean new file mode 100644 index 000000000000..2b417f1bdb0d --- /dev/null +++ b/tests/elab/inferInstanceAs2.lean @@ -0,0 +1,39 @@ +/-! +Tests for `inferInstanceAs` against expected types whose explicit arguments wrap a +non-reducible defined type (`Zmod n` here, which unfolds to `Nat ⧸ n`). User-placed +`_` placeholders in the `inferInstanceAs` type argument must be resolved by matching +against the expected type without getting blocked by the `.instances` transparency +cap on synthetic instance metavariables. +-/ + +class HasQuotient (A : outParam <| Type u) (B : Type v) where + Quotient (A) : B → Type max u v + +notation:35 G " ⧸ " H:34 => HasQuotient.Quotient G H + +class Foo (α : Type) [Neg α] where + +instance {n : Nat} : Foo (Fin n) where + +instance : HasQuotient Nat Nat where + Quotient n := Fin n + +instance {n : Nat} : Neg (Nat ⧸ n) := + inferInstanceAs <| Neg (Fin n) + +instance {n : Nat} : Foo (Nat ⧸ n) := + inferInstanceAs <| Foo (Fin n) + +def Zmod (n : Nat) := + Nat ⧸ n +deriving Neg + +instance {n : Nat} : Foo (Zmod n) := + inferInstanceAs <| Foo (_ ⧸ _) + +instance {n : Nat} : Foo (Zmod n) := + inferInstanceAs <| Foo (Nat ⧸ n) + +set_option backward.isDefEq.respectTransparency.instances false in +instance {n : Nat} : Foo (Zmod n) := + inferInstanceAs <| Foo (_ ⧸ _) diff --git a/tests/elab/irredoutparam.lean b/tests/elab/irredoutparam.lean new file mode 100644 index 000000000000..a82e11569a6e --- /dev/null +++ b/tests/elab/irredoutparam.lean @@ -0,0 +1,15 @@ +class Foo (α : Type) (β : outParam Type) where + +def Bar := + Nat + +instance : Foo Nat Nat where + +/-- +error: failed to synthesize + Foo Nat Bar + +Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command. +-/ +#guard_msgs in +#synth Foo Nat Bar -- instFooNat diff --git a/tests/elab/isDefEqCheckAssignmentBug.lean.out.expected b/tests/elab/isDefEqCheckAssignmentBug.lean.out.expected index 2fd0b5e7b8f9..6561fcfe88e4 100644 --- a/tests/elab/isDefEqCheckAssignmentBug.lean.out.expected +++ b/tests/elab/isDefEqCheckAssignmentBug.lean.out.expected @@ -24,12 +24,13 @@ (StateRefT' IO.RealWorld Elab.Command.State (EIO Exception)) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) [Meta.isDefEq] ❌️ Elab.Command.Context =?= Context - [Meta.isDefEq.onFailure] ❌️ ReaderT Elab.Command.Context - (StateRefT' IO.RealWorld Elab.Command.State - (EIO Exception)) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) - [Meta.isDefEq.onFailure] ❌️ ReaderT Elab.Command.Context - (StateRefT' IO.RealWorld Elab.Command.State - (EIO Exception)) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) + [Meta.isDefEq] ❌️ fun α => + Elab.Command.Context → + StateRefT' IO.RealWorld Elab.Command.State (EIO Exception) + α =?= fun α => Context → StateRefT' IO.RealWorld State CoreM α + [Meta.isDefEq] ✅️ Type =?= Type + [Meta.isDefEq] ❌️ Elab.Command.Context =?= Context + [Meta.isDefEq] ❌️ Elab.Command.Context =?= Context [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM Elab.Command.CommandElabM =?= MonadEvalT ?m ?m [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM Elab.Command.CommandElabM =?= MonadEvalT ?m ?m [Meta.isDefEq] ✅️ MonadEvalT MetaM Elab.Command.CommandElabM =?= MonadEvalT ?m ?m @@ -79,10 +80,13 @@ [Meta.isDefEq] ❌️ ReaderT Elab.Term.Context (StateRefT' IO.RealWorld Elab.Term.State MetaM) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) [Meta.isDefEq] ❌️ Elab.Term.Context =?= Context - [Meta.isDefEq.onFailure] ❌️ ReaderT Elab.Term.Context - (StateRefT' IO.RealWorld Elab.Term.State MetaM) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) - [Meta.isDefEq.onFailure] ❌️ ReaderT Elab.Term.Context - (StateRefT' IO.RealWorld Elab.Term.State MetaM) =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) + [Meta.isDefEq] ❌️ fun α => + Elab.Term.Context → + StateRefT' IO.RealWorld Elab.Term.State MetaM + α =?= fun α => Context → StateRefT' IO.RealWorld State CoreM α + [Meta.isDefEq] ✅️ Type =?= Type + [Meta.isDefEq] ❌️ Elab.Term.Context =?= Context + [Meta.isDefEq] ❌️ Elab.Term.Context =?= Context [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM Elab.TermElabM =?= MonadEvalT ?m ?m [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM Elab.TermElabM =?= MonadEvalT ?m ?m [Meta.isDefEq] ✅️ MonadEvalT MetaM Elab.TermElabM =?= MonadEvalT ?m ?m @@ -177,11 +181,21 @@ [Meta.isDefEq] ❌️ StateRefT' IO.RealWorld Elab.Term.State MetaM =?= MetaM [Meta.isDefEq] ❌️ StateRefT' IO.RealWorld Elab.Term.State MetaM =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) - [Meta.isDefEq] ❌️ StateRefT' =?= ReaderT - [Meta.isDefEq.onFailure] ❌️ StateRefT' IO.RealWorld Elab.Term.State - MetaM =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) - [Meta.isDefEq.onFailure] ❌️ StateRefT' IO.RealWorld Elab.Term.State - MetaM =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) + [Meta.isDefEq] ❌️ fun α => + ReaderT (ST.Ref IO.RealWorld Elab.Term.State) MetaM + α =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) + [Meta.isDefEq] ❌️ fun α => + ReaderT (ST.Ref IO.RealWorld Elab.Term.State) MetaM + α =?= fun α => ReaderT Context (StateRefT' IO.RealWorld State CoreM) α + [Meta.isDefEq] ✅️ Type =?= Type + [Meta.isDefEq] ❌️ ReaderT (ST.Ref IO.RealWorld Elab.Term.State) MetaM + α =?= ReaderT Context (StateRefT' IO.RealWorld State CoreM) α + [Meta.isDefEq] ❌️ ST.Ref IO.RealWorld Elab.Term.State =?= Context + [Meta.isDefEq.onFailure] ❌️ ST.Ref IO.RealWorld Elab.Term.State =?= Context + [Meta.isDefEq] ❌️ ST.Ref IO.RealWorld Elab.Term.State → + MetaM α =?= Context → StateRefT' IO.RealWorld State CoreM α + [Meta.isDefEq] ❌️ ST.Ref IO.RealWorld Elab.Term.State =?= Context + [Meta.isDefEq] ❌️ ST.Ref IO.RealWorld Elab.Term.State =?= Context [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM (StateRefT' IO.RealWorld Elab.Term.State MetaM) =?= MonadEvalT ?m ?m [Meta.isDefEq.onFailure] ❌️ MonadEvalT MetaM diff --git a/tests/elab/issue11450.lean b/tests/elab/issue11450.lean index 85131ed22d5a..54ddc005691c 100644 --- a/tests/elab/issue11450.lean +++ b/tests/elab/issue11450.lean @@ -22,8 +22,7 @@ info: @[reducible] def Term.var.noConfusion.{u} : {L : Nat → Type} → #guard_msgs in #print sig Term.var.noConfusion - -def Vector' (α : Type u) (n : Nat) := +abbrev Vector' (α : Type u) (n : Nat) := { l : List α // l.length = n } inductive HVect : (n : Nat) -> (Vector' (Type v) n) -> Type (v+1) where diff --git a/tests/elab/krivine.lean b/tests/elab/krivine.lean index 4ff5785dd024..49c9f513da6e 100644 --- a/tests/elab/krivine.lean +++ b/tests/elab/krivine.lean @@ -8,6 +8,7 @@ inductive KrivineClosure namespace Ex1 +@[instance_reducible] def KrivineEnv := List KrivineClosure -- We need to define a `SizeOf` instance for `KrivineEnv`. Otherwise, we cannot use the auto-generated well-founded relation in diff --git a/tests/elab/partial_fixpoint_probability.lean b/tests/elab/partial_fixpoint_probability.lean index 8ff412d0e804..7c90b9f26d4c 100644 --- a/tests/elab/partial_fixpoint_probability.lean +++ b/tests/elab/partial_fixpoint_probability.lean @@ -46,6 +46,7 @@ end /-- Distributions (not normalized, which is curcial, else we don't have ⊥.) -/ +@[instance_reducible] def Distr (α : Type) : Type := α → ENNReal noncomputable def Distr.join : Distr (Distr α) → Distr α := fun dd x => diff --git a/tests/elab/print_cmd.lean b/tests/elab/print_cmd.lean index 24d0a25cbe94..04e8d370e2fe 100644 --- a/tests/elab/print_cmd.lean +++ b/tests/elab/print_cmd.lean @@ -5,7 +5,7 @@ private def foo (x : Nat) : Nat := x + 1 /-- info: hello -/ #guard_msgs in #print "hello" /-- -info: def id.{u} : {α : Sort u} → α → α := +info: @[instance_reducible] def id.{u} : {α : Sort u} → α → α := fun {α} a => a -/ #guard_msgs in #print id diff --git a/tests/elab/renaming.lean b/tests/elab/renaming.lean index 4534517ed6f7..efea182740ac 100644 --- a/tests/elab/renaming.lean +++ b/tests/elab/renaming.lean @@ -4,7 +4,7 @@ inductive Ty | base | arr (a b : Ty) -def Cxt := List Ty +@[instance_reducible] def Cxt := List Ty inductive Var : (g : Cxt) → (a : Ty) → Type | vz {g a} : Var (a :: g) a diff --git a/tests/elab/set.lean b/tests/elab/set.lean index c1238693617a..6fc6abb4d97a 100644 --- a/tests/elab/set.lean +++ b/tests/elab/set.lean @@ -1,4 +1,4 @@ -def Set (α : Type u) := α → Prop +abbrev Set (α : Type u) := α → Prop def Set.in (s : Set α) (a : α) := s a notation:50 a " ∈ " s:50 => Set.in s a diff --git a/tests/elab/slice.lean b/tests/elab/slice.lean index d06c44075a64..ca4b8965b425 100644 --- a/tests/elab/slice.lean +++ b/tests/elab/slice.lean @@ -47,6 +47,7 @@ example : #[1, 2, 3, 4, 5][1...*][*...2].toList = [2, 3] := by simp example : #[1, 2, 3, 4, 5][1...*][*...=2].toList = [2, 3, 4] := by simp example : #[1, 2, 3, 4, 5][1...*][*...*].toList = [2, 3, 4, 5] := by simp example : #[1, 2, 3][0...2][*...*].toList = [1, 2] := by simp + example : #[1, 2, 3][0...2][1...2].toArray = #[2] := by simp example : #[1, 2, 3][0...2][1...5].toArray = #[2] := by simp example : #[1, 2, 3][1...2][0...2].toArray = #[2] := by simp diff --git a/tests/elab/splitImplicitReducible.lean b/tests/elab/splitImplicitReducible.lean index 1e0def48670e..dabf5e926430 100644 --- a/tests/elab/splitImplicitReducible.lean +++ b/tests/elab/splitImplicitReducible.lean @@ -26,10 +26,10 @@ instance instFoo : Foo := ⟨42⟩ /-! ## `@[implicit_reducible]` is preserved (no longer aliased to `instance_reducible`). -/ -@[implicit_reducible] def myAdd : Nat → Nat → Nat +@[instance_reducible] def myAdd : Nat → Nat → Nat | a, b => a + b -/-- info: @[implicit_reducible] def myAdd : Nat → Nat → Nat -/ +/-- info: @[instance_reducible] def myAdd : Nat → Nat → Nat -/ #guard_msgs in #print sig myAdd @@ -52,7 +52,7 @@ during implicit-arg defeq. -/ attribute [implicit_reducible] upgradeMe -/-- info: @[implicit_reducible] def upgradeMe : Nat → Nat -/ +/-- info: @[instance_reducible] def upgradeMe : Nat → Nat -/ #guard_msgs in #print sig upgradeMe @@ -70,7 +70,7 @@ def noAttr : Foo := ⟨42⟩ @[instance_reducible] def withInstanceReducible : Foo := ⟨42⟩ #guard_msgs in -@[implicit_reducible] def withImplicitReducible : Foo := ⟨42⟩ +@[instance_reducible] def withImplicitReducible : Foo := ⟨42⟩ /-! ## Sanity: instance-tier behavior continues to work. -/ diff --git a/tests/elab/sym_pattern_3.lean b/tests/elab/sym_pattern_3.lean index 504c223f71ad..cc841f192ec3 100644 --- a/tests/elab/sym_pattern_3.lean +++ b/tests/elab/sym_pattern_3.lean @@ -14,7 +14,6 @@ theorem Exec.bind (k₁ : M α) (k₂ : α → M β) (post : β → S → Prop) Exec s k₁ (fun a s₁ => Exec s₁ (k₂ a) post) → Exec s (k₁ >>= k₂) post := by simp [Exec, Bind.bind, StateT.bind] - cases k₁ s; simp def goal := ∀ a b, Exec b (set a >>= fun _ => get) fun v _ => v = a set_option pp.explicit true diff --git a/tests/elab/symbolFrequency_foldRelevantConsts.lean b/tests/elab/symbolFrequency_foldRelevantConsts.lean index d4d14adac082..3a109ad612af 100644 --- a/tests/elab/symbolFrequency_foldRelevantConsts.lean +++ b/tests/elab/symbolFrequency_foldRelevantConsts.lean @@ -19,7 +19,7 @@ run_meta do let consts ← ci.type.foldRelevantConstants (init := #[]) (fun n ns => return ns.push n) logInfo m!"{consts}" -/-- info: [Array, Nat, LT.lt, HAdd.hAdd, OfNat.ofNat, Array.swap, Not] -/ +/-- info: [Array, Nat, LT.lt, HAdd.hAdd, OfNat.ofNat, Array.swap] -/ #guard_msgs in run_meta do let ci ← getConstInfo `Array.eraseIdx.induct diff --git a/tests/elab/wfirred.lean b/tests/elab/wfirred.lean index 41184d270bcb..f32d0e1bb421 100644 --- a/tests/elab/wfirred.lean +++ b/tests/elab/wfirred.lean @@ -123,11 +123,11 @@ termination_by n m => (n, m) #guard_msgs in #print sig baz -@[implicit_reducible] def qux : Nat → Nat → Nat +@[instance_reducible] def qux : Nat → Nat → Nat | 0, m => m | n+1, m => qux n (m + n) termination_by n m => (n, m) -/-- info: @[implicit_reducible] def qux : Nat → Nat → Nat -/ +/-- info: @[instance_reducible] def qux : Nat → Nat → Nat -/ #guard_msgs in #print sig qux diff --git a/tests/elab_bench/cbv_aes.lean b/tests/elab_bench/cbv_aes.lean index 417c6281552c..2c3b026b5a24 100644 --- a/tests/elab_bench/cbv_aes.lean +++ b/tests/elab_bench/cbv_aes.lean @@ -279,6 +279,7 @@ namespace AESArm open BitVec def WordSize := 32 +@[instance_reducible] def BlockSize := 128 def Rcon : List (BitVec WordSize) := @@ -306,6 +307,7 @@ structure KBR where h : block_size = BlockSize deriving DecidableEq, Repr +@[instance_reducible] def AES128KBR : KBR := {key_len := 128, block_size := BlockSize, Nr := 10, h := by decide} def AES192KBR : KBR := diff --git a/tests/elab_fail/simp_trace.lean.out.expected b/tests/elab_fail/simp_trace.lean.out.expected index 1392a09d93a1..cd717661d616 100644 --- a/tests/elab_fail/simp_trace.lean.out.expected +++ b/tests/elab_fail/simp_trace.lean.out.expected @@ -43,7 +43,7 @@ Try this: simp only [g, pure] [Meta.Tactic.simp.rewrite] unfold g, g x ==> (have x := x; pure x).run Try this: simp (config := { unfoldPartialApp := true }) only [f1, modify, modifyGet, MonadStateOf.modifyGet, - StateT.modifyGet, pure, f2, bind, StateT.bind, get, getThe, MonadStateOf.get, StateT.get, set, StateT.set] + StateT.modifyGet, pure, f2, bind, StateT.bind, set, StateT.set, StateT.get] [Meta.Tactic.simp.rewrite] unfold f1, f1 ==> modify fun x => g x [Meta.Tactic.simp.rewrite] unfold modify, modify fun x => g x ==> modifyGet fun s => (PUnit.unit, (fun x => g x) s) [Meta.Tactic.simp.rewrite] unfold StateT.modifyGet, StateT.modifyGet fun s => @@ -55,9 +55,9 @@ Try this: simp (config := { unfoldPartialApp := true }) only [f1, modify, modify let __x ← get s match __x with | (a, s) => (fun s => set (g s)) a s -[Meta.Tactic.simp.rewrite] unfold getThe, getThe Nat s ==> MonadStateOf.get s +[Meta.Tactic.simp.rewrite] unfold StateT.set, StateT.set (g (StateT.get s).fst) + (StateT.get s).snd ==> pure (PUnit.unit, g (StateT.get s).fst) [Meta.Tactic.simp.rewrite] unfold StateT.get, StateT.get s ==> pure (s, s) -[Meta.Tactic.simp.rewrite] unfold StateT.set, StateT.set (g s) s ==> pure (PUnit.unit, g s) [Meta.Tactic.simp.rewrite] eq_self:1000: (fun s => (PUnit.unit, g s)) = fun s => (PUnit.unit, g s) ==>