Skip to content

Commit e2bcf14

Browse files
chore: bump to nightly-2025-12-09 (#693)
Includes #689. --------- Co-authored-by: Paul Reichert <[email protected]>
1 parent 73899b6 commit e2bcf14

File tree

8 files changed

+123
-64
lines changed

8 files changed

+123
-64
lines changed

Manual/BuildTools/Lake.lean

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,9 @@ end
717717

718718
{docstring Lake.getRootPackage}
719719

720-
{docstring Lake.findPackage?}
720+
{docstring Lake.findPackageByName?}
721+
722+
{docstring Lake.findPackageByKey?}
721723

722724
{docstring Lake.findModule?}
723725

Manual/BuildTools/Lake/Config.lean

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ This package contains no {tech}[targets], so there is no code to be built.
136136
name = "example-package"
137137
```
138138
```expected
139-
{name := `«example-package»,
139+
{wsIdx := 0,
140+
baseName := `«example-package»,
141+
keyName := `«example-package»,
140142
origName := `«example-package»,
141143
dir := FilePath.mk ".",
142144
relDir := FilePath.mk ".",
@@ -222,7 +224,9 @@ defaultTargets = ["Sorting"]
222224
name = "Sorting"
223225
```
224226
```expected
225-
{name := `«example-package»,
227+
{wsIdx := 0,
228+
baseName := `«example-package»,
229+
keyName := `«example-package»,
226230
origName := `«example-package»,
227231
dir := FilePath.mk ".",
228232
relDir := FilePath.mk ".",

Manual/Iterators.lean

Lines changed: 106 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,20 @@ Thus, Lean divides iterators into three termination classes:
257257
All finite iterators are necessarily productive.
258258
:::
259259

260-
{docstring Finite +allowMissing}
260+
{docstring Finite}
261261

262-
{docstring Productive +allowMissing}
262+
{docstring Productive}
263263

264-
Sometimes, a needed {name}`Finite` instance is not available because an iterator has not yet been proved finite.
265-
In these cases, {name}`Iter.allowNontermination` can be used to bypass a finiteness requirement.
264+
Lean's standard library provides many functions that iterate over an iterator. These consumer functions usually do not
265+
make any assumptions about the underlying iterator. In particular, such functions may run forever for certain iterators.
266266

267-
{docstring Iter.allowNontermination}
267+
Sometimes, it is of utmost importance that a function does terminate.
268+
For these cases, the combinator {name}`Iter.ensureTermination` results in an iterator that provides variants of consumers that are guaranteed to terminate.
269+
They usually require proof that the involved iterator is finite.
268270

269-
{docstring IterM.allowNontermination}
271+
{docstring Iter.ensureTermination}
272+
273+
{docstring IterM.ensureTermination}
270274

271275
::::example "Iterating Over `Nat`"
272276
```imports -show
@@ -300,6 +304,18 @@ instance [Pure m] : Iterator Nats m Nat where
300304
pure <| .deflate <|
301305
.yield { it with internalState.next := n + 1 } n (by grind)
302306
```
307+
308+
Whenever an iterator is defined, {name}`IteratorCollect` and {name}`IteratorLoop` instances should be provided.
309+
They are required for most consumers of iterators such as {name}`Iter.toList` or the `for` loops.
310+
One can use their default implementations as follows:
311+
312+
```lean
313+
instance [Pure m] [Monad n] : IteratorCollect Nats m n :=
314+
.defaultImplementation
315+
316+
instance [Pure m] [Monad n] : IteratorLoop Nats m n :=
317+
.defaultImplementation
318+
```
303319
:::
304320

305321
:::paragraph
@@ -329,7 +345,18 @@ def Nats.iter : Iter (α := Nats) Nat :=
329345
:::
330346

331347
:::paragraph
332-
This iterator is useful with combinators such as {name}`Iter.zip`:
348+
One can print all natural numbers by running the following function:
349+
```lean
350+
def f : IO Unit := do
351+
for x in Nats.iter do
352+
IO.println s!"{x}"
353+
```
354+
This function never terminates, printing all natural numbers in increasing order, one
355+
after another.
356+
:::
357+
358+
:::paragraph
359+
This iterator is most useful with combinators such as {name}`Iter.zip`:
333360
```lean (name := natzip)
334361
#eval show IO Unit from do
335362
let xs : List String := ["cat", "dog", "pachycephalosaurus"]
@@ -342,6 +369,43 @@ This iterator is useful with combinators such as {name}`Iter.zip`:
342369
2: pachycephalosaurus
343370
```
344371
:::
372+
373+
:::paragraph
374+
In contrast to the previous example, this loop terminates because `xs.iter` is a finite iterator,
375+
One can make sure that a loop actually terminates by providing a {name}`Finite` instance:
376+
```lean (name := natfin)
377+
#check type_of% (Nats.iter.zip ["cat", "dog"].iter).internalState
378+
379+
#synth Finite (Zip Nats Id (ListIterator String) String) Id
380+
```
381+
```leanOutput natfin
382+
Zip Nats Id (ListIterator String) String : Type
383+
```
384+
```leanOutput natfin
385+
Zip.instFinite₂
386+
```
387+
In contrast, `Nats.iter` has no `Finite` instance because it yields infinitely many values:
388+
```lean (name := natinf) +error
389+
#synth Finite Nats Id
390+
```
391+
```leanOutput natinf
392+
failed to synthesize
393+
Finite Nats Id
394+
395+
Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
396+
```
397+
398+
Because there are infinitely many {name}`Nat`s, using {name}`Iter.ensureTermination` results in an error:
399+
```lean (name := natterm) +error
400+
#eval show IO Unit from do
401+
for x in Nats.iter.ensureTermination do
402+
IO.println s!"{x}"
403+
```
404+
```leanOutput natterm
405+
failed to synthesize instance for 'for_in%' notation
406+
ForIn (EIO IO.Error) (Iter.Total Nat) ?m.12
407+
```
408+
:::
345409
::::
346410

347411
::::example "Iterating Over Triples"
@@ -432,7 +496,7 @@ where finally
432496
all_goals grind [Triple.get?]
433497
```
434498

435-
This iterator cannot yet be converted to an array, because it is missing a {name}`Finite` instance and an {name}`IteratorCollect` instance:
499+
This iterator cannot yet be converted to an array, because it is missing an {name}`IteratorCollect` instance:
436500
```lean
437501
def abc : Triple Char := ⟨'a', 'b', 'c'
438502
```
@@ -441,12 +505,30 @@ def abc : Triple Char := ⟨'a', 'b', 'c'⟩
441505
```
442506
```leanOutput noAbc
443507
failed to synthesize instance of type class
444-
Finite (TripleIterator Char) Id
508+
IteratorCollect (TripleIterator Char) Id Id
445509

446510
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
447511
```
448512

449-
To prove finiteness, it's easiest to start at {name}`TriplePos.done` and work backwards toward {name}`TriplePos.fst`, showing that each position in turn has a finite chain of successors:
513+
To support {name}`Iter.toArray`, the default implementation of {name}`IteratorCollect` can be used:
514+
515+
```lean
516+
instance [Iterator (TripleIterator α) m α] [Monad n] :
517+
IteratorCollect (TripleIterator α) m n :=
518+
IteratorCollect.defaultImplementation
519+
```
520+
521+
With the {name}`IteratorCollect` instance in place, {name}`Iter.toArray` now works:
522+
```lean (name := abcToArray)
523+
#eval abc.iter.toArray
524+
```
525+
```leanOutput abcToArray
526+
#['a', 'b', 'c']
527+
```
528+
529+
In general, `Iter.toArray` might run forever. One can prove that `abc` is finite, and the above example will terminate after finitely many steps, by
530+
constructing a `Finite (Triple Char) Id` instance.
531+
It's easiest to start at {name}`TriplePos.done` and work backwards toward {name}`TriplePos.fst`, showing that each position in turn has a finite chain of successors:
450532

451533
```lean
452534
@[grind! .]
@@ -487,28 +569,8 @@ instance [Pure m] : Finite (TripleIterator α) m where
487569
cases pos <;> grind
488570
```
489571

490-
With the {name}`Finite` instance in place, the default implementation of {name}`IteratorCollect` can be used:
491-
492-
```lean
493-
instance [Iterator (TripleIterator α) m α] [Monad n] :
494-
IteratorCollect (TripleIterator α) m n :=
495-
IteratorCollect.defaultImplementation
496-
```
497-
498-
{name}`Iter.toArray` now works:
499-
```lean (name := abcToArray)
500-
#eval abc.iter.toArray
501-
```
502-
```leanOutput abcToArray
503-
#['a', 'b', 'c']
504-
```
505-
506-
To enable the iterator in {keywordOf Lean.Parser.Term.doFor}`for` loops, instances of {name}`IteratorLoopPartial` and {name}`IteratorLoop` are needed:
572+
To enable the iterator in {keywordOf Lean.Parser.Term.doFor}`for` loops, an instance of {name}`IteratorLoop` are needed:
507573
```lean
508-
instance [Monad m] [Monad n] :
509-
IteratorLoopPartial (TripleIterator α) m n :=
510-
.defaultImplementation
511-
512574
instance [Monad m] [Monad n] :
513575
IteratorLoop (TripleIterator α) m n :=
514576
.defaultImplementation
@@ -573,21 +635,17 @@ instance : Iterator FileIterator IO ByteArray where
573635
return .deflate <| .yield it' bytes (by grind)
574636
```
575637

576-
To use it in loops, {name}`IteratorLoop` and {name}`IteratorLoopPartial` instances will be necessary.
577-
In practice, the latter is most important: because file streams may be infinite, the iterator itself may be infinite.
638+
To use it in loops, an {name}`IteratorLoop` instance will be necessary.
578639
```lean
579640
instance [Monad n] : IteratorLoop FileIterator IO n :=
580641
.defaultImplementation
581-
582-
instance [Monad n] : IteratorLoopPartial FileIterator IO n :=
583-
.defaultImplementation
584642
```
585643

586644
This is enough support code to use the iterator to calculate file sizes:
587645
```lean
588646
def fileSize (name : System.FilePath) : IO Nat := do
589647
let mut size := 0
590-
let f := (← iterFile name).allowNontermination
648+
let f := (← iterFile name)
591649
for bytes in f do
592650
size := size + bytes.size
593651
return size
@@ -612,10 +670,6 @@ For example, an array iterator can skip any number of elements in constant time
612670

613671
{docstring LawfulIteratorLoop +allowMissing}
614672

615-
{docstring IteratorLoopPartial +allowMissing}
616-
617-
{docstring IteratorLoopPartial.defaultImplementation}
618-
619673
## Universe Levels
620674

621675
To make the {tech}[universe levels] of iterators more flexible, a wrapper type {name Std.Shrink}`Shrink` is applied around the result of {name}`Iterator.step`.
@@ -655,7 +709,7 @@ There are three primary ways to consume an iterator:
655709
: {keywordOf Lean.Parser.Term.doFor}`for` loops
656710

657711
A {keywordOf Lean.Parser.Term.doFor}`for` loop can consume an iterator, making each value available in its body.
658-
This requires that the iterator have either an instance of {name}`IteratorLoop` or {name}`IteratorLoopPartial` for the loop's monad.
712+
This requires that the iterator have an instance of {name}`IteratorLoop` for the loop's monad.
659713

660714
: Stepping through iterators
661715

@@ -701,25 +755,26 @@ import Std.Data.Iterators
701755
```lean -show
702756
open Std.Iterators
703757
```
704-
Attempting to construct a list of all the natural numbers from an iterator fails:
705-
```lean (name := toListInf) +error -keep
758+
Attempting to construct a list of all the natural numbers from an iterator will produce an endless loop:
759+
```lean (name := toListInf) -keep
706760
def allNats : List Nat :=
707761
let steps : Iter Nat := (0...*).iter
708762
steps.toList
709763
```
764+
The combinator {lean}`Iter.ensureTermination` results in an iterator where non-termination is ruled out.
765+
These iterators are guaranteed to terminate after finitely many steps, and thus cannot be used when Lean cannot prove the iterator finite.
766+
```lean (name := toListInf) +error -keep
767+
def allNats : List Nat :=
768+
let steps := (0...*).iter.ensureTermination
769+
steps.toList
770+
```
710771
The resulting error message states that there is no {name}`Finite` instance:
711772
```leanOutput toListInf
712773
failed to synthesize instance of type class
713774
Finite (Std.Rxi.Iterator Nat) Id
714775

715776
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
716777
```
717-
If the failure to synthesize the instance is due to a missing proof, or if an infinite loop is desirable for an application, then the fact that consuming the iterator may not terminate can be hidden using {name}`Iter.allowNontermination`:
718-
```lean
719-
def allNats : List Nat :=
720-
let steps : Iter Nat := (0...*).iter
721-
steps.allowNontermination.toList
722-
```
723778

724779
:::
725780

@@ -881,7 +936,7 @@ termination_by it.finitelyManySkips
881936
## Collectors
882937

883938
Collectors consume an iterator, returning all of its data in a list or array.
884-
To be collected, an iterator must be finite and have an {name}`IteratorCollect` or {name}`IteratorCollectPartial` instance.
939+
To be collected, an iterator must be finite and have an {name}`IteratorCollect` instance.
885940

886941
{docstring Iter.toArray}
887942

@@ -901,10 +956,6 @@ To be collected, an iterator must be finite and have an {name}`IteratorCollect`
901956

902957
{docstring LawfulIteratorCollect +allowMissing}
903958

904-
{docstring IteratorCollectPartial}
905-
906-
{docstring IteratorCollectPartial.defaultImplementation}
907-
908959

909960
# Iterator Combinators
910961

Manual/Meta/LakeToml.lean

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,9 @@ def checkTomlPackage [Lean.MonadError m] (str : String) : m (Except String Strin
824824
remoteUrl := cfg.remoteUrl
825825
configFile := cfg.configFile
826826
config, depConfigs, targetDecls, targetDeclMap
827-
defaultTargets, name
827+
defaultTargets
828+
baseName := name
829+
wsIdx := 0
828830
origName := name
829831
}
830832

Manual/Meta/LakeToml/Toml.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,9 @@ partial def Highlighted.toHtml (tableLink : Name → Option String) (keyLink : N
316316
| .text s => s
317317
| .ws s =>
318318
let comment := s.find (· == '#')
319-
let commentStr := comment.extract s.endPos
319+
let commentStr := s.extract comment s.endPos
320320
let commentHtml := if commentStr.isEmpty then .empty else {{<span class="comment">{{commentStr}}</span>}}
321-
{{ {{s.startPos.extract comment}} {{commentHtml}} }}
321+
{{ {{s.extract s.startPos comment}} {{commentHtml}} }}
322322
| .key none k => {{
323323
<span class="key">
324324
{{k.toHtml tableLink keyLink}}

lake-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "git",
66
"subDir": null,
77
"scope": "",
8-
"rev": "81c6be41a1bdc34102a6d946f577d30bffa8a018",
8+
"rev": "832af34767bb5941709930d8bec5f394748a9794",
99
"name": "verso",
1010
"manifestFile": "lake-manifest.json",
1111
"inputRev": "nightly-testing",

lakefile.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def ensureDir (dir : System.FilePath) : IO Unit := do
4949

5050
/-- Ensure that the subverso-extract-mod executable is available -/
5151
target subversoExtractMod : FilePath := do
52-
let some pkg := ← findPackage? `subverso
52+
let some pkg := ← findPackageByName? `subverso
5353
| failure
5454
let some exe := pkg.findLeanExe? `«subverso-extract-mod»
5555
| failure

lean-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
leanprover/lean4:nightly-2025-12-08
1+
leanprover/lean4:nightly-2025-12-09

0 commit comments

Comments
 (0)