Skip to content

Commit 1d25c02

Browse files
committed
merge master
2 parents 6fd6da5 + 9c47f39 commit 1d25c02

File tree

512 files changed

+227281
-112606
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

512 files changed

+227281
-112606
lines changed

.github/workflows/pr-release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
- name: Download artifact from the previous workflow.
3535
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
3636
id: download-artifact
37-
uses: dawidd6/action-download-artifact@v8 # https://github.com/marketplace/actions/download-workflow-artifact
37+
uses: dawidd6/action-download-artifact@v9 # https://github.com/marketplace/actions/download-workflow-artifact
3838
with:
3939
run_id: ${{ github.event.workflow_run.id }}
4040
path: artifacts

doc/declarations.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -764,11 +764,12 @@ Structures and Records
764764
The ``structure`` command in Lean is used to define an inductive data type with a single constructor and to define its projections at the same time. The syntax is as follows:
765765

766766
```
767-
structure Foo (a : α) extends Bar, Baz : Sort u :=
767+
structure Foo (a : α) : Sort u extends Bar, Baz :=
768768
constructor :: (field₁ : β₁) ... (fieldₙ : βₙ)
769769
```
770770

771-
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``Foo``, and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible. Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
771+
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``Foo``, and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible (unless all the fields are ``Prop``, in which case it infers ``Prop``).
772+
Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
772773

773774
The declaration above is syntactic sugar for an inductive type declaration, and so results in the addition of the following constants to the environment:
774775

