From ea221f3283fef1a883b1e0be78295a4a49a92d23 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 22 Nov 2024 14:05:51 +1100 Subject: [PATCH] feat: `Nat.(fold|foldRev|any|all)M?` take a function which sees the upper bound (#6139) This PR modifies the signature of the functions `Nat.fold`, `Nat.foldRev`, `Nat.any`, `Nat.all`, so that the function is passed the upper bound. This allows us to change runtime array bounds checks to compile time checks in many places. --- src/Init/Data/Array/Basic.lean | 2 +- src/Init/Data/Array/Lemmas.lean | 23 ++- src/Init/Data/Nat.lean | 1 + src/Init/Data/Nat/Basic.lean | 101 ----------- src/Init/Data/Nat/Control.lean | 69 +++---- src/Init/Data/Nat/Fold.lean | 168 ++++++++++++++++++ src/Lean/Compiler/IR/Borrow.lean | 8 +- src/Lean/Compiler/IR/Boxing.lean | 4 +- src/Lean/Compiler/IR/ElimDeadBranches.lean | 14 +- src/Lean/Compiler/IR/EmitC.lean | 86 ++++----- src/Lean/Compiler/IR/EmitLLVM.lean | 10 +- src/Lean/Compiler/IR/ExpandResetReuse.lean | 6 +- src/Lean/Compiler/IR/RC.lean | 18 +- src/Lean/Compiler/LCNF/ElimDeadBranches.lean | 6 +- src/Lean/Compiler/LCNF/InferType.lean | 4 +- src/Lean/Data/PersistentArray.lean | 3 +- src/Lean/Elab/App.lean | 4 +- src/Lean/Elab/MutualDef.lean | 8 +- src/Lean/LocalContext.lean | 6 +- src/Lean/Meta/Basic.lean | 2 +- src/Lean/Meta/Closure.lean | 4 +- src/Lean/Meta/LazyDiscrTree.lean | 4 +- src/Lean/Meta/Match/Match.lean | 2 +- src/Lean/Meta/Match/MatcherApp/Transform.lean | 8 +- src/Lean/Meta/Tactic/Apply.lean | 4 +- src/Lean/Meta/Tactic/Cases.lean | 2 +- src/Lean/Meta/Tactic/FunInd.lean | 4 +- src/Lean/Meta/Tactic/Induction.lean | 8 +- src/Lean/Meta/Tactic/Subst.lean | 4 +- src/Lean/MetavarContext.lean | 18 +- src/Lean/PrettyPrinter/Formatter.lean | 4 +- src/Lean/PrettyPrinter/Parenthesizer.lean | 6 +- tests/bench/qsort.lean | 4 +- tests/compiler/phashmap.lean | 18 +- tests/compiler/phashmap2.lean | 8 +- tests/compiler/phashmap3.lean | 8 +- tests/compiler/rbmap_library.lean | 2 +- tests/lean/IRbug.lean | 2 +- tests/lean/Reformat.lean | 2 +- tests/lean/ref1.lean | 6 +- .../lean/run/unexpected_result_with_bind.lean | 2 +- 41 files changed, 372 insertions(+), 291 deletions(-) create mode 100644 src/Init/Data/Nat/Fold.lean diff --git a/src/Init/Data/Array/Basic.lean b/src/Init/Data/Array/Basic.lean index cdda587895..3880183ce6 100644 --- a/src/Init/Data/Array/Basic.lean +++ b/src/Init/Data/Array/Basic.lean @@ -233,7 +233,7 @@ def ofFn {n} (f : Fin n → α) : Array α := go 0 (mkEmpty n) where /-- The array `#[0, 1, ..., n - 1]`. -/ def range (n : Nat) : Array Nat := - n.fold (flip Array.push) (mkEmpty n) + ofFn fun (i : Fin n) => i def singleton (v : α) : Array α := mkArray 1 v diff --git a/src/Init/Data/Array/Lemmas.lean b/src/Init/Data/Array/Lemmas.lean index a7819b1b29..abd28060cd 100644 --- a/src/Init/Data/Array/Lemmas.lean +++ b/src/Init/Data/Array/Lemmas.lean @@ -621,6 +621,19 @@ theorem getElem?_ofFn (f : Fin n → α) (i : Nat) : (ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := by simp [getElem?_def] +@[simp] theorem ofFn_zero (f : Fin 0 → α) : ofFn f = #[] := rfl + +theorem ofFn_succ (f : Fin (n+1) → α) : + ofFn f = (ofFn (fun (i : Fin n) => f i.castSucc)).push (f ⟨n, by omega⟩) := by + ext i h₁ h₂ + · simp + · simp [getElem_push] + split <;> rename_i h₃ + · rfl + · congr + simp at h₁ h₂ + omega + /-! # mkArray -/ @[simp] theorem size_mkArray (n : Nat) (v : α) : (mkArray n v).size = n := @@ -840,16 +853,10 @@ theorem size_eq_length_toList (as : Array α) : as.size = as.toList.length := rf simp only [reverse]; split <;> simp [go] @[simp] theorem size_range {n : Nat} : (range n).size = n := by - unfold range - induction n with - | zero => simp [Nat.fold] - | succ k ih => - rw [Nat.fold, flip] - simp only [mkEmpty_eq, size_push] at * - omega + induction n <;> simp [range] @[simp] theorem toList_range (n : Nat) : (range n).toList = List.range n := by - induction n <;> simp_all [range, Nat.fold, flip, List.range_succ] + apply List.ext_getElem <;> simp [range] @[simp] theorem getElem_range {n : Nat} {x : Nat} (h : x < (Array.range n).size) : (Array.range n)[x] = x := by diff --git a/src/Init/Data/Nat.lean b/src/Init/Data/Nat.lean index 5f602ccd59..6ce784e109 100644 --- a/src/Init/Data/Nat.lean +++ b/src/Init/Data/Nat.lean @@ -20,3 +20,4 @@ import Init.Data.Nat.Mod import Init.Data.Nat.Lcm import Init.Data.Nat.Compare import Init.Data.Nat.Simproc +import Init.Data.Nat.Fold diff --git a/src/Init/Data/Nat/Basic.lean b/src/Init/Data/Nat/Basic.lean index ea2c6253c7..5b7d9d5542 100644 --- a/src/Init/Data/Nat/Basic.lean +++ b/src/Init/Data/Nat/Basic.lean @@ -35,52 +35,6 @@ Used as the default `Nat` eliminator by the `cases` tactic. -/ protected abbrev casesAuxOn {motive : Nat → Sort u} (t : Nat) (zero : motive 0) (succ : (n : Nat) → motive (n + 1)) : motive t := Nat.casesOn t zero succ -/-- -`Nat.fold` evaluates `f` on the numbers up to `n` exclusive, in increasing order: -* `Nat.fold f 3 init = init |> f 0 |> f 1 |> f 2` --/ -@[specialize] def fold {α : Type u} (f : Nat → α → α) : (n : Nat) → (init : α) → α - | 0, a => a - | succ n, a => f n (fold f n a) - -/-- Tail-recursive version of `Nat.fold`. -/ -@[inline] def foldTR {α : Type u} (f : Nat → α → α) (n : Nat) (init : α) : α := - let rec @[specialize] loop - | 0, a => a - | succ m, a => loop m (f (n - succ m) a) - loop n init - -/-- -`Nat.foldRev` evaluates `f` on the numbers up to `n` exclusive, in decreasing order: -* `Nat.foldRev f 3 init = f 0 <| f 1 <| f 2 <| init` --/ -@[specialize] def foldRev {α : Type u} (f : Nat → α → α) : (n : Nat) → (init : α) → α - | 0, a => a - | succ n, a => foldRev f n (f n a) - -/-- `any f n = true` iff there is `i in [0, n-1]` s.t. `f i = true` -/ -@[specialize] def any (f : Nat → Bool) : Nat → Bool - | 0 => false - | succ n => any f n || f n - -/-- Tail-recursive version of `Nat.any`. -/ -@[inline] def anyTR (f : Nat → Bool) (n : Nat) : Bool := - let rec @[specialize] loop : Nat → Bool - | 0 => false - | succ m => f (n - succ m) || loop m - loop n - -/-- `all f n = true` iff every `i in [0, n-1]` satisfies `f i = true` -/ -@[specialize] def all (f : Nat → Bool) : Nat → Bool - | 0 => true - | succ n => all f n && f n - -/-- Tail-recursive version of `Nat.all`. -/ -@[inline] def allTR (f : Nat → Bool) (n : Nat) : Bool := - let rec @[specialize] loop : Nat → Bool - | 0 => true - | succ m => f (n - succ m) && loop m - loop n /-- `Nat.repeat f n a` is `f^(n) a`; that is, it iterates `f` `n` times on `a`. @@ -1158,33 +1112,6 @@ theorem not_lt_eq (a b : Nat) : (¬ (a < b)) = (b ≤ a) := theorem not_gt_eq (a b : Nat) : (¬ (a > b)) = (a ≤ b) := not_lt_eq b a -/-! # csimp theorems -/ - -@[csimp] theorem fold_eq_foldTR : @fold = @foldTR := - funext fun α => funext fun f => funext fun n => funext fun init => - let rec go : ∀ m n, foldTR.loop f (m + n) m (fold f n init) = fold f (m + n) init - | 0, n => by simp [foldTR.loop] - | succ m, n => by rw [foldTR.loop, add_sub_self_left, succ_add]; exact go m (succ n) - (go n 0).symm - -@[csimp] theorem any_eq_anyTR : @any = @anyTR := - funext fun f => funext fun n => - let rec go : ∀ m n, (any f n || anyTR.loop f (m + n) m) = any f (m + n) - | 0, n => by simp [anyTR.loop] - | succ m, n => by - rw [anyTR.loop, add_sub_self_left, ← Bool.or_assoc, succ_add] - exact go m (succ n) - (go n 0).symm - -@[csimp] theorem all_eq_allTR : @all = @allTR := - funext fun f => funext fun n => - let rec go : ∀ m n, (all f n && allTR.loop f (m + n) m) = all f (m + n) - | 0, n => by simp [allTR.loop] - | succ m, n => by - rw [allTR.loop, add_sub_self_left, ← Bool.and_assoc, succ_add] - exact go m (succ n) - (go n 0).symm - @[csimp] theorem repeat_eq_repeatTR : @repeat = @repeatTR := funext fun α => funext fun f => funext fun n => funext fun init => let rec go : ∀ m n, repeatTR.loop f m (repeat f n init) = repeat f (m + n) init @@ -1193,31 +1120,3 @@ theorem not_gt_eq (a b : Nat) : (¬ (a > b)) = (a ≤ b) := (go n 0).symm end Nat - -namespace Prod - -/-- -`(start, stop).foldI f a` evaluates `f` on all the numbers -from `start` (inclusive) to `stop` (exclusive) in increasing order: -* `(5, 8).foldI f init = init |> f 5 |> f 6 |> f 7` --/ -@[inline] def foldI {α : Type u} (f : Nat → α → α) (i : Nat × Nat) (a : α) : α := - Nat.foldTR.loop f i.2 (i.2 - i.1) a - -/-- -`(start, stop).anyI f a` returns true if `f` is true for some natural number -from `start` (inclusive) to `stop` (exclusive): -* `(5, 8).anyI f = f 5 || f 6 || f 7` --/ -@[inline] def anyI (f : Nat → Bool) (i : Nat × Nat) : Bool := - Nat.anyTR.loop f i.2 (i.2 - i.1) - -/-- -`(start, stop).allI f a` returns true if `f` is true for all natural numbers -from `start` (inclusive) to `stop` (exclusive): -* `(5, 8).anyI f = f 5 && f 6 && f 7` --/ -@[inline] def allI (f : Nat → Bool) (i : Nat × Nat) : Bool := - Nat.allTR.loop f i.2 (i.2 - i.1) - -end Prod diff --git a/src/Init/Data/Nat/Control.lean b/src/Init/Data/Nat/Control.lean index 2c6adb8e2c..a0928496c5 100644 --- a/src/Init/Data/Nat/Control.lean +++ b/src/Init/Data/Nat/Control.lean @@ -6,50 +6,51 @@ Author: Leonardo de Moura prelude import Init.Control.Basic import Init.Data.Nat.Basic +import Init.Omega namespace Nat universe u v -@[inline] def forM {m} [Monad m] (n : Nat) (f : Nat → m Unit) : m Unit := - let rec @[specialize] loop - | 0 => pure () - | i+1 => do f (n-i-1); loop i - loop n +@[inline] def forM {m} [Monad m] (n : Nat) (f : (i : Nat) → i < n → m Unit) : m Unit := + let rec @[specialize] loop : ∀ i, i ≤ n → m Unit + | 0, _ => pure () + | i+1, h => do f (n-i-1) (by omega); loop i (Nat.le_of_succ_le h) + loop n (by simp) -@[inline] def forRevM {m} [Monad m] (n : Nat) (f : Nat → m Unit) : m Unit := - let rec @[specialize] loop - | 0 => pure () - | i+1 => do f i; loop i - loop n +@[inline] def forRevM {m} [Monad m] (n : Nat) (f : (i : Nat) → i < n → m Unit) : m Unit := + let rec @[specialize] loop : ∀ i, i ≤ n → m Unit + | 0, _ => pure () + | i+1, h => do f i (by omega); loop i (Nat.le_of_succ_le h) + loop n (by simp) -@[inline] def foldM {α : Type u} {m : Type u → Type v} [Monad m] (f : Nat → α → m α) (init : α) (n : Nat) : m α := - let rec @[specialize] loop - | 0, a => pure a - | i+1, a => f (n-i-1) a >>= loop i - loop n init +@[inline] def foldM {α : Type u} {m : Type u → Type v} [Monad m] (n : Nat) (f : (i : Nat) → i < n → α → m α) (init : α) : m α := + let rec @[specialize] loop : ∀ i, i ≤ n → α → m α + | 0, h, a => pure a + | i+1, h, a => f (n-i-1) (by omega) a >>= loop i (Nat.le_of_succ_le h) + loop n (by omega) init -@[inline] def foldRevM {α : Type u} {m : Type u → Type v} [Monad m] (f : Nat → α → m α) (init : α) (n : Nat) : m α := - let rec @[specialize] loop - | 0, a => pure a - | i+1, a => f i a >>= loop i - loop n init +@[inline] def foldRevM {α : Type u} {m : Type u → Type v} [Monad m] (n : Nat) (f : (i : Nat) → i < n → α → m α) (init : α) : m α := + let rec @[specialize] loop : ∀ i, i ≤ n → α → m α + | 0, h, a => pure a + | i+1, h, a => f i (by omega) a >>= loop i (Nat.le_of_succ_le h) + loop n (by omega) init -@[inline] def allM {m} [Monad m] (n : Nat) (p : Nat → m Bool) : m Bool := - let rec @[specialize] loop - | 0 => pure true - | i+1 => do - match (← p (n-i-1)) with - | true => loop i +@[inline] def allM {m} [Monad m] (n : Nat) (p : (i : Nat) → i < n → m Bool) : m Bool := + let rec @[specialize] loop : ∀ i, i ≤ n → m Bool + | 0, _ => pure true + | i+1 , h => do + match (← p (n-i-1) (by omega)) with + | true => loop i (by omega) | false => pure false - loop n + loop n (by simp) -@[inline] def anyM {m} [Monad m] (n : Nat) (p : Nat → m Bool) : m Bool := - let rec @[specialize] loop - | 0 => pure false - | i+1 => do - match (← p (n-i-1)) with +@[inline] def anyM {m} [Monad m] (n : Nat) (p : (i : Nat) → i < n → m Bool) : m Bool := + let rec @[specialize] loop : ∀ i, i ≤ n → m Bool + | 0, _ => pure false + | i+1, h => do + match (← p (n-i-1) (by omega)) with | true => pure true - | false => loop i - loop n + | false => loop i (Nat.le_of_succ_le h) + loop n (by simp) end Nat diff --git a/src/Init/Data/Nat/Fold.lean b/src/Init/Data/Nat/Fold.lean new file mode 100644 index 0000000000..1fda04b695 --- /dev/null +++ b/src/Init/Data/Nat/Fold.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2014 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Floris van Doorn, Leonardo de Moura, Kim Morrison +-/ +prelude +import Init.Omega + +set_option linter.missingDocs true -- keep it documented +universe u + +namespace Nat + +/-- +`Nat.fold` evaluates `f` on the numbers up to `n` exclusive, in increasing order: +* `Nat.fold f 3 init = init |> f 0 |> f 1 |> f 2` +-/ +@[specialize] def fold {α : Type u} : (n : Nat) → (f : (i : Nat) → i < n → α → α) → (init : α) → α + | 0, f, a => a + | succ n, f, a => f n (by omega) (fold n (fun i h => f i (by omega)) a) + +/-- Tail-recursive version of `Nat.fold`. -/ +@[inline] def foldTR {α : Type u} (n : Nat) (f : (i : Nat) → i < n → α → α) (init : α) : α := + let rec @[specialize] loop : ∀ j, j ≤ n → α → α + | 0, h, a => a + | succ m, h, a => loop m (by omega) (f (n - succ m) (by omega) a) + loop n (by omega) init + +/-- +`Nat.foldRev` evaluates `f` on the numbers up to `n` exclusive, in decreasing order: +* `Nat.foldRev f 3 init = f 0 <| f 1 <| f 2 <| init` +-/ +@[specialize] def foldRev {α : Type u} : (n : Nat) → (f : (i : Nat) → i < n → α → α) → (init : α) → α + | 0, f, a => a + | succ n, f, a => foldRev n (fun i h => f i (by omega)) (f n (by omega) a) + +/-- `any f n = true` iff there is `i in [0, n-1]` s.t. `f i = true` -/ +@[specialize] def any : (n : Nat) → (f : (i : Nat) → i < n → Bool) → Bool + | 0, f => false + | succ n, f => any n (fun i h => f i (by omega)) || f n (by omega) + +/-- Tail-recursive version of `Nat.any`. -/ +@[inline] def anyTR (n : Nat) (f : (i : Nat) → i < n → Bool) : Bool := + let rec @[specialize] loop : (i : Nat) → i ≤ n → Bool + | 0, h => false + | succ m, h => f (n - succ m) (by omega) || loop m (by omega) + loop n (by omega) + +/-- `all f n = true` iff every `i in [0, n-1]` satisfies `f i = true` -/ +@[specialize] def all : (n : Nat) → (f : (i : Nat) → i < n → Bool) → Bool + | 0, f => true + | succ n, f => all n (fun i h => f i (by omega)) && f n (by omega) + +/-- Tail-recursive version of `Nat.all`. -/ +@[inline] def allTR (n : Nat) (f : (i : Nat) → i < n → Bool) : Bool := + let rec @[specialize] loop : (i : Nat) → i ≤ n → Bool + | 0, h => true + | succ m, h => f (n - succ m) (by omega) && loop m (by omega) + loop n (by omega) + +/-! # csimp theorems -/ + +theorem fold_congr {α : Type u} {n m : Nat} (w : n = m) + (f : (i : Nat) → i < n → α → α) (init : α) : + fold n f init = fold m (fun i h => f i (by omega)) init := by + subst m + rfl + +theorem foldTR_loop_congr {α : Type u} {n m : Nat} (w : n = m) + (f : (i : Nat) → i < n → α → α) (j : Nat) (h : j ≤ n) (init : α) : + foldTR.loop n f j h init = foldTR.loop m (fun i h => f i (by omega)) j (by omega) init := by + subst m + rfl + +@[csimp] theorem fold_eq_foldTR : @fold = @foldTR := + funext fun α => funext fun n => funext fun f => funext fun init => + let rec go : ∀ m n f, fold (m + n) f init = foldTR.loop (m + n) f m (by omega) (fold n (fun i h => f i (by omega)) init) + | 0, n, f => by + simp only [foldTR.loop] + have t : 0 + n = n := by omega + rw [fold_congr t] + | succ m, n, f => by + have t : (m + 1) + n = m + (n + 1) := by omega + rw [foldTR.loop] + simp only [succ_eq_add_one, Nat.add_sub_cancel] + rw [fold_congr t, foldTR_loop_congr t, go, fold] + congr + omega + go n 0 f + +theorem any_congr {n m : Nat} (w : n = m) (f : (i : Nat) → i < n → Bool) : any n f = any m (fun i h => f i (by omega)) := by + subst m + rfl + +theorem anyTR_loop_congr {n m : Nat} (w : n = m) (f : (i : Nat) → i < n → Bool) (j : Nat) (h : j ≤ n) : + anyTR.loop n f j h = anyTR.loop m (fun i h => f i (by omega)) j (by omega) := by + subst m + rfl + +@[csimp] theorem any_eq_anyTR : @any = @anyTR := + funext fun n => funext fun f => + let rec go : ∀ m n f, any (m + n) f = (any n (fun i h => f i (by omega)) || anyTR.loop (m + n) f m (by omega)) + | 0, n, f => by + simp [anyTR.loop] + have t : 0 + n = n := by omega + rw [any_congr t] + | succ m, n, f => by + have t : (m + 1) + n = m + (n + 1) := by omega + rw [anyTR.loop] + simp only [succ_eq_add_one] + rw [any_congr t, anyTR_loop_congr t, go, any, Bool.or_assoc] + congr + omega + go n 0 f + +theorem all_congr {n m : Nat} (w : n = m) (f : (i : Nat) → i < n → Bool) : all n f = all m (fun i h => f i (by omega)) := by + subst m + rfl + +theorem allTR_loop_congr {n m : Nat} (w : n = m) (f : (i : Nat) → i < n → Bool) (j : Nat) (h : j ≤ n) : allTR.loop n f j h = allTR.loop m (fun i h => f i (by omega)) j (by omega) := by + subst m + rfl + +@[csimp] theorem all_eq_allTR : @all = @allTR := + funext fun n => funext fun f => + let rec go : ∀ m n f, all (m + n) f = (all n (fun i h => f i (by omega)) && allTR.loop (m + n) f m (by omega)) + | 0, n, f => by + simp [allTR.loop] + have t : 0 + n = n := by omega + rw [all_congr t] + | succ m, n, f => by + have t : (m + 1) + n = m + (n + 1) := by omega + rw [allTR.loop] + simp only [succ_eq_add_one] + rw [all_congr t, allTR_loop_congr t, go, all, Bool.and_assoc] + congr + omega + go n 0 f + +end Nat + +namespace Prod + +/-- +`(start, stop).foldI f a` evaluates `f` on all the numbers +from `start` (inclusive) to `stop` (exclusive) in increasing order: +* `(5, 8).foldI f init = init |> f 5 |> f 6 |> f 7` +-/ +@[inline] def foldI {α : Type u} (i : Nat × Nat) (f : (j : Nat) → i.1 ≤ j → j < i.2 → α → α) (a : α) : α := + (i.2 - i.1).fold (fun j _ => f (i.1 + j) (by omega) (by omega)) a + +/-- +`(start, stop).anyI f a` returns true if `f` is true for some natural number +from `start` (inclusive) to `stop` (exclusive): +* `(5, 8).anyI f = f 5 || f 6 || f 7` +-/ +@[inline] def anyI (i : Nat × Nat) (f : (j : Nat) → i.1 ≤ j → j < i.2 → Bool) : Bool := + (i.2 - i.1).any (fun j _ => f (i.1 + j) (by omega) (by omega)) + +/-- +`(start, stop).allI f a` returns true if `f` is true for all natural numbers +from `start` (inclusive) to `stop` (exclusive): +* `(5, 8).anyI f = f 5 && f 6 && f 7` +-/ +@[inline] def allI (i : Nat × Nat) (f : (j : Nat) → i.1 ≤ j → j < i.2 → Bool) : Bool := + (i.2 - i.1).all (fun j _ => f (i.1 + j) (by omega) (by omega)) + +end Prod diff --git a/src/Lean/Compiler/IR/Borrow.lean b/src/Lean/Compiler/IR/Borrow.lean index 618ddf8687..e5b73af621 100644 --- a/src/Lean/Compiler/IR/Borrow.lean +++ b/src/Lean/Compiler/IR/Borrow.lean @@ -205,8 +205,8 @@ def getParamInfo (k : ParamMap.Key) : M (Array Param) := do /-- For each ps[i], if ps[i] is owned, then mark xs[i] as owned. -/ def ownArgsUsingParams (xs : Array Arg) (ps : Array Param) : M Unit := - xs.size.forM fun i => do - let x := xs[i]! + xs.size.forM fun i _ => do + let x := xs[i] let p := ps[i]! unless p.borrow do ownArg x @@ -216,8 +216,8 @@ def ownArgsUsingParams (xs : Array Arg) (ps : Array Param) : M Unit := we would have to insert a `dec xs[i]` after `f xs` and consequently "break" the tail call. -/ def ownParamsUsingArgs (xs : Array Arg) (ps : Array Param) : M Unit := - xs.size.forM fun i => do - let x := xs[i]! + xs.size.forM fun i _ => do + let x := xs[i] let p := ps[i]! match x with | Arg.var x => if (← isOwned x) then ownVar p.x diff --git a/src/Lean/Compiler/IR/Boxing.lean b/src/Lean/Compiler/IR/Boxing.lean index 34de6e6f9e..9e06d2ca6f 100644 --- a/src/Lean/Compiler/IR/Boxing.lean +++ b/src/Lean/Compiler/IR/Boxing.lean @@ -48,9 +48,9 @@ def requiresBoxedVersion (env : Environment) (decl : Decl) : Bool := def mkBoxedVersionAux (decl : Decl) : N Decl := do let ps := decl.params let qs ← ps.mapM fun _ => do let x ← N.mkFresh; pure { x := x, ty := IRType.object, borrow := false : Param } - let (newVDecls, xs) ← qs.size.foldM (init := (#[], #[])) fun i (newVDecls, xs) => do + let (newVDecls, xs) ← qs.size.foldM (init := (#[], #[])) fun i _ (newVDecls, xs) => do let p := ps[i]! - let q := qs[i]! + let q := qs[i] if !p.ty.isScalar then pure (newVDecls, xs.push (Arg.var q.x)) else diff --git a/src/Lean/Compiler/IR/ElimDeadBranches.lean b/src/Lean/Compiler/IR/ElimDeadBranches.lean index ee00cabf6a..ce7c9726ac 100644 --- a/src/Lean/Compiler/IR/ElimDeadBranches.lean +++ b/src/Lean/Compiler/IR/ElimDeadBranches.lean @@ -63,7 +63,7 @@ partial def merge (v₁ v₂ : Value) : Value := | top, _ => top | _, top => top | v₁@(ctor i₁ vs₁), v₂@(ctor i₂ vs₂) => - if i₁ == i₂ then ctor i₁ <| vs₁.size.fold (init := #[]) fun i r => r.push (merge vs₁[i]! vs₂[i]!) + if i₁ == i₂ then ctor i₁ <| vs₁.size.fold (init := #[]) fun i _ r => r.push (merge vs₁[i] vs₂[i]!) else choice [v₁, v₂] | choice vs₁, choice vs₂ => choice <| vs₁.foldl (addChoice merge) vs₂ | choice vs, v => choice <| addChoice merge vs v @@ -225,8 +225,8 @@ def updateCurrFnSummary (v : Value) : M Unit := do def updateJPParamsAssignment (ys : Array Param) (xs : Array Arg) : M Bool := do let ctx ← read let currFnIdx := ctx.currFnIdx - ys.size.foldM (init := false) fun i r => do - let y := ys[i]! + ys.size.foldM (init := false) fun i _ r => do + let y := ys[i] let x := xs[i]! let yVal ← findVarValue y.x let xVal ← findArgValue x @@ -282,8 +282,8 @@ partial def interpFnBody : FnBody → M Unit def inferStep : M Bool := do let ctx ← read modify fun s => { s with assignments := ctx.decls.map fun _ => {} } - ctx.decls.size.foldM (init := false) fun idx modified => do - match ctx.decls[idx]! with + ctx.decls.size.foldM (init := false) fun idx _ modified => do + match ctx.decls[idx] with | .fdecl (xs := ys) (body := b) .. => do let s ← get let currVals := s.funVals[idx]! @@ -336,8 +336,8 @@ def elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do let funVals := s.funVals let assignments := s.assignments modify fun s => - let env := decls.size.fold (init := s.env) fun i env => - addFunctionSummary env decls[i]!.name funVals[i]! + let env := decls.size.fold (init := s.env) fun i _ env => + addFunctionSummary env decls[i].name funVals[i]! { s with env := env } return decls.mapIdx fun i decl => elimDead assignments[i]! decl diff --git a/src/Lean/Compiler/IR/EmitC.lean b/src/Lean/Compiler/IR/EmitC.lean index 505fd75335..abc0eb777c 100644 --- a/src/Lean/Compiler/IR/EmitC.lean +++ b/src/Lean/Compiler/IR/EmitC.lean @@ -108,9 +108,9 @@ def emitFnDeclAux (decl : Decl) (cppBaseName : String) (isExternal : Bool) : M U if ps.size > closureMaxArgs && isBoxedName decl.name then emit "lean_object**" else - ps.size.forM fun i => do + ps.size.forM fun i _ => do if i > 0 then emit ", " - emit (toCType ps[i]!.ty) + emit (toCType ps[i].ty) emit ")" emitLn ";" @@ -321,20 +321,22 @@ def emitSSet (x : VarId) (n : Nat) (offset : Nat) (y : VarId) (t : IRType) : M U def emitJmp (j : JoinPointId) (xs : Array Arg) : M Unit := do let ps ← getJPParams j - unless xs.size == ps.size do throw "invalid goto" - xs.size.forM fun i => do - let p := ps[i]! - let x := xs[i]! - emit p.x; emit " = "; emitArg x; emitLn ";" - emit "goto "; emit j; emitLn ";" + if h : xs.size = ps.size then + xs.size.forM fun i _ => do + let p := ps[i] + let x := xs[i] + emit p.x; emit " = "; emitArg x; emitLn ";" + emit "goto "; emit j; emitLn ";" + else + do throw "invalid goto" def emitLhs (z : VarId) : M Unit := do emit z; emit " = " def emitArgs (ys : Array Arg) : M Unit := - ys.size.forM fun i => do + ys.size.forM fun i _ => do if i > 0 then emit ", " - emitArg ys[i]! + emitArg ys[i] def emitCtorScalarSize (usize : Nat) (ssize : Nat) : M Unit := do if usize == 0 then emit ssize @@ -346,8 +348,8 @@ def emitAllocCtor (c : CtorInfo) : M Unit := do emitCtorScalarSize c.usize c.ssize; emitLn ");" def emitCtorSetArgs (z : VarId) (ys : Array Arg) : M Unit := - ys.size.forM fun i => do - emit "lean_ctor_set("; emit z; emit ", "; emit i; emit ", "; emitArg ys[i]!; emitLn ");" + ys.size.forM fun i _ => do + emit "lean_ctor_set("; emit z; emit ", "; emit i; emit ", "; emitArg ys[i]; emitLn ");" def emitCtor (z : VarId) (c : CtorInfo) (ys : Array Arg) : M Unit := do emitLhs z; @@ -358,7 +360,7 @@ def emitCtor (z : VarId) (c : CtorInfo) (ys : Array Arg) : M Unit := do def emitReset (z : VarId) (n : Nat) (x : VarId) : M Unit := do emit "if (lean_is_exclusive("; emit x; emitLn ")) {"; - n.forM fun i => do + n.forM fun i _ => do emit " lean_ctor_release("; emit x; emit ", "; emit i; emitLn ");" emit " "; emitLhs z; emit x; emitLn ";"; emitLn "} else {"; @@ -399,12 +401,12 @@ def emitSimpleExternalCall (f : String) (ps : Array Param) (ys : Array Arg) : M emit f; emit "(" -- We must remove irrelevant arguments to extern calls. discard <| ys.size.foldM - (fun i (first : Bool) => + (fun i _ (first : Bool) => if ps[i]!.ty.isIrrelevant then pure first else do unless first do emit ", " - emitArg ys[i]! + emitArg ys[i] pure false) true emitLn ");" @@ -431,8 +433,8 @@ def emitPartialApp (z : VarId) (f : FunId) (ys : Array Arg) : M Unit := do let decl ← getDecl f let arity := decl.params.size; emitLhs z; emit "lean_alloc_closure((void*)("; emitCName f; emit "), "; emit arity; emit ", "; emit ys.size; emitLn ");"; - ys.size.forM fun i => do - let y := ys[i]! + ys.size.forM fun i _ => do + let y := ys[i] emit "lean_closure_set("; emit z; emit ", "; emit i; emit ", "; emitArg y; emitLn ");" def emitApp (z : VarId) (f : VarId) (ys : Array Arg) : M Unit := @@ -544,34 +546,36 @@ That is, we have -/ def overwriteParam (ps : Array Param) (ys : Array Arg) : Bool := let n := ps.size; - n.any fun i => - let p := ps[i]! - (i+1, n).anyI fun j => paramEqArg p ys[j]! + n.any fun i _ => + let p := ps[i] + (i+1, n).anyI fun j _ _ => paramEqArg p ys[j]! def emitTailCall (v : Expr) : M Unit := match v with | Expr.fap _ ys => do let ctx ← read let ps := ctx.mainParams - unless ps.size == ys.size do throw "invalid tail call" - if overwriteParam ps ys then - emitLn "{" - ps.size.forM fun i => do - let p := ps[i]! - let y := ys[i]! - unless paramEqArg p y do - emit (toCType p.ty); emit " _tmp_"; emit i; emit " = "; emitArg y; emitLn ";" - ps.size.forM fun i => do - let p := ps[i]! - let y := ys[i]! - unless paramEqArg p y do emit p.x; emit " = _tmp_"; emit i; emitLn ";" - emitLn "}" + if h : ps.size = ys.size then + if overwriteParam ps ys then + emitLn "{" + ps.size.forM fun i _ => do + let p := ps[i] + let y := ys[i] + unless paramEqArg p y do + emit (toCType p.ty); emit " _tmp_"; emit i; emit " = "; emitArg y; emitLn ";" + ps.size.forM fun i _ => do + let p := ps[i] + let y := ys[i] + unless paramEqArg p y do emit p.x; emit " = _tmp_"; emit i; emitLn ";" + emitLn "}" + else + ys.size.forM fun i _ => do + let p := ps[i] + let y := ys[i] + unless paramEqArg p y do emit p.x; emit " = "; emitArg y; emitLn ";" + emitLn "goto _start;" else - ys.size.forM fun i => do - let p := ps[i]! - let y := ys[i]! - unless paramEqArg p y do emit p.x; emit " = "; emitArg y; emitLn ";" - emitLn "goto _start;" + throw "invalid tail call" | _ => throw "bug at emitTailCall" mutual @@ -654,16 +658,16 @@ def emitDeclAux (d : Decl) : M Unit := do if xs.size > closureMaxArgs && isBoxedName d.name then emit "lean_object** _args" else - xs.size.forM fun i => do + xs.size.forM fun i _ => do if i > 0 then emit ", " - let x := xs[i]! + let x := xs[i] emit (toCType x.ty); emit " "; emit x.x emit ")" else emit ("_init_" ++ baseName ++ "()") emitLn " {"; if xs.size > closureMaxArgs && isBoxedName d.name then - xs.size.forM fun i => do + xs.size.forM fun i _ => do let x := xs[i]! emit "lean_object* "; emit x.x; emit " = _args["; emit i; emitLn "];" emitLn "_start:"; diff --git a/src/Lean/Compiler/IR/EmitLLVM.lean b/src/Lean/Compiler/IR/EmitLLVM.lean index fd2b19d26e..a93e26d164 100644 --- a/src/Lean/Compiler/IR/EmitLLVM.lean +++ b/src/Lean/Compiler/IR/EmitLLVM.lean @@ -571,9 +571,9 @@ def emitAllocCtor (builder : LLVM.Builder llvmctx) def emitCtorSetArgs (builder : LLVM.Builder llvmctx) (z : VarId) (ys : Array Arg) : M llvmctx Unit := do - ys.size.forM fun i => do + ys.size.forM fun i _ => do let zv ← emitLhsVal builder z - let (_yty, yv) ← emitArgVal builder ys[i]! + let (_yty, yv) ← emitArgVal builder ys[i] let iv ← constIntUnsigned i callLeanCtorSet builder zv iv yv emitLhsSlotStore builder z zv @@ -702,8 +702,8 @@ def emitPartialApp (builder : LLVM.Builder llvmctx) (z : VarId) (f : FunId) (ys (← constIntUnsigned arity) (← constIntUnsigned ys.size) LLVM.buildStore builder zval zslot - ys.size.forM fun i => do - let (yty, yslot) ← emitArgSlot_ builder ys[i]! + ys.size.forM fun i _ => do + let (yty, yslot) ← emitArgSlot_ builder ys[i] let yval ← LLVM.buildLoad2 builder yty yslot callLeanClosureSetFn builder zval (← constIntUnsigned i) yval @@ -922,7 +922,7 @@ def emitReset (builder : LLVM.Builder llvmctx) (z : VarId) (n : Nat) (x : VarId) buildIfThenElse_ builder "isExclusive" isExclusive (fun builder => do let xv ← emitLhsVal builder x - n.forM fun i => do + n.forM fun i _ => do callLeanCtorRelease builder xv (← constIntUnsigned i) emitLhsSlotStore builder z xv return ShouldForwardControlFlow.yes diff --git a/src/Lean/Compiler/IR/ExpandResetReuse.lean b/src/Lean/Compiler/IR/ExpandResetReuse.lean index 8afaf13c53..04dc7527b5 100644 --- a/src/Lean/Compiler/IR/ExpandResetReuse.lean +++ b/src/Lean/Compiler/IR/ExpandResetReuse.lean @@ -134,15 +134,15 @@ abbrev M := ReaderT Context (StateM Nat) modifyGet fun n => ({ idx := n }, n + 1) def releaseUnreadFields (y : VarId) (mask : Mask) (b : FnBody) : M FnBody := - mask.size.foldM (init := b) fun i b => - match mask.get! i with + mask.size.foldM (init := b) fun i _ b => + match mask[i] with | some _ => pure b -- code took ownership of this field | none => do let fld ← mkFresh pure (FnBody.vdecl fld IRType.object (Expr.proj i y) (FnBody.dec fld 1 true false b)) def setFields (y : VarId) (zs : Array Arg) (b : FnBody) : FnBody := - zs.size.fold (init := b) fun i b => FnBody.set y i (zs.get! i) b + zs.size.fold (init := b) fun i _ b => FnBody.set y i zs[i] b /-- Given `set x[i] := y`, return true iff `y := proj[i] x` -/ def isSelfSet (ctx : Context) (x : VarId) (i : Nat) (y : Arg) : Bool := diff --git a/src/Lean/Compiler/IR/RC.lean b/src/Lean/Compiler/IR/RC.lean index be983307b5..79d9b09e4d 100644 --- a/src/Lean/Compiler/IR/RC.lean +++ b/src/Lean/Compiler/IR/RC.lean @@ -79,13 +79,13 @@ private def addDecForAlt (ctx : Context) (caseLiveVars altLiveVars : LiveVarSet) /-- `isFirstOcc xs x i = true` if `xs[i]` is the first occurrence of `xs[i]` in `xs` -/ private def isFirstOcc (xs : Array Arg) (i : Nat) : Bool := let x := xs[i]! - i.all fun j => xs[j]! != x + i.all fun j _ => xs[j]! != x /-- Return true if `x` also occurs in `ys` in a position that is not consumed. That is, it is also passed as a borrow reference. -/ private def isBorrowParamAux (x : VarId) (ys : Array Arg) (consumeParamPred : Nat → Bool) : Bool := - ys.size.any fun i => - let y := ys[i]! + ys.size.any fun i _ => + let y := ys[i] match y with | Arg.irrelevant => false | Arg.var y => x == y && !consumeParamPred i @@ -99,15 +99,15 @@ Return `n`, the number of times `x` is consumed. - `consumeParamPred i = true` if parameter `i` is consumed. -/ private def getNumConsumptions (x : VarId) (ys : Array Arg) (consumeParamPred : Nat → Bool) : Nat := - ys.size.fold (init := 0) fun i n => - let y := ys[i]! + ys.size.fold (init := 0) fun i _ n => + let y := ys[i] match y with | Arg.irrelevant => n | Arg.var y => if x == y && consumeParamPred i then n+1 else n private def addIncBeforeAux (ctx : Context) (xs : Array Arg) (consumeParamPred : Nat → Bool) (b : FnBody) (liveVarsAfter : LiveVarSet) : FnBody := - xs.size.fold (init := b) fun i b => - let x := xs[i]! + xs.size.fold (init := b) fun i _ b => + let x := xs[i] match x with | Arg.irrelevant => b | Arg.var x => @@ -128,8 +128,8 @@ private def addIncBefore (ctx : Context) (xs : Array Arg) (ps : Array Param) (b /-- See `addIncBeforeAux`/`addIncBefore` for the procedure that inserts `inc` operations before an application. -/ private def addDecAfterFullApp (ctx : Context) (xs : Array Arg) (ps : Array Param) (b : FnBody) (bLiveVars : LiveVarSet) : FnBody := -xs.size.fold (init := b) fun i b => - match xs[i]! with +xs.size.fold (init := b) fun i _ b => + match xs[i] with | Arg.irrelevant => b | Arg.var x => /- We must add a `dec` if `x` must be consumed, it is alive after the application, diff --git a/src/Lean/Compiler/LCNF/ElimDeadBranches.lean b/src/Lean/Compiler/LCNF/ElimDeadBranches.lean index d01ad7db49..c5b836e6ec 100644 --- a/src/Lean/Compiler/LCNF/ElimDeadBranches.lean +++ b/src/Lean/Compiler/LCNF/ElimDeadBranches.lean @@ -587,15 +587,15 @@ def Decl.elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do refer to the docstring of `Decl.safe`. -/ if decls[i]!.safe then .bot else .top - let mut funVals := decls.size.fold (init := .empty) fun i p => p.push (initialVal i) + let mut funVals := decls.size.fold (init := .empty) fun i _ p => p.push (initialVal i) let ctx := { decls } let mut state := { assignments, funVals } (_, state) ← inferMain |>.run ctx |>.run state funVals := state.funVals assignments := state.assignments modifyEnv fun e => - decls.size.fold (init := e) fun i env => - addFunctionSummary env decls[i]!.name funVals[i]! + decls.size.fold (init := e) fun i _ env => + addFunctionSummary env decls[i].name funVals[i]! decls.mapIdxM fun i decl => if decl.safe then elimDead assignments[i]! decl else return decl diff --git a/src/Lean/Compiler/LCNF/InferType.lean b/src/Lean/Compiler/LCNF/InferType.lean index 44aae02e42..1bb54b7571 100644 --- a/src/Lean/Compiler/LCNF/InferType.lean +++ b/src/Lean/Compiler/LCNF/InferType.lean @@ -76,8 +76,8 @@ def getType (fvarId : FVarId) : InferTypeM Expr := do def mkForallFVars (xs : Array Expr) (type : Expr) : InferTypeM Expr := let b := type.abstract xs - xs.size.foldRevM (init := b) fun i b => do - let x := xs[i]! + xs.size.foldRevM (init := b) fun i _ b => do + let x := xs[i] let n ← InferType.getBinderName x.fvarId! let ty ← InferType.getType x.fvarId! let ty := ty.abstractRange i xs; diff --git a/src/Lean/Data/PersistentArray.lean b/src/Lean/Data/PersistentArray.lean index 7f014b50b2..39877e000a 100644 --- a/src/Lean/Data/PersistentArray.lean +++ b/src/Lean/Data/PersistentArray.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude +import Init.Data.Nat.Fold import Init.Data.Array.Basic import Init.NotationExtra import Init.Data.ToString.Macro @@ -371,7 +372,7 @@ instance : ToString Stats := ⟨Stats.toString⟩ end PersistentArray def mkPersistentArray {α : Type u} (n : Nat) (v : α) : PArray α := - n.fold (init := PersistentArray.empty) fun _ p => p.push v + n.fold (init := PersistentArray.empty) fun _ _ p => p.push v @[inline] def mkPArray {α : Type u} (n : Nat) (v : α) : PArray α := mkPersistentArray n v diff --git a/src/Lean/Elab/App.lean b/src/Lean/Elab/App.lean index 0f724aa210..4ba28f696e 100644 --- a/src/Lean/Elab/App.lean +++ b/src/Lean/Elab/App.lean @@ -807,8 +807,8 @@ def getElabElimExprInfo (elimExpr : Expr) : MetaM ElabElimInfo := do These are the primary set of major parameters. -/ let initMotiveFVars : CollectFVars.State := motiveArgs.foldl (init := {}) collectFVars - let motiveFVars ← xs.size.foldRevM (init := initMotiveFVars) fun i s => do - let x := xs[i]! + let motiveFVars ← xs.size.foldRevM (init := initMotiveFVars) fun i _ s => do + let x := xs[i] if s.fvarSet.contains x.fvarId! then return collectFVars s (← inferType x) else diff --git a/src/Lean/Elab/MutualDef.lean b/src/Lean/Elab/MutualDef.lean index 55b057eb6b..c345959a64 100644 --- a/src/Lean/Elab/MutualDef.lean +++ b/src/Lean/Elab/MutualDef.lean @@ -840,8 +840,8 @@ private def mkLetRecClosures (sectionVars : Array Expr) (mainFVarIds : Array FVa abbrev Replacement := FVarIdMap Expr def insertReplacementForMainFns (r : Replacement) (sectionVars : Array Expr) (mainHeaders : Array DefViewElabHeader) (mainFVars : Array Expr) : Replacement := - mainFVars.size.fold (init := r) fun i r => - r.insert mainFVars[i]!.fvarId! (mkAppN (Lean.mkConst mainHeaders[i]!.declName) sectionVars) + mainFVars.size.fold (init := r) fun i _ r => + r.insert mainFVars[i].fvarId! (mkAppN (Lean.mkConst mainHeaders[i]!.declName) sectionVars) def insertReplacementForLetRecs (r : Replacement) (letRecClosures : List LetRecClosure) : Replacement := @@ -871,8 +871,8 @@ def Replacement.apply (r : Replacement) (e : Expr) : Expr := def pushMain (preDefs : Array PreDefinition) (sectionVars : Array Expr) (mainHeaders : Array DefViewElabHeader) (mainVals : Array Expr) : TermElabM (Array PreDefinition) := - mainHeaders.size.foldM (init := preDefs) fun i preDefs => do - let header := mainHeaders[i]! + mainHeaders.size.foldM (init := preDefs) fun i _ preDefs => do + let header := mainHeaders[i] let termination ← declValToTerminationHint header.value let termination := termination.rememberExtraParams header.numParams mainVals[i]! let value ← mkLambdaFVars sectionVars mainVals[i]! diff --git a/src/Lean/LocalContext.lean b/src/Lean/LocalContext.lean index 3db35ad9da..6000679799 100644 --- a/src/Lean/LocalContext.lean +++ b/src/Lean/LocalContext.lean @@ -406,8 +406,8 @@ def isSubPrefixOf (lctx₁ lctx₂ : LocalContext) (exceptFVars : Array Expr := @[inline] def mkBinding (isLambda : Bool) (lctx : LocalContext) (xs : Array Expr) (b : Expr) : Expr := let b := b.abstract xs - xs.size.foldRev (init := b) fun i b => - let x := xs[i]! + xs.size.foldRev (init := b) fun i _ b => + let x := xs[i] match lctx.findFVar? x with | some (.cdecl _ _ n ty bi _) => let ty := ty.abstractRange i xs; @@ -457,7 +457,7 @@ def sanitizeNames (lctx : LocalContext) : StateM NameSanitizerState LocalContext let st ← get if !getSanitizeNames st.options then pure lctx else StateT.run' (s := ({} : NameSet)) <| - lctx.decls.size.foldRevM (init := lctx) fun i lctx => do + lctx.decls.size.foldRevM (init := lctx) fun i _ lctx => do match lctx.decls[i]! with | none => pure lctx | some decl => diff --git a/src/Lean/Meta/Basic.lean b/src/Lean/Meta/Basic.lean index 6ea02b0803..9767caa085 100644 --- a/src/Lean/Meta/Basic.lean +++ b/src/Lean/Meta/Basic.lean @@ -825,7 +825,7 @@ def mkFreshExprMVarWithId (mvarId : MVarId) (type? : Option Expr := none) (kind mkFreshExprMVarWithIdCore mvarId type kind userName def mkFreshLevelMVars (num : Nat) : MetaM (List Level) := - num.foldM (init := []) fun _ us => + num.foldM (init := []) fun _ _ us => return (← mkFreshLevelMVar)::us def mkFreshLevelMVarsFor (info : ConstantInfo) : MetaM (List Level) := diff --git a/src/Lean/Meta/Closure.lean b/src/Lean/Meta/Closure.lean index f59ffd12da..ca169eaf96 100644 --- a/src/Lean/Meta/Closure.lean +++ b/src/Lean/Meta/Closure.lean @@ -286,8 +286,8 @@ partial def process : ClosureM Unit := do @[inline] def mkBinding (isLambda : Bool) (decls : Array LocalDecl) (b : Expr) : Expr := let xs := decls.map LocalDecl.toExpr let b := b.abstract xs - decls.size.foldRev (init := b) fun i b => - let decl := decls[i]! + decls.size.foldRev (init := b) fun i _ b => + let decl := decls[i] match decl with | .cdecl _ _ n ty bi _ => let ty := ty.abstractRange i xs diff --git a/src/Lean/Meta/LazyDiscrTree.lean b/src/Lean/Meta/LazyDiscrTree.lean index bacc79cccb..d1f2290d64 100644 --- a/src/Lean/Meta/LazyDiscrTree.lean +++ b/src/Lean/Meta/LazyDiscrTree.lean @@ -566,9 +566,9 @@ Append results to array partial def appendResultsAux (mr : MatchResult α) (a : Array β) (f : Nat → α → β) : Array β := let aa := mr.elts let n := aa.size - Nat.fold (n := n) (init := a) fun i r => + Nat.fold (n := n) (init := a) fun i _ r => let j := n-1-i - let b := aa[j]! + let b := aa[j] b.foldl (init := r) (· ++ ·.map (f j)) partial def appendResults (mr : MatchResult α) (a : Array α) : Array α := diff --git a/src/Lean/Meta/Match/Match.lean b/src/Lean/Meta/Match/Match.lean index 040c32cd38..d602bdb831 100644 --- a/src/Lean/Meta/Match/Match.lean +++ b/src/Lean/Meta/Match/Match.lean @@ -882,7 +882,7 @@ def mkMatcher (input : MkMatcherInput) (exceptionIfContainsSorry := false) : Met | none => pure () trace[Meta.Match.debug] "matcher: {matcher}" - let unusedAltIdxs := lhss.length.fold (init := []) fun i r => + let unusedAltIdxs := lhss.length.fold (init := []) fun i _ r => if s.used.contains i then r else i::r return { matcher, diff --git a/src/Lean/Meta/Match/MatcherApp/Transform.lean b/src/Lean/Meta/Match/MatcherApp/Transform.lean index 6a9d534b88..92cfeccf5f 100644 --- a/src/Lean/Meta/Match/MatcherApp/Transform.lean +++ b/src/Lean/Meta/Match/MatcherApp/Transform.lean @@ -59,9 +59,9 @@ def addArg (matcherApp : MatcherApp) (e : Expr) : MetaM MatcherApp := -- This error can only happen if someone implemented a transformation that rewrites the motive created by `mkMatcher`. throwError "unexpected matcher application, motive must be lambda expression with #{matcherApp.discrs.size} arguments" let eType ← inferType e - let eTypeAbst ← matcherApp.discrs.size.foldRevM (init := eType) fun i eTypeAbst => do + let eTypeAbst ← matcherApp.discrs.size.foldRevM (init := eType) fun i _ eTypeAbst => do let motiveArg := motiveArgs[i]! - let discr := matcherApp.discrs[i]! + let discr := matcherApp.discrs[i] let eTypeAbst ← kabstract eTypeAbst discr return eTypeAbst.instantiate1 motiveArg let motiveBody ← mkArrow eTypeAbst motiveBody @@ -118,9 +118,9 @@ def refineThrough (matcherApp : MatcherApp) (e : Expr) : MetaM (Array Expr) := -- This error can only happen if someone implemented a transformation that rewrites the motive created by `mkMatcher`. throwError "failed to transfer argument through matcher application, motive must be lambda expression with #{matcherApp.discrs.size} arguments" - let eAbst ← matcherApp.discrs.size.foldRevM (init := e) fun i eAbst => do + let eAbst ← matcherApp.discrs.size.foldRevM (init := e) fun i _ eAbst => do let motiveArg := motiveArgs[i]! - let discr := matcherApp.discrs[i]! + let discr := matcherApp.discrs[i] let eTypeAbst ← kabstract eAbst discr return eTypeAbst.instantiate1 motiveArg -- Let's create something that’s a `Sort` and mentions `e` diff --git a/src/Lean/Meta/Tactic/Apply.lean b/src/Lean/Meta/Tactic/Apply.lean index 056863bef1..b912883a96 100644 --- a/src/Lean/Meta/Tactic/Apply.lean +++ b/src/Lean/Meta/Tactic/Apply.lean @@ -104,8 +104,8 @@ def appendParentTag (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Arr newMVars[0]!.mvarId!.setTag parentTag else unless parentTag.isAnonymous do - newMVars.size.forM fun i => do - let mvarIdNew := newMVars[i]!.mvarId! + newMVars.size.forM fun i _ => do + let mvarIdNew := newMVars[i].mvarId! unless (← mvarIdNew.isAssigned) do unless binderInfos[i]!.isInstImplicit do let currTag ← mvarIdNew.getTag diff --git a/src/Lean/Meta/Tactic/Cases.lean b/src/Lean/Meta/Tactic/Cases.lean index 38e25a00cb..ecc00556bd 100644 --- a/src/Lean/Meta/Tactic/Cases.lean +++ b/src/Lean/Meta/Tactic/Cases.lean @@ -168,7 +168,7 @@ private def hasIndepIndices (ctx : Context) : MetaM Bool := do else if ctx.majorTypeIndices.any fun idx => !idx.isFVar then /- One of the indices is not a free variable. -/ return false - else if ctx.majorTypeIndices.size.any fun i => i.any fun j => ctx.majorTypeIndices[i]! == ctx.majorTypeIndices[j]! then + else if ctx.majorTypeIndices.size.any fun i _ => i.any fun j _ => ctx.majorTypeIndices[i] == ctx.majorTypeIndices[j] then /- An index occurs more than once -/ return false else diff --git a/src/Lean/Meta/Tactic/FunInd.lean b/src/Lean/Meta/Tactic/FunInd.lean index 99b21d7276..780d4438e7 100644 --- a/src/Lean/Meta/Tactic/FunInd.lean +++ b/src/Lean/Meta/Tactic/FunInd.lean @@ -283,9 +283,9 @@ partial def foldAndCollect (oldIH newIH : FVarId) (isRecCall : Expr → Option E (onMotive := fun xs _body => do -- Remove the old IH that was added in mkFix let eType ← newIH.getType - let eTypeAbst ← matcherApp.discrs.size.foldRevM (init := eType) fun i eTypeAbst => do + let eTypeAbst ← matcherApp.discrs.size.foldRevM (init := eType) fun i _ eTypeAbst => do let motiveArg := xs[i]! - let discr := matcherApp.discrs[i]! + let discr := matcherApp.discrs[i] let eTypeAbst ← kabstract eTypeAbst discr return eTypeAbst.instantiate1 motiveArg diff --git a/src/Lean/Meta/Tactic/Induction.lean b/src/Lean/Meta/Tactic/Induction.lean index 3132991bd1..ff62ef476e 100644 --- a/src/Lean/Meta/Tactic/Induction.lean +++ b/src/Lean/Meta/Tactic/Induction.lean @@ -105,10 +105,10 @@ private partial def finalize let mvarId' ← mvar.mvarId!.tryClear major.fvarId! let (fields, mvarId') ← mvarId'.introN nparams minorGivenNames.varNames (useNamesForExplicitOnly := !minorGivenNames.explicit) let (extra, mvarId') ← mvarId'.introNP nextra - let subst := reverted.size.fold (init := baseSubst) fun i (subst : FVarSubst) => + let subst := reverted.size.fold (init := baseSubst) fun i _ (subst : FVarSubst) => if i < indices.size + 1 then subst else - let revertedFVarId := reverted[i]! + let revertedFVarId := reverted[i] let newFVarId := extra[i - indices.size - 1]! subst.insert revertedFVarId (mkFVar newFVarId) let fields := fields.map mkFVar @@ -134,8 +134,8 @@ def getMajorTypeIndices (mvarId : MVarId) (tacticName : Name) (recursorInfo : Re if idxPos ≥ majorTypeArgs.size then throwTacticEx tacticName mvarId m!"major premise type is ill-formed{indentExpr majorType}" let idx := majorTypeArgs.get! idxPos unless idx.isFVar do throwTacticEx tacticName mvarId m!"major premise type index {idx} is not a variable{indentExpr majorType}" - majorTypeArgs.size.forM fun i => do - let arg := majorTypeArgs[i]! + majorTypeArgs.size.forM fun i _ => do + let arg := majorTypeArgs[i] if i != idxPos && arg == idx then throwTacticEx tacticName mvarId m!"'{idx}' is an index in major premise, but it occurs more than once{indentExpr majorType}" if i < idxPos then diff --git a/src/Lean/Meta/Tactic/Subst.lean b/src/Lean/Meta/Tactic/Subst.lean index 2b0980fc65..b061399cce 100644 --- a/src/Lean/Meta/Tactic/Subst.lean +++ b/src/Lean/Meta/Tactic/Subst.lean @@ -80,9 +80,9 @@ def substCore (mvarId : MVarId) (hFVarId : FVarId) (symm := false) (fvarSubst : pure mvarId let (newFVars, mvarId) ← mvarId.introNP (vars.size - 2) trace[Meta.Tactic.subst] "after intro rest {vars.size - 2} {MessageData.ofGoal mvarId}" - let fvarSubst ← newFVars.size.foldM (init := fvarSubst) fun i (fvarSubst : FVarSubst) => + let fvarSubst ← newFVars.size.foldM (init := fvarSubst) fun i _ (fvarSubst : FVarSubst) => let var := vars[i+2]! - let newFVar := newFVars[i]! + let newFVar := newFVars[i] pure $ fvarSubst.insert var (mkFVar newFVar) let fvarSubst := fvarSubst.insert aFVarIdOriginal (if clearH then b else mkFVar aFVarId) let fvarSubst := fvarSubst.insert hFVarIdOriginal (mkFVar hFVarId) diff --git a/src/Lean/MetavarContext.lean b/src/Lean/MetavarContext.lean index 9652db7729..ee67968d30 100644 --- a/src/Lean/MetavarContext.lean +++ b/src/Lean/MetavarContext.lean @@ -979,10 +979,10 @@ def collectForwardDeps (lctx : LocalContext) (toRevert : Array Expr) : M (Array else if (← preserveOrder) then -- Make sure toRevert[j] does not depend on toRevert[i] for j < i - toRevert.size.forM fun i => do - let fvar := toRevert[i]! - i.forM fun j => do - let prevFVar := toRevert[j]! + toRevert.size.forM fun i _ => do + let fvar := toRevert[i] + i.forM fun j _ => do + let prevFVar := toRevert[j] let prevDecl := lctx.getFVar! prevFVar if (← localDeclDependsOn prevDecl fvar.fvarId!) then throw (Exception.revertFailure (← getMCtx) lctx toRevert prevDecl.userName.toString) @@ -990,7 +990,7 @@ def collectForwardDeps (lctx : LocalContext) (toRevert : Array Expr) : M (Array let firstDeclToVisit := getLocalDeclWithSmallestIdx lctx toRevert let initSize := newToRevert.size lctx.foldlM (init := newToRevert) (start := firstDeclToVisit.index) fun (newToRevert : Array Expr) decl => do - if initSize.any fun i => decl.fvarId == newToRevert[i]!.fvarId! then + if initSize.any fun i _ => decl.fvarId == newToRevert[i]!.fvarId! then return newToRevert else if toRevert.any fun x => decl.fvarId == x.fvarId! then return newToRevert.push decl.toExpr @@ -1061,8 +1061,8 @@ mutual -/ private partial def mkAuxMVarType (lctx : LocalContext) (xs : Array Expr) (kind : MetavarKind) (e : Expr) (usedLetOnly : Bool) : M Expr := do let e ← abstractRangeAux xs xs.size e - xs.size.foldRevM (init := e) fun i e => do - let x := xs[i]! + xs.size.foldRevM (init := e) fun i _ e => do + let x := xs[i] if x.isFVar then match lctx.getFVar! x with | LocalDecl.cdecl _ _ n type bi _ => @@ -1231,8 +1231,8 @@ private def mkLambda' (x : Name) (bi : BinderInfo) (t : Expr) (b : Expr) (etaRed If `usedLetOnly == true` then `let` expressions are created only for used (let-) variables. -/ def mkBinding (isLambda : Bool) (lctx : LocalContext) (xs : Array Expr) (e : Expr) (usedOnly : Bool) (usedLetOnly : Bool) (etaReduce : Bool) : M Expr := do let e ← abstractRange xs xs.size e - xs.size.foldRevM (init := e) fun i e => do - let x := xs[i]! + xs.size.foldRevM (init := e) fun i _ e => do + let x := xs[i] if x.isFVar then match lctx.getFVar! x with | LocalDecl.cdecl _ _ n type bi _ => diff --git a/src/Lean/PrettyPrinter/Formatter.lean b/src/Lean/PrettyPrinter/Formatter.lean index 805bfd03a7..44ab70e433 100644 --- a/src/Lean/PrettyPrinter/Formatter.lean +++ b/src/Lean/PrettyPrinter/Formatter.lean @@ -467,7 +467,7 @@ def visitAtom (k : SyntaxNodeKind) : Formatter := do @[combinator_formatter manyNoAntiquot] def manyNoAntiquot.formatter (p : Formatter) : Formatter := do let stx ← getCur - visitArgs $ stx.getArgs.size.forM fun _ => p + visitArgs $ stx.getArgs.size.forM fun _ _ => p @[combinator_formatter many1NoAntiquot] def many1NoAntiquot.formatter (p : Formatter) : Formatter := manyNoAntiquot.formatter p @@ -487,7 +487,7 @@ def many1Unbox.formatter (p : Formatter) : Formatter := do @[combinator_formatter sepByNoAntiquot] def sepByNoAntiquot.formatter (p pSep : Formatter) : Formatter := do let stx ← getCur - visitArgs <| stx.getArgs.size.forRevM fun i => if i % 2 == 0 then p else pSep + visitArgs <| stx.getArgs.size.forRevM fun i _ => if i % 2 == 0 then p else pSep @[combinator_formatter sepBy1NoAntiquot] def sepBy1NoAntiquot.formatter := sepByNoAntiquot.formatter diff --git a/src/Lean/PrettyPrinter/Parenthesizer.lean b/src/Lean/PrettyPrinter/Parenthesizer.lean index 9b04f6fe9a..5162d08e98 100644 --- a/src/Lean/PrettyPrinter/Parenthesizer.lean +++ b/src/Lean/PrettyPrinter/Parenthesizer.lean @@ -268,7 +268,7 @@ def visitToken : Parenthesizer := do let stx ← getCur -- `orelse` may produce `choice` nodes for antiquotations if stx.getKind == `choice then - visitArgs $ stx.getArgs.size.forM fun _ => do + visitArgs $ stx.getArgs.size.forM fun _ _ => do orelse.parenthesizer p1 p2 else -- HACK: We have no (immediate) information on which side of the orelse could have produced the current node, so try @@ -332,7 +332,7 @@ partial def parenthesizeCategoryCore (cat : Name) (_prec : Nat) : Parenthesizer withReader (fun ctx => { ctx with cat := cat }) do let stx ← getCur if stx.getKind == `choice then - visitArgs $ stx.getArgs.size.forM fun _ => do + visitArgs $ stx.getArgs.size.forM fun _ _ => do parenthesizeCategoryCore cat _prec else withAntiquot.parenthesizer (mkAntiquot.parenthesizer' cat.toString cat (isPseudoKind := true)) (parenthesizerForKind stx.getKind) @@ -470,7 +470,7 @@ def trailingNode.parenthesizer (k : SyntaxNodeKind) (prec lhsPrec : Nat) (p : Pa @[combinator_parenthesizer manyNoAntiquot] def manyNoAntiquot.parenthesizer (p : Parenthesizer) : Parenthesizer := do let stx ← getCur - visitArgs $ stx.getArgs.size.forM fun _ => p + visitArgs $ stx.getArgs.size.forM fun _ _ => p @[combinator_parenthesizer many1NoAntiquot] def many1NoAntiquot.parenthesizer (p : Parenthesizer) : Parenthesizer := do diff --git a/tests/bench/qsort.lean b/tests/bench/qsort.lean index 225db4966e..c5c61f102b 100755 --- a/tests/bench/qsort.lean +++ b/tests/bench/qsort.lean @@ -58,8 +58,8 @@ qsortAux lt as 0 (UInt32.ofNat (as.size - 1)) def main (xs : List String) : IO Unit := do let n := xs.head!.toNat!; -n.forM $ fun _ => -n.forM $ fun i => do +n.forM $ fun _ _ => +n.forM $ fun i _ => do let xs := mkRandomArray i (UInt32.ofNat i) Array.empty; let xs := qsort xs (fun a b => a < b); --IO.println xs; diff --git a/tests/compiler/phashmap.lean b/tests/compiler/phashmap.lean index 8d7e4904c0..1cb34bd990 100644 --- a/tests/compiler/phashmap.lean +++ b/tests/compiler/phashmap.lean @@ -8,16 +8,16 @@ abbrev Map := PersistentHashMap Nat Nat partial def formatMap : Node Nat Nat → Format | Node.collision keys vals _ => Format.sbracket $ keys.size.fold - (fun i fmt => - let k := keys.get! i; + (fun i _ fmt => + let k := keys[i]; let v := vals.get! i; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ "c@" ++ Format.paren (format k ++ " => " ++ format v)) Format.nil | Node.entries entries => Format.sbracket $ entries.size.fold - (fun i fmt => - let entry := entries.get! i; + (fun i _ fmt => + let entry := entries[i]; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ match entry with @@ -27,19 +27,19 @@ partial def formatMap : Node Nat Nat → Format Format.nil def mkMap (n : Nat) : Map := -n.fold (fun i m => m.insert i (i*10)) PersistentHashMap.empty +n.fold (fun i _ m => m.insert i (i*10)) PersistentHashMap.empty def check (n : Nat) (m : Map) : IO Unit := -n.forM $ fun i => do +n.forM $ fun i _ => do match m.find? i with | none => IO.println s!"failed to find {i}" | some v => unless v == i*10 do IO.println s!"unexpected value {i} => {v}" def delOdd (n : Nat) (m : Map) : Map := -n.fold (fun i m => if i % 2 == 0 then m else m.erase i) m +n.fold (fun i _ m => if i % 2 == 0 then m else m.erase i) m def check2 (n : Nat) (bot : Nat) (m : Map) : IO Unit := -n.forM $ fun i => do +n.forM $ fun i _ => do if i % 2 == 0 && i >= bot then match m.find? i with | none => IO.println s!"failed to find {i}" @@ -48,7 +48,7 @@ n.forM $ fun i => do unless m.find? i == none do IO.println s!"mapping still contains {i}" def delLess (n : Nat) (m : Map) : Map := -n.fold (fun i m => m.erase i) m +n.fold (fun i _ m => m.erase i) m def main (xs : List String) : IO Unit := do diff --git a/tests/compiler/phashmap2.lean b/tests/compiler/phashmap2.lean index 18745da505..b412509a1c 100644 --- a/tests/compiler/phashmap2.lean +++ b/tests/compiler/phashmap2.lean @@ -7,16 +7,16 @@ abbrev Map := PersistentHashMap Nat Nat partial def formatMap : Node Nat Nat → Format | Node.collision keys vals _ => Format.sbracket $ keys.size.fold - (fun i fmt => - let k := keys.get! i; + (fun i _ fmt => + let k := keys[i]; let v := vals.get! i; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ "c@" ++ Format.paren (format k ++ " => " ++ format v)) Format.nil | Node.entries entries => Format.sbracket $ entries.size.fold - (fun i fmt => - let entry := entries.get! i; + (fun i _ fmt => + let entry := entries[i]; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ match entry with diff --git a/tests/compiler/phashmap3.lean b/tests/compiler/phashmap3.lean index 8f54db813a..8492a8d4d3 100644 --- a/tests/compiler/phashmap3.lean +++ b/tests/compiler/phashmap3.lean @@ -7,16 +7,16 @@ abbrev Map := PersistentHashMap Nat Nat partial def formatMap : Node Nat Nat → Format | Node.collision keys vals _ => Format.sbracket $ keys.size.fold - (fun i fmt => - let k := keys.get! i; + (fun i _ fmt => + let k := keys[i]; let v := vals.get! i; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ "c@" ++ Format.paren (format k ++ " => " ++ format v)) Format.nil | Node.entries entries => Format.sbracket $ entries.size.fold - (fun i fmt => - let entry := entries.get! i; + (fun i _ fmt => + let entry := entries[i]; let p := if i > 0 then fmt ++ format "," ++ Format.line else fmt; p ++ match entry with diff --git a/tests/compiler/rbmap_library.lean b/tests/compiler/rbmap_library.lean index 1577cab6b7..b715646889 100644 --- a/tests/compiler/rbmap_library.lean +++ b/tests/compiler/rbmap_library.lean @@ -26,7 +26,7 @@ def tst2 : IO Unit := do let Map := RBMap Nat Nat compare let m : Map := {} let n : Nat := 10000 - let mut m := n.fold (fun i (m : Map) => m.insert i (i*10)) m + let mut m := n.fold (fun i _ (m : Map) => m.insert i (i*10)) m check (m.all (fun k v => v == k*10)) check (sz m == n) IO.println (">> " ++ toString (depth m) ++ ", " ++ toString (sz m)) diff --git a/tests/lean/IRbug.lean b/tests/lean/IRbug.lean index bc49bb79ae..ee6f492c38 100644 --- a/tests/lean/IRbug.lean +++ b/tests/lean/IRbug.lean @@ -16,7 +16,7 @@ def unexpectedBehavior : FooM String := do let b : Bool := (#[] : Array Nat).isEmpty; let trueBranch ← pure "trueBranch"; let falseBranch ← pure "falseBranch"; -(1 : Nat).foldM (λ _ (s : String) => do +(1 : Nat).foldM (λ _ _ (s : String) => do let s ← pure $ if b then trueBranch else falseBranch; pure s) "" #eval unexpectedBehavior () diff --git a/tests/lean/Reformat.lean b/tests/lean/Reformat.lean index fdd5f3a7e0..de42de2ade 100644 --- a/tests/lean/Reformat.lean +++ b/tests/lean/Reformat.lean @@ -19,7 +19,7 @@ let stx' ← Lean.Parser.testParseModule env args.head! (toString f) if stx' != stx then let stx := stx.raw.getArg 1 let stx' := stx'.raw.getArg 1 - stx.getArgs.size.forM fun i => do + stx.getArgs.size.forM fun i _ => do if stx.getArg i != stx'.getArg i then throw $ IO.userError s!"reparsing failed:\n{stx.getArg i}\n{stx'.getArg i}" diff --git a/tests/lean/ref1.lean b/tests/lean/ref1.lean index 7e5718a5a2..fce802e583 100644 --- a/tests/lean/ref1.lean +++ b/tests/lean/ref1.lean @@ -5,18 +5,18 @@ r.set (v+1); IO.println (">> " ++ toString v) def initArray (r : IO.Ref (Array Nat)) (n : Nat) : IO Unit := -n.forM $ fun i => do +n.forM $ fun i _ => do r.modify $ fun a => a.push (2*i) def showArrayRef (r : IO.Ref (Array Nat)) : IO Unit := do let a ← r.swap ∅; -a.size.forM (fun i => IO.println ("[" ++ toString i ++ "]: " ++ toString (a.get! i))); +a.size.forM (fun i _ => IO.println ("[" ++ toString i ++ "]: " ++ toString (a.get! i))); discard $ r.swap a; pure () def tst (n : Nat) : IO Unit := do let r₁ ← IO.mkRef 0; -n.forM fun _ => inc r₁; +n.forM fun _ _ => inc r₁; let r₂ ← IO.mkRef (∅ : Array Nat); initArray r₂ n; showArrayRef r₂ diff --git a/tests/lean/run/unexpected_result_with_bind.lean b/tests/lean/run/unexpected_result_with_bind.lean index 65c00f2e82..66bfc8a706 100644 --- a/tests/lean/run/unexpected_result_with_bind.lean +++ b/tests/lean/run/unexpected_result_with_bind.lean @@ -15,7 +15,7 @@ def unexpectedBehavior : FooM String := do let b : Bool := (#[] : Array Nat).isEmpty; let trueBranch ← pure "trueBranch"; let falseBranch ← pure "falseBranch"; -(1 : Nat).foldM (λ _ (s : String) => do +(1 : Nat).foldM (λ _ _ (s : String) => do let s ← pure $ if b then trueBranch else falseBranch; pure s) "" /-- info: "trueBranch" -/