script/prepare-llvm-mingw.sh

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ cp llvm/lib/clang/*/include/{std*,__std*,limits}.h stage1/include/clang
2525
echo '
2626
// https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode
2727
#define SEM_FAILCRITICALERRORS 0x0001
28-
__declspec(dllimport) __stdcall unsigned int SetErrorMode(unsigned int uMode);' > stage1/include/clang/windows.h
28+
__declspec(dllimport) __stdcall unsigned int SetErrorMode(unsigned int uMode);
29+
// https://docs.microsoft.com/en-us/windows/console/setconsoleoutputcp
30+
#define CP_UTF8 65001
31+
__declspec(dllimport) __stdcall int SetConsoleOutputCP(unsigned int wCodePageID);' > stage1/include/clang/windows.h
2932
# COFF dependencies
3033
cp /clang64/lib/{crtbegin,crtend,crt2,dllcrt2}.o stage1/lib/
3134
# runtime

script/release_notes.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,21 @@ def format_markdown_description(pr_number, description):
6565
link = f"[#{pr_number}](https://github.com/leanprover/lean4/pull/{pr_number})"
6666
return f"{link} {description}"
6767

68+
def commit_types():
69+
# see doc/dev/commit_convention.md
70+
return ['feat', 'fix', 'doc', 'style', 'refactor', 'test', 'chore', 'perf']
71+
6872
def count_commit_types(commits):
6973
counts = {
7074
'total': len(commits),
71-
'feat': 0,
72-
'fix': 0,
73-
'refactor': 0,
74-
'doc': 0,
75-
'chore': 0
7675
}
76+
for commit_type in commit_types():
77+
counts[commit_type] = 0
7778

7879
for _, first_line, _ in commits:
79-
for commit_type in ['feat:', 'fix:', 'refactor:', 'doc:', 'chore:']:
80-
if first_line.startswith(commit_type):
81-
counts[commit_type.rstrip(':')] += 1
80+
for commit_type in commit_types():
81+
if first_line.startswith(f'{commit_type}:'):
82+
counts[commit_type] += 1
8283
break
8384

8485
return counts
@@ -158,8 +159,9 @@ def main():
158159
counts = count_commit_types(commits)
159160
print(f"For this release, {counts['total']} changes landed. "
160161
f"In addition to the {counts['feat']} feature additions and {counts['fix']} fixes listed below "
161-
f"there were {counts['refactor']} refactoring changes, {counts['doc']} documentation improvements "
162-
f"and {counts['chore']} chores.\n")
162+
f"there were {counts['refactor']} refactoring changes, {counts['doc']} documentation improvements, "
163+
f"{counts['perf']} performance improvements, {counts['test']} improvements to the test suite "
164+
f"and {counts['style'] + counts['chore']} other changes.\n")
163165

164166
section_order = sort_sections_order()
165167
sorted_changelog = sorted(changelog.items(), key=lambda item: section_order.index(format_section_title(item[0])) if format_section_title(item[0]) in section_order else len(section_order))

src/CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -805,8 +805,6 @@ string(REPLACE "ROOT" "${CMAKE_BINARY_DIR}" LEANC_INTERNAL_LINKER_FLAGS "${LEANC
805805
string(APPEND LEANC_OPTS " ${LEANC_EXTRA_CC_FLAGS} ${LEANC_INTERNAL_FLAGS}")
806806
set(LINK_OPTS "${LEANC_INTERNAL_LINKER_FLAGS} ${LEAN_EXTRA_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/lib/lean")
807807

808-
set(LAKE_PREV_PLUGIN "${PREV_STAGE}/${CMAKE_RELATIVE_LIBRARY_OUTPUT_DIRECTORY}/libLake_shared${CMAKE_SHARED_LIBRARY_SUFFIX}")
809-
810808
# Escape for `make`. Yes, twice.
811809
string(REPLACE "$" "\\\$$" CMAKE_EXE_LINKER_FLAGS_MAKE "${CMAKE_EXE_LINKER_FLAGS}")
812810
string(REPLACE "$" "$$" CMAKE_EXE_LINKER_FLAGS_MAKE_MAKE "${CMAKE_EXE_LINKER_FLAGS_MAKE}")

src/Init/Control/Basic.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Error recovery and state can interact subtly. For example, the implementation of
7878
-/
7979
-- NB: List instance is in mathlib. Once upstreamed, add
8080
-- * `List`, where `failure` is the empty list and `<|>` concatenates.
81-
class Alternative (f : Type u → Type v) extends Applicative f : Type (max (u+1) v) where
81+
class Alternative (f : Type u → Type v) : Type (max (u+1) v) extends Applicative f where
8282
/--
8383
Produces an empty collection or recoverable failure. The `<|>` operator collects values or recovers
8484
from failures. See `Alternative` for more details.

src/Init/Control/Lawful/Basic.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pure f <*> pure x = pure (f x)
4747
u <*> pure y = pure (· y) <*> u
4848
```
4949
-/
50-
class LawfulApplicative (f : Type u → Type v) [Applicative f] extends LawfulFunctor f : Prop where
50+
class LawfulApplicative (f : Type u → Type v) [Applicative f] : Prop extends LawfulFunctor f where
5151
seqLeft_eq (x : f α) (y : f β) : x <* y = const β <$> x <*> y
5252
seqRight_eq (x : f α) (y : f β) : x *> y = const α id <$> x <*> y
5353
pure_seq (g : α → β) (x : f α) : pure g <*> x = g <$> x
@@ -77,7 +77,7 @@ x >>= f >>= g = x >>= (fun x => f x >>= g)
7777
7878
`LawfulMonad.mk'` is an alternative constructor containing useful defaults for many fields.
7979
-/
80-
class LawfulMonad (m : Type u → Type v) [Monad m] extends LawfulApplicative m : Prop where
80+
class LawfulMonad (m : Type u → Type v) [Monad m] : Prop extends LawfulApplicative m where
8181
bind_pure_comp (f : α → β) (x : m α) : x >>= (fun a => pure (f a)) = f <$> x
8282
bind_map {α β : Type u} (f : m (α → β)) (x : m α) : f >>= (. <$> x) = f <*> x
8383
pure_bind (x : α) (f : α → m β) : pure x >>= f = f x

src/Init/Core.lean

+8-8
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,7 @@ free variables. The frontend automatically declares a fresh auxiliary constant `
20202020
20212021
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
20222022
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
2023-
external type checkers (e.g., Trepplein) that do not implement this feature.
2023+
external type checkers that do not implement this feature.
20242024
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
20252025
So, you are mainly losing the capability of type checking your development using external checkers.
20262026
@@ -2055,7 +2055,7 @@ decidability instance can be evaluated to `true` using the lean compiler / inter
20552055
20562056
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
20572057
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
2058-
external type checkers (e.g., Trepplein) that do not implement this feature.
2058+
external type checkers that do not implement this feature.
20592059
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
20602060
So, you are mainly losing the capability of type checking your development using external checkers.
20612061
-/
@@ -2066,7 +2066,7 @@ The axiom `ofReduceNat` is used to perform proofs by reflection. See `reduceBool
20662066
20672067
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
20682068
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
2069-
external type checkers (e.g., Trepplein) that do not implement this feature.
2069+
external type checkers that do not implement this feature.
20702070
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
20712071
So, you are mainly losing the capability of type checking your development using external checkers.
20722072
-/
@@ -2125,7 +2125,7 @@ class LeftIdentity (op : α → β → β) (o : outParam α) : Prop
21252125
`LawfulLeftIdentify op o` indicates `o` is a verified left identity of
21262126
`op`.
21272127
-/
2128-
class LawfulLeftIdentity (op : α → β → β) (o : outParam α) extends LeftIdentity op o : Prop where
2128+
class LawfulLeftIdentity (op : α → β → β) (o : outParam α) : Prop extends LeftIdentity op o where
21292129
/-- Left identity `o` is an identity. -/
21302130
left_id : ∀ a, op o a = a
21312131

@@ -2141,7 +2141,7 @@ class RightIdentity (op : α → β → α) (o : outParam β) : Prop
21412141
`LawfulRightIdentify op o` indicates `o` is a verified right identity of
21422142
`op`.
21432143
-/
2144-
class LawfulRightIdentity (op : α → β → α) (o : outParam β) extends RightIdentity op o : Prop where
2144+
class LawfulRightIdentity (op : α → β → α) (o : outParam β) : Prop extends RightIdentity op o where
21452145
/-- Right identity `o` is an identity. -/
21462146
right_id : ∀ a, op a o = a
21472147

@@ -2151,13 +2151,13 @@ class LawfulRightIdentity (op : α → β → α) (o : outParam β) extends Righ
21512151
This class does not require a proof that `o` is an identity, and is used
21522152
primarily for inferring the identity using class resolution.
21532153
-/
2154-
class Identity (op : α → α → α) (o : outParam α) extends LeftIdentity op o, RightIdentity op o : Prop
2154+
class Identity (op : α → α → α) (o : outParam α) : Prop extends LeftIdentity op o, RightIdentity op o
21552155

21562156
/--
21572157
`LawfulIdentity op o` indicates `o` is a verified left and right
21582158
identity of `op`.
21592159
-/
2160-
class LawfulIdentity (op : α → α → α) (o : outParam α) extends Identity op o, LawfulLeftIdentity op o, LawfulRightIdentity op o : Prop
2160+
class LawfulIdentity (op : α → α → α) (o : outParam α) : Prop extends Identity op o, LawfulLeftIdentity op o, LawfulRightIdentity op o
21612161

21622162
/--
21632163
`LawfulCommIdentity` can simplify defining instances of `LawfulIdentity`
@@ -2168,7 +2168,7 @@ This class is intended for simplifying defining instances of
21682168
`LawfulIdentity` and functions needed commutative operations with
21692169
identity should just add a `LawfulIdentity` constraint.
21702170
-/
2171-
class LawfulCommIdentity (op : α → α → α) (o : outParam α) [hc : Commutative op] extends LawfulIdentity op o : Prop where
2171+
class LawfulCommIdentity (op : α → α → α) (o : outParam α) [hc : Commutative op] : Prop extends LawfulIdentity op o where
21722172
left_id a := Eq.trans (hc.comm o a) (right_id a)
21732173
right_id a := Eq.trans (hc.comm a o) (left_id a)
21742174

src/Init/Data/Array/Attach.lean

+21-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import Init.Data.Array.Mem
88
import Init.Data.Array.Lemmas
99
import Init.Data.Array.Count
1010
import Init.Data.List.Attach
11-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
12-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
11+
12+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
13+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1314

1415
namespace Array
1516

@@ -554,6 +555,10 @@ def unattach {α : Type _} {p : α → Prop} (xs : Array { x // p x }) : Array
554555
(xs.push a).unattach = xs.unattach.push a.1 := by
555556
simp only [unattach, Array.map_push]
556557

558+
@[simp] theorem mem_unattach {p : α → Prop} {xs : Array { x // p x }} {a} :
559+
a ∈ xs.unattach ↔ ∃ h : p a, ⟨a, h⟩ ∈ xs := by
560+
simp only [unattach, mem_map, Subtype.exists, exists_and_right, exists_eq_right]
561+
557562
@[simp] theorem size_unattach {p : α → Prop} {xs : Array { x // p x }} :
558563
xs.unattach.size = xs.size := by
559564
unfold unattach
@@ -675,6 +680,20 @@ and simplifies these to the function directly taking the value.
675680
simp
676681
rw [List.find?_subtype hf]
677682

683+
@[simp] theorem all_subtype {p : α → Prop} {xs : Array { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
684+
(hf : ∀ x h, f ⟨x, h⟩ = g x) (w : stop = xs.size) :
685+
xs.all f 0 stop = xs.unattach.all g := by
686+
subst w
687+
rcases xs with ⟨xs⟩
688+
simp [hf]
689+
690+
@[simp] theorem any_subtype {p : α → Prop} {xs : Array { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
691+
(hf : ∀ x h, f ⟨x, h⟩ = g x) (w : stop = xs.size) :
692+
xs.any f 0 stop = xs.unattach.any g := by
693+
subst w
694+
rcases xs with ⟨xs⟩
695+
simp [hf]
696+
678697
/-! ### Simp lemmas pushing `unattach` inwards. -/
679698

680699
@[simp] theorem unattach_filter {p : α → Prop} {xs : Array { x // p x }}

src/Init/Data/Array/Basic.lean

+23-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import Init.GetElem
1414
import Init.Data.List.ToArrayImpl
1515
import Init.Data.Array.Set
1616

17-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
18-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
17+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
18+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1919

2020
universe u v w
2121

@@ -144,6 +144,8 @@ end List
144144

145145
namespace Array
146146

147+
theorem size_eq_length_toList (xs : Array α) : xs.size = xs.toList.length := rfl
148+
147149
@[deprecated toList_toArray (since := "2024-09-09")] abbrev data_toArray := @List.toList_toArray
148150

149151
@[deprecated Array.toList (since := "2024-09-10")] abbrev Array.data := @Array.toList
@@ -1090,6 +1092,11 @@ def split (as : Array α) (p : α → Bool) : Array α × Array α :=
10901092
as.foldl (init := (#[], #[])) fun (as, bs) a =>
10911093
if p a then (as.push a, bs) else (as, bs.push a)
10921094

1095+
def replace [BEq α] (xs : Array α) (a b : α) : Array α :=
1096+
match xs.finIdxOf? a with
1097+
| none => xs
1098+
| some i => xs.set i b
1099+
10931100
/-! ### Lexicographic ordering -/
10941101

10951102
instance instLT [LT α] : LT (Array α) := ⟨fun as bs => as.toList < bs.toList⟩
@@ -1102,6 +1109,20 @@ instance instLE [LT α] : LE (Array α) := ⟨fun as bs => as.toList ≤ bs.toLi
11021109
We do not currently intend to provide verification theorems for these functions.
11031110
-/
11041111

1112+
/-! ### leftpad and rightpad -/
1113+
1114+
/--
1115+
Pads `l : Array α` on the left with repeated occurrences of `a : α` until it is of size `n`.
1116+
If `l` is initially larger than `n`, just return `l`.
1117+
-/
1118+
def leftpad (n : Nat) (a : α) (xs : Array α) : Array α := mkArray (n - xs.size) a ++ xs
1119+
1120+
/--
1121+
Pads `l : Array α` on the right with repeated occurrences of `a : α` until it is of size `n`.
1122+
If `l` is initially larger than `n`, just return `l`.
1123+
-/
1124+
def rightpad (n : Nat) (a : α) (xs : Array α) : Array α := xs ++ mkArray (n - xs.size) a
1125+
11051126
/- ### reduceOption -/
11061127

11071128
/-- Drop `none`s from a Array, and replace each remaining `some a` with `a`. -/

src/Init/Data/Array/BasicAux.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import Init.Data.Array.Basic
88
import Init.Data.Nat.Linear
99
import Init.NotationExtra
1010

11-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
12-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
11+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
12+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1313

1414
theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : as = bs ∧ a = b := by
1515
simp only [push, mk.injEq] at h

src/Init/Data/Array/BinSearch.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Init.Data.Int.DivMod.Lemmas
99
import Init.Omega
1010
universe u v
1111

12-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
12+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
1313
-- We do not use `linter.indexVariables` here as it is helpful to name the index variables as `lo`, `mid`, and `hi`.
1414

1515
namespace Array

src/Init/Data/Array/Bootstrap.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import Init.Data.List.TakeDrop
1313
This file contains some theorems about `Array` and `List` needed for `Init.Data.List.Impl`.
1414
-/
1515

16-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
17-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
16+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
17+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1818

1919
namespace Array
2020

src/Init/Data/Array/Count.lean

+21-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import Init.Data.List.Nat.Count
1111
# Lemmas about `Array.countP` and `Array.count`.
1212
-/
1313

14-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
15-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
14+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
15+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1616

1717
namespace Array
1818

@@ -23,6 +23,18 @@ section countP
2323

2424
variable (p q : α → Bool)
2525

26+
@[simp] theorem _root_.List.countP_toArray (l : List α) : countP p l.toArray = l.countP p := by
27+
simp [countP]
28+
induction l with
29+
| nil => rfl
30+
| cons hd tl ih =>
31+
simp only [List.foldr_cons, ih, List.countP_cons]
32+
split <;> simp_all
33+
34+
@[simp] theorem countP_toList (xs : Array α) : xs.toList.countP p = countP p xs := by
35+
cases xs
36+
simp
37+
2638
@[simp] theorem countP_empty : countP p #[] = 0 := rfl
2739

2840
@[simp] theorem countP_push_of_pos (xs) (pa : p a) : countP p (xs.push a) = countP p xs + 1 := by
@@ -150,6 +162,13 @@ section count
150162

151163
variable [BEq α]
152164

165+
@[simp] theorem _root_.List.count_toArray (l : List α) (a : α) : count a l.toArray = l.count a := by
166+
simp [count, List.count_eq_countP]
167+
168+
@[simp] theorem count_toList (xs : Array α) (a : α) : xs.toList.count a = xs.count a := by
169+
cases xs
170+
simp
171+
153172
@[simp] theorem count_empty (a : α) : count a #[] = 0 := rfl
154173

155174
theorem count_push (a b : α) (xs : Array α) :

src/Init/Data/Array/DecidableEq.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import Init.Data.BEq
99
import Init.Data.List.Nat.BEq
1010
import Init.ByCases
1111

12-
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
13-
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
12+
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
13+
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
1414

1515
namespace Array
1616

0 commit comments

Comments
 (0)