Compare commits

...

436 Commits

Author SHA1 Message Date
Sofia Rodrigues
e006edd7a1 feat: make tests smaller, add functions 2026-01-21 19:41:01 -03:00
Sofia Rodrigues
017c99b581 feat: onError 2026-01-21 15:16:01 -03:00
Sofia Rodrigues
b2cdef129f fix: small fixes 2026-01-21 00:08:57 -03:00
Sofia Rodrigues
1caabef943 fix: make url behavior srtict 2026-01-19 23:07:29 -03:00
Sofia Rodrigues
0617cc2cac fix: test 2026-01-18 14:39:31 -03:00
Sofia Rodrigues
9686680591 fix: small comment changes 2026-01-18 14:05:23 -03:00
Sofia Rodrigues
e12db84dc0 fix: small issues 2026-01-18 13:51:09 -03:00
Sofia Rodrigues
185d2be818 fix: remove useless files 2026-01-18 13:43:08 -03:00
Sofia Rodrigues
21cdf34d6c fix: typos 2026-01-18 13:42:49 -03:00
Sofia Rodrigues
d92122c8c4 fix: URI parsing was wrong for authorityForm
localhost:8080 now is parsed as a scheme and a path, to work with the URI RFC and HTTP1.1 RFC
2026-01-18 13:36:52 -03:00
Sofia Rodrigues
14129a736f fix: docs 2026-01-16 18:25:58 -03:00
Sofia Rodrigues
a1c1995076 fix: comments 2026-01-16 12:11:33 -03:00
Sofia Rodrigues
00f41fb152 feat: headers 2026-01-14 15:37:23 -03:00
Sofia Rodrigues
1458a61f7f feat: chunked as last encoding 2026-01-12 16:36:18 -03:00
Sofia Rodrigues
8cb626c8db Merge branch 'sofia/async-http' of https://github.com/leanprover/lean4 into sofia/async-http 2026-01-12 15:22:08 -03:00
Sofia Rodrigues
8fc12a44eb feat: headers normal form 2026-01-12 15:20:51 -03:00
Sofia Rodrigues
abae28d28b feat: more uri helpers and theorems 2026-01-09 20:02:07 -03:00
Sofia Rodrigues
aafc5f5f1f feat: uri decidable 2026-01-09 20:02:07 -03:00
Sofia Rodrigues
c94865d221 feat: request smuggling check 2026-01-09 20:02:07 -03:00
Sofia Rodrigues
71d7c96e82 fix: test with wrong content-length order 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
64c58c5b2b feat: add limit to bodycollect 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
4f0fa598c2 feat: add property in headers 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
1e08ec5e8d feat: add more tests for uri, specialize the userinfo type 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
522f08d212 feat: change parsing of uri 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
7f3178941c fix: recv selector of bytestream 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
dcb58be1b7 feat: HasAll in headers 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
d2706fd156 feat: keep alive timeout 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
02c736eb4d reverse: files 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
f2d280160f fix: server timeout 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
4af4420c64 feat: change build functions 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
81f3a88511 reverse: signal 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
865c3953a4 remove: useless files 2026-01-09 20:02:06 -03:00
Sofia Rodrigues
26d5bc7a74 feat: future 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
c5577d6d3b fix: tests 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
9b59503854 fix: tests 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
5cd8b6fce4 feat: doc 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
762c328ec3 fix: connection fork 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
aa693c18fa feat: more tests 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
0a71777aee test: add test 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
79343b87c0 fix: context 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
29f1d178ab fix: cancellationctx 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
397d67a0b4 fix: keep alive behavior 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
0f7390582d feat: cancellation backwards 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
1fd8d038c6 fix: comments 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
e7efa58e6e fix: docs 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
aa4f133c74 feat: add more tests 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
a0a0f45f38 feat: contextual fixes 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
13c6c4994c fix: context 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
59f4c09c21 fix: ext chunk 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
146419bd63 fix: gramatic issues 2026-01-09 20:02:05 -03:00
Sofia Rodrigues
36bcbb093a fix: grammatical issues 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
3a26a540ca fix: parser 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
39c035cad7 fix: trailer 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
f87c952296 feat: parse chunk 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
21ac5a6c80 fix: trailers parsing 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
a726a11ed6 fix: string changes 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
a2b322387b fix: multiple small problems 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
92fe0967b0 fix: weird behaviro when message as not sent :) 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
3d39609878 fix: test 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
83c51ead75 fix: details of connection: close 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
fc231fc42d fix: remove client related 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
25d950b50b fix: tests 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
98602cd8ce fix: bug fixes and improvement in performance 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
c1007723a7 fix: test 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
cfd5ca67aa feat: header changes 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
b974d4ca4d feat: small improvements in tests and client 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
4ef5e0f8e5 fix: import structure 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
34f848225c fix: test 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
5ec62e008c fix: copyright header 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
3f9cfbce83 feat: limits and tests 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
8992b70fb9 feat: header detection and duplication 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
f1f2d98fc7 fix: loop 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
04c5d3ae47 fix: remove small useless things 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
a1f8a5fddf feat: remove useless variable 2026-01-09 20:02:04 -03:00
Sofia Rodrigues
83cfe853fe fix: small issues with chunks and comments 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
97c8a3bf1a fix: protocol 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
818f915362 fix: headers 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
b7a3496999 refactor: part of the connection API 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
a542f73cdf feat: big refactor 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
e7247e1312 fix: remove log 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
470b49f573 feat: improve chunk extensions and handling of shutdown 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
d6ee4c539f fix: comment 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
0ff829a10b fix: remove macro 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
f1a4f3ee60 fix: copyright header 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
a0bcb4f1c7 fix: behavior of the client 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
65d5ef42c1 feat: closePeerConnection 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
2673fe3575 feat: small changes 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
9036480e07 fix: selectors 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
ee126cb28b fix: remove orphaned modules 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
f62fb4ff38 fix: http 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
33bd907d4f fix: update to master 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
6537fdc559 feat: small changes 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
6d209bcfa6 fix: style changes 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
7a35339254 fix: comments 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
a27778b261 fix: comments 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
3590ac0a8a fix: comment and bytebuffer 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
a813e216f9 feat: small changes 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
aab4877222 feat: add header value validation 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
b2adbc96ff fix: bytestream 2026-01-09 20:02:03 -03:00
Sofia Rodrigues
1930fd26ff feat: tests and small changes 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
08daa78cc3 fix: funnel imports 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
99e8939d9b fix: remove orphaned module 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
62e76bc384 feat: http 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
1a8aeca374 fix: async 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
9c983fa7ca fix: streammap 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
0274659e18 feat: cancellation 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
7c2f56f66c fix: simplify 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
e1ebd0e5a5 fix: async 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
271ff7ae0a fix: small comments 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
e146c0e61f fix: async 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
de669dbcb7 fix: streammap 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
9363e42c21 fix: async stream 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
7d81615fc5 fix: channel 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
f074c51af9 fix: stream map 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
bec683ca35 feat: basics stream map 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
69681b56a5 fix: channel 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
ef9df58907 fix: wrong function 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
7ba79053b3 fix: small fixes 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
3a253893d6 feat: async traits 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
4222c6cebd fix: stream can only return one type 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
449112b3da fix: remove useless function 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
8f22819d68 feat: remove outparams 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
b430c5456e feat: async type classes 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
801548be14 feat: http client 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
6cb476d464 refactor: http 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
d850276573 feat: rename 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
1c18ca11b5 fix: test 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
9bc9b49261 fix: timeout 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
fba7b5ad8f fix: update to master 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
75dbf7df97 feat: small changes 2026-01-09 20:02:02 -03:00
Sofia Rodrigues
c7595e1aba fix: small changes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
965be635a2 feat: improve comment of serveConnection 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
1bc51eb0dd fix: style changes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
24091da04f fix: comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
559885014e fix: bytestream comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
94b5ee5836 fix: comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
d86fc27254 fix: comment and bytebuffer 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
c09a0f70ea fix: url parser 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
7705e951a6 feat: small changes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
51b67327de fix: test and small comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
c512fa1b49 fix: merge 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
ea2305b174 feat: add header value validation 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
e623949488 fix: remove useless coe 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
aab7d16cf4 fix: bytestream 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
e9ed6a9204 feat: tests and small changes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
cd63928177 fix: imports 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
6383021cec fix: funnel imports 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
514f1bb20d fix: remove orphaned module 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
7d8bf08fd9 fix: imports 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
7b5a9d662c fix: coe option 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
63365564b0 fix: copyright notice 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
1cf73d1e66 feat: http 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
546b79e481 fix: async 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
c876d64c55 fix: streammap 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
39606ece6e feat: cancellation 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
7df95d7e01 fix: simplify 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
089a9eb254 fix: async 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
1bd391b450 fix: small comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
ebb4d1f2c3 fix: async 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
ffc9b3cb14 fix: streammap 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
29bdadea39 fix: async stream 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
d6ff24fdf3 fix: channel 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
dd79fda420 fix: stream map 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
4ff1146b19 feat: basics stream map 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
55692a55ae fix: channel 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
acb0af7da9 fix: wrong function 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
068fdb4842 fix: small fixes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
2dd2d6cfc5 feat: async traits 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
8f0e8ffd77 fix: stream can only return one type 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
fe99ae3a37 fix: remove useless function 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
5952dc115a feat: remove outparams 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
48ea7def07 feat: async type classes 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
1800a079b6 fix: function names 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
08c14ffafd fix: notes and concurrently 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
2f03e145d4 feat: countAliveTokens and background 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
695cf3c9e9 fix: name and remove backgroudn 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
a934bc0acd test: async context test 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
46fd70864b feat: add selector.cancelled function 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
58a4d61e99 fix: comments 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
0f429d4ed2 feat: add contextual monad 2026-01-09 20:02:01 -03:00
Sofia Rodrigues
392e15075f fix: comment 2026-01-09 20:02:00 -03:00
Sofia Rodrigues
c6f80c2a11 fix: comments 2026-01-09 20:02:00 -03:00
Sofia Rodrigues
8cf20cdeb4 feat: context 2026-01-09 20:02:00 -03:00
Sofia Rodrigues
6313f22b1e feat: future 2026-01-09 20:01:19 -03:00
Sofia Rodrigues
d429561512 feat: more uri helpers and theorems 2026-01-09 19:58:14 -03:00
Kim Morrison
5bb7f37645 feat: add first_par combinator for try? with grind +locals (#11949)
This PR adds a new `first_par` tactic combinator that runs multiple
tactics in parallel and returns the first successful result (cancelling
the others).

The `try?` tactic's `atomicSuggestions` step now uses `first_par` to try
three grind variants in parallel:
- `grind? +suggestions` - uses library suggestion engine  
- `grind? +locals` - unfolds local definitions from current file
- `grind? +locals +suggestions` - combines both

This leverages `TacticM.parFirst` which already provides the "first
success wins" parallel execution with cancellation.

### Depends on
- [x] depends on: #11946

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 21:09:41 +00:00
Sebastian Graf
15a719cb36 chore: extract shared match splitting impl from FunInd and mvcgen (#11953)
This was an indepedently viable refactoring proposed by Joachim. It
fixes a bug in `mvcgen` exposed by the now reverted #11696.
2026-01-09 15:53:26 +00:00
Sebastian Graf
0f1eb1d0e5 chore: remove superfluous (generalizing := false) after revert of #11696 (#11952) 2026-01-09 10:14:18 +00:00
Lean stage0 autoupdater
e766839345 chore: update stage0 2026-01-09 09:33:31 +00:00
Sebastian Graf
22bef1c45a chore: revert "feat: abstract metavariables when generalizing match motives (#8099)" (#11941)
This PR reverts #11696.

Reopens #8099.
2026-01-09 08:24:03 +00:00
George Rennie
b771d12072 feat: Decidable instance for Nat.isPowerOfTwo (#11905)
This PR provides a `Decidable` instance for `Nat.isPowerOfTwo` based on
the formula `(n ≠ 0) ∧ (n &&& (n - 1)) = 0`.

To do this it includes theorems about `Nat.testBit` to show that the
`n.log2`th bit is set in `n` and `n - 1` for non powers of two.

Bitwise lemmas are needed to reason about the `&&&` so the file
`Init.Data.Nat.Power2` is renamed to `Init.Data.Nat.Power2.Basic` and
`Init.Data.Nat.Power2.Lemmas` introduced that depends on
`Init.Data.Nat.Bitwise.Lemmas` to prevent circular includes.

---------

Co-authored-by: Kim Morrison <477956+kim-em@users.noreply.github.com>
2026-01-09 07:51:41 +00:00
dependabot[bot]
214abb7eb2 chore: CI: bump actions/checkout from 5 to 6 (#11459)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to
6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>v6-beta by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
<li>update readme/changelog for v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2311">actions/checkout#2311</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5.0.0...v6.0.0">https://github.com/actions/checkout/compare/v5.0.0...v6.0.0</a></p>
<h2>v6-beta</h2>
<h2>What's Changed</h2>
<p>Updated persist-credentials to store the credentials under
<code>$RUNNER_TEMP</code> instead of directly in the local git
config.</p>
<p>This requires a minimum Actions Runner version of <a
href="https://github.com/actions/runner/releases/tag/v2.329.0">v2.329.0</a>
to access the persisted credentials for <a
href="https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action">Docker
container action</a> scenarios.</p>
<h2>v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5...v5.0.1">https://github.com/actions/checkout/compare/v5...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>V6.0.0</h2>
<ul>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
</ul>
<h2>V5.0.1</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<h2>V5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>V4.3.1</h2>
<ul>
<li>Port v6 cleanup to v4 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
</ul>
<h2>V4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>v4.2.0</h2>
<ul>
<li>Add Ref and Commit outputs by <a
href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
<li>Dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
<a
href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
</ul>
<h2>v4.1.7</h2>
<ul>
<li>Bump the minor-npm-dependencies group across 1 directory with 4
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
<li>Bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
<li>Check out other refs/* by commit by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
<li>Pin actions/checkout's own workflows to a known, good, stable
version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
</ul>
<h2>v4.1.6</h2>
<ul>
<li>Check platform to set archive extension appropriately by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
</ul>
<h2>v4.1.5</h2>
<ul>
<li>Update NPM dependencies by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
<li>Bump github/codeql-action from 2 to 3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
<li>Bump actions/setup-node from 1 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
<li>Bump actions/upload-artifact from 2 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1af3b93b68"><code>1af3b93</code></a>
update readme/changelog for v6 (<a
href="https://redirect.github.com/actions/checkout/issues/2311">#2311</a>)</li>
<li><a
href="71cf2267d8"><code>71cf226</code></a>
v6-beta (<a
href="https://redirect.github.com/actions/checkout/issues/2298">#2298</a>)</li>
<li><a
href="069c695914"><code>069c695</code></a>
Persist creds to a separate file (<a
href="https://redirect.github.com/actions/checkout/issues/2286">#2286</a>)</li>
<li><a
href="ff7abcd0c3"><code>ff7abcd</code></a>
Update README to include Node.js 24 support details and requirements (<a
href="https://redirect.github.com/actions/checkout/issues/2248">#2248</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v5...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-09 07:43:13 +00:00
dependabot[bot]
76a734c907 chore: CI: bump softprops/action-gh-release from 2.4.1 to 2.5.0 (#11458)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 2.4.1 to 2.5.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.5.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: mark release as draft until all artifacts are uploaded by <a
href="https://github.com/dumbmoron"><code>@​dumbmoron</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/692">softprops/action-gh-release#692</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump the npm group across 1 directory with 5 updates by
<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/697">softprops/action-gh-release#697</a></li>
<li>chore(deps): bump actions/checkout from 5.0.0 to 5.0.1 in the
github-actions group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/689">softprops/action-gh-release#689</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/dumbmoron"><code>@​dumbmoron</code></a>
made their first contribution in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/692">softprops/action-gh-release#692</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.4.2...v2.5.0">https://github.com/softprops/action-gh-release/compare/v2.4.2...v2.5.0</a></p>
<h2>v2.4.2</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: Ensure generated release notes cannot be over 125000
characters by <a
href="https://github.com/BeryJu"><code>@​BeryJu</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/684">softprops/action-gh-release#684</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>dependency updates</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/BeryJu"><code>@​BeryJu</code></a> made
their first contribution in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/684">softprops/action-gh-release#684</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.4.1...v2.4.2">https://github.com/softprops/action-gh-release/compare/v2.4.1...v2.4.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>2.5.0</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: mark release as draft until all artifacts are uploaded by <a
href="https://github.com/dumbmoron"><code>@​dumbmoron</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/692">softprops/action-gh-release#692</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>dependency updates</li>
</ul>
<h2>2.4.2</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: Ensure generated release notes cannot be over 125000
characters by <a
href="https://github.com/BeryJu"><code>@​BeryJu</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/684">softprops/action-gh-release#684</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>dependency updates</li>
</ul>
<h2>2.4.1</h2>
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>fix(util): support brace expansion globs containing commas in
parseInputFiles by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/672">softprops/action-gh-release#672</a></li>
<li>fix: gracefully fallback to body when body_path cannot be read by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/671">softprops/action-gh-release#671</a></li>
</ul>
<h2>2.4.0</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat(action): respect working_directory for files globs by <a
href="https://github.com/stephenway"><code>@​stephenway</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/667">softprops/action-gh-release#667</a></li>
</ul>
<h2>2.3.4</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix(action): handle 422 already_exists race condition by <a
href="https://github.com/stephenway"><code>@​stephenway</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/665">softprops/action-gh-release#665</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a06a81a03e"><code>a06a81a</code></a>
release 2.5.0</li>
<li><a
href="7da8983734"><code>7da8983</code></a>
feat: mark release as draft until all artifacts are uploaded (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/692">#692</a>)</li>
<li><a
href="87973286a4"><code>8797328</code></a>
chore(deps): bump actions/checkout in the github-actions group (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/689">#689</a>)</li>
<li><a
href="1bfc62a71b"><code>1bfc62a</code></a>
chore(deps): bump the npm group across 1 directory with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/697">#697</a>)</li>
<li><a
href="5be0e66d93"><code>5be0e66</code></a>
release 2.4.2</li>
<li><a
href="af658b4d5d"><code>af658b4</code></a>
feat: Ensure generated release notes cannot be over 125000 characters
(<a
href="https://redirect.github.com/softprops/action-gh-release/issues/684">#684</a>)</li>
<li><a
href="237aaccf71"><code>237aacc</code></a>
chore: bump node to 24.11.0</li>
<li><a
href="00362bea6f"><code>00362be</code></a>
chore(deps): bump the npm group with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/687">#687</a>)</li>
<li><a
href="0adea5aa98"><code>0adea5a</code></a>
chore(deps): bump the npm group with 3 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/686">#686</a>)</li>
<li><a
href="aa05f9d779"><code>aa05f9d</code></a>
chore(deps): bump actions/setup-node from 5.0.0 to 6.0.0 in the
github-action...</li>
<li>Additional commits viewable in <a
href="6da8fa9354...a06a81a03e">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=2.4.1&new-version=2.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-09 07:42:17 +00:00
dependabot[bot]
f65fe51630 chore: CI: bump namespacelabs/nscloud-checkout-action from 7 to 8 (#11457)
Bumps
[namespacelabs/nscloud-checkout-action](https://github.com/namespacelabs/nscloud-checkout-action)
from 7 to 8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/namespacelabs/nscloud-checkout-action/releases">namespacelabs/nscloud-checkout-action's
releases</a>.</em></p>
<blockquote>
<h2>v8.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Rework checkout flow to precisely control what is fetched and
checked out. by <a
href="https://github.com/nichtverstehen"><code>@​nichtverstehen</code></a>
in <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/pull/22">namespacelabs/nscloud-checkout-action#22</a></li>
<li>Log all mirrored refs in debug mode. by <a
href="https://github.com/nichtverstehen"><code>@​nichtverstehen</code></a>
in <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/pull/23">namespacelabs/nscloud-checkout-action#23</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/namespacelabs/nscloud-checkout-action/compare/v7.1.0...v8.0.0">https://github.com/namespacelabs/nscloud-checkout-action/compare/v7.1.0...v8.0.0</a></p>
<h2>v7.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Correctly check out merge branches for PRs. by <a
href="https://github.com/nichtverstehen"><code>@​nichtverstehen</code></a>
in <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/pull/21">namespacelabs/nscloud-checkout-action#21</a></li>
<li>Set up remote.origin.fetch to allow fetching any branch. by <a
href="https://github.com/nichtverstehen"><code>@​nichtverstehen</code></a>
in <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/pull/21">namespacelabs/nscloud-checkout-action#21</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/nichtverstehen"><code>@​nichtverstehen</code></a>
made their first contribution in <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/pull/21">namespacelabs/nscloud-checkout-action#21</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/namespacelabs/nscloud-checkout-action/compare/v7...v7.1.0">https://github.com/namespacelabs/nscloud-checkout-action/compare/v7...v7.1.0</a></p>
<h2>V7.0.1</h2>
<p>No release notes provided.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0c5e6ce59a"><code>0c5e6ce</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/issues/25">#25</a>
from namespacelabs/fix-doing-lfs-checkouts-on-macos</li>
<li><a
href="135cb5f92a"><code>135cb5f</code></a>
Fix doing lfs checkouts on macos</li>
<li><a
href="2716e107fb"><code>2716e10</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/issues/24">#24</a>
from namespacelabs/kirill/prune</li>
<li><a
href="700dc55af6"><code>700dc55</code></a>
Prune references in the mirror when fetching.</li>
<li><a
href="28e5665c3c"><code>28e5665</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/issues/23">#23</a>
from namespacelabs/kirill/all</li>
<li><a
href="e03456f7c8"><code>e03456f</code></a>
Log all mirrored refs in debug mode.</li>
<li><a
href="253d47cfc0"><code>253d47c</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/issues/22">#22</a>
from namespacelabs/kirill/init</li>
<li><a
href="f2df08a5f7"><code>f2df08a</code></a>
Rework checkout flow to precisely control what is fetched and checked
out.</li>
<li><a
href="65866b8ec2"><code>65866b8</code></a>
Merge pull request <a
href="https://redirect.github.com/namespacelabs/nscloud-checkout-action/issues/21">#21</a>
from namespacelabs/NSL-6774</li>
<li><a
href="ef7d6fcaeb"><code>ef7d6fc</code></a>
Correctly check out merge branches for PRs.</li>
<li>See full diff in <a
href="https://github.com/namespacelabs/nscloud-checkout-action/compare/v7...v8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=namespacelabs/nscloud-checkout-action&package-manager=github_actions&previous-version=7&new-version=8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-09 07:41:50 +00:00
Rob23oba
e6d021967e fix: ensure that decide (xs = #[]) gets compiled to efficient code (#11945)
This PR changes the runtime implementation of the `Decidable (xs = #[])`
and `Decidable (#[] = xs)` instances to use `Array.isEmpty`. Previously,
`decide (xs = #[])` would first convert `xs` into a list and then
compare it against `List.nil`.
2026-01-09 07:30:37 +00:00
Alok Singh
4c360d50fa style: fix typos in Init/ and Std/ docstrings (#11864)
Typos in `Init/` and `Std/`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 07:24:07 +00:00
Alok Singh
821218aabd style: fix typos in Lake docstrings (#11867)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 07:21:35 +00:00
Kim Morrison
7b1fb7ac9e feat: add simp +locals to include local definitions (#11947)
This PR adds a `+locals` configuration option to the `simp`, `simp_all`,
and `dsimp` tactics that automatically adds all definitions from the
current file to unfold.

Example usage:
```lean
def foo (n : Nat) : Nat := n + 1

-- Without +locals, simp doesn't know about foo
example (n : Nat) : foo n = n + 1 := by simp  -- fails

-- With +locals, simp can unfold foo
example (n : Nat) : foo n = n + 1 := by simp +locals  -- succeeds
```

The implementation iterates over `env.constants.map₂` (which contains
constants defined in the current module) and adds definitions to unfold.
Instance definitions and internal details are filtered out.

**Note:** For local theorems, use `+suggestions` instead, which will
include relevant local theorems via the library suggestion engine.

🤖 Prepared with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 07:19:40 +00:00
Kim Morrison
cd632b033d feat: add grind +locals to include local definitions (#11946)
This PR adds a `+locals` configuration option to the `grind` tactic that
automatically adds all definitions from the current file as e-match
theorems. This provides a convenient alternative to manually adding
`[local grind]` attributes to each definition. In the form `grind?
+locals`, it is also helpful for discovering which local declarations it
may be useful to add `[local grind]` attributes to.

Example usage:
```lean
def foo (n : Nat) : Nat := n + 1

-- Without +locals, grind doesn't know about foo
example (n : Nat) : foo n = n + 1 := by grind  -- fails

-- With +locals, grind can use the equation
example (n : Nat) : foo n = n + 1 := by grind +locals  -- succeeds
```

Instance definitions and internal details are filtered out.

🤖 Prepared with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 07:19:32 +00:00
Leonardo de Moura
d92cdae8e9 feat: simpForall and simpArrow in Sym.simp (#11950)
This PR implements `simpForall` and `simpArrow` in `Sym.simp`.
2026-01-09 06:20:04 +00:00
David Thrane Christiansen
7d5a96941e doc: add missing docstrings to iterator library (#11912)
This PR adds missing docstrings for parts of the iterator library, which
removes warnings and empty content in the manual.

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
2026-01-08 19:25:39 +00:00
Sebastian Ullrich
b4cf6b02b9 chore: shake: explain indirect uses as well (#11944) 2026-01-08 16:42:13 +00:00
Sebastian Ullrich
ea7c740ad4 fix: ctor visibility in mutual public inductives (#11940)
This PR fixes module system visibiltity issues when trying to declare a
public inductive inside a mutual block.

Fixes #11115
2026-01-08 14:25:25 +00:00
Sebastian Ullrich
aa8fa47321 chore: attributes do not have to be tracked as public uses (#11939) 2026-01-08 13:39:10 +00:00
Henrik Böving
7e6365567f refactor: preparatory change from structure to inductive on LCNF (#11934) 2026-01-08 09:56:41 +00:00
Sebastian Ullrich
1361d733a6 feat: re-integrate lean4checker as leanchecker (#11887)
This PR makes the external checker lean4checker available as the
existing `leanchecker` binary already known to elan, allowing for
out-of-the-box access to it.

---------

Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:41:33 +00:00
Kim Morrison
0ad15fe982 refactor: add message log capture helpers for tactic evaluation (#11933)
This PR adds utility functions for managing the message log during
tactic
evaluation, and refactors existing code to use them.

**New helpers in `Lean.Elab.Tactic`:**
- `withSuppressedMessages`: executes an action while suppressing new
messages
- `withCapturedMessages`: executes an action and returns any new
messages
- `hasErrorMessages`: checks if a message list contains errors

**Refactored to use these helpers:**
- `LibrarySearch.tryDischarger`: now uses `withSuppressedMessages`
- `Try.evalAndSuggest`: now uses `withSuppressedMessages`
- `Try.evalAndSuggestWithBy`: now uses `withSuppressedMessages`

These helpers provide a standard pattern for tactic validation that
needs to
inspect error messages (e.g., filtering out suggestions that produce
errors).

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:25:36 +00:00
Leonardo de Moura
531dbf0e1b perf: mkFunExtFor (#11932)
This PR eliminates super-linear kernel type checking overhead when
simplifying lambda expressions. I improved the proof term produced by
`mkFunext`. This function is used in `Sym.simp` when simplifying lambda
expressions.

 ### Lambda benchmark: before vs after optimization

| Lambda | Before simp (ms) | After simp (ms) | Simp speedup | Before
kernel (ms) | After kernel (ms) | Kernel speedup | Before proof | After
proof | Proof reduction |

|--------|------------------|-----------------|--------------|--------------------|-------------------|----------------|--------------|-------------|-----------------|
| 10 | 0.269 | 0.208 | 1.29× | 0.521 | 0.390 | 1.34× | 583 | 498 | 1.17×
|
| 20 | 0.457 | 0.382 | 1.20× | 1.126 | 0.651 | 1.73× | 1323 | 918 |
1.44× |
| 30 | 0.747 | 0.536 | 1.39× | 1.733 | 0.789 | 2.20× | 2263 | 1338 |
1.69× |
| 40 | 0.819 | 0.697 | 1.18× | 2.696 | 1.065 | 2.53× | 3403 | 1758 |
1.94× |
| 50 | 1.035 | 0.901 | 1.15× | 3.918 | 1.304 | 3.01× | 4743 | 2178 |
2.18× |
| 100 | 2.351 | 1.823 | 1.29× | 20.073 | 2.927 | 6.86× | 14443 | 4278 |
3.38× |
| 150 | 3.920 | 2.873 | 1.36× | 60.266 | 5.290 | 11.39× | 29143 | 6378 |
4.57× |
| 200 | 5.869 | 3.819 | 1.54× | 148.681 | 6.903 | 21.54× | 48843 | 8478
| 5.76× |

We can now handle much larger lambda expressions. For example:

lambda_1000: 20.869250ms, kernel: 98.637875ms, proof_size=42078

This new approach will be implemented in `Meta.simp` in the future. Here
is the table with the `Meta.simp` numbers.

 ### Old `Meta.simp` lambda benchmark

| Lambda | Simp time (ms) | Kernel time (ms) | Proof size |
|--------|----------------|------------------|------------|
| 10  | 2.308 | 0.667 | 1273 |
| 20  | 5.739 | 1.817 | 3323 |
| 30  | 10.687 | 3.320 | 6173 |
| 40  | 17.607 | 6.326 | 9823 |
| 50  | 28.336 | 9.024 | 14273 |
| 100 | 137.878 | 34.344 | 48523 |
| 150 | 395.429 | 77.329 | 102773 |
| 200 | 866.097 | 143.020 | 177023 |
2026-01-08 04:28:58 +00:00
Michael Rothgang
2e649e16f0 fix: pretty-printing of unification hints (#11780)
This PR ensures that pretty-printing of unification hints inserts a
space after |- resp. ⊢.

All uses in Lean core and mathlib add a space after the |- or ⊢ symbol;
this makes the output match usage in practice.
This was discovered in leanprover-community/mathlib4#30658, adding a
formatting linter using pretty-printing as initial guide.
2026-01-08 01:46:25 +00:00
Leonardo de Moura
0e4794a1a9 test: benchmarks for lambda-telescopes (#11929) 2026-01-08 00:20:03 +00:00
Kim Morrison
975a81cdb8 feat: filter out deprecated lemmas from suggestions in exact?/rw? (#11918)
This PR filters deprecated lemmas from `exact?` and `rw?` suggestions.

Previously, both tactics would suggest deprecated lemmas, which could be
confusing for users since using the suggestion would trigger a
deprecation warning.

Now, lemmas marked with `@[deprecated]` are filtered out in the
`addImport` functions that populate the discrimination trees used by
these tactics.

**Example (before this PR):**
```lean
import Mathlib.Logic.Basic

example (h : ∃ n : Nat, n > 0) : True := by
  choose (n : Nat) (hn : n > 0 + 0) using h
  guard_hyp hn : n > 0  -- `rw?` would suggest `Eq.rec_eq_cast` which is deprecated
```

Zulip discussion:
https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/deprecated.20lemma.20from.20rw.3F/near/554106870

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 23:45:04 +00:00
Kim Morrison
f7de0c408f fix: improve error message for initialize with missing Nonempty instance (#11919)
This PR improves the error message when `initialize` (or `opaque`) fails
to find an `Inhabited` or `Nonempty` instance.

**Before:**
```
failed to synthesize
  Inhabited Foo
```

**After:**
```
failed to synthesize 'Inhabited' or 'Nonempty' instance for
  Foo

If this type is defined using the 'structure' or 'inductive' command, you can try adding a 'deriving Nonempty' clause to it.
```

Prompted by
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/initialize.20structure.20with.20IO.2ERef/near/564936030

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 23:44:33 +00:00
Kim Morrison
60cdda3c1e refactor: move simp/grind attributes for leftpad/rightpad to definition (#11928)
This PR moves the `@[simp, grind =]` attributes for `List.leftpad` and
`List.rightpad` from `Init.Data.List.Lemmas` to the point of definition
in `Init.Data.List.Basic`.

This makes the simp behavior discoverable at the definition site,
addressing the discoverability issue raised in [this Zulip
discussion](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/Finding.20the.20.60.40.5Bsimp.5D.60.20attribute/near/566714920).

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 23:43:05 +00:00
Leonardo de Moura
8484dbad5d test: benchmarks for have-telescopes (#11927) 2026-01-07 23:24:46 +00:00
Kim Morrison
b0ebfaa812 fix: ensure use of unsafeEIO is marked as unsafe (#11926)
This PR adds an `unsafe` modifier to an existing helper function user
`unsafeEIO`, and also leaves the function private.
2026-01-07 21:38:37 +00:00
Henrik Böving
c3cc61cdb4 feat: add a symbol gadget for non linear Array copies (#11916)
This PR adds a symbol to the runtime for marking `Array`
non-linearities. This should allow users to
spot them more easily in profiles or hunt them down using a debugger.
2026-01-07 13:08:45 +00:00
Leonardo de Moura
ff87bcb8e5 feat: add option for simplifying have decls in two passes (#11923)
This PR adds a new option to the function `simpHaveTelescope` in which
the `have` telescope is simplified in two passes:

* In the first pass, only the values and the body are simplified.
* In the second pass, unused declarations are eliminated.

This new mode eliminates **superlinear** behavior in the benchmark
`simp_3.lean`. Note that the kernel type checker still **exhibits**
quadratic behavior in this example, because it **does not have support**
for expanding a `have`/`let` telescope in a single step.
2026-01-07 01:58:36 +00:00
Kim Morrison
a6ed0d640d feat: add #guard_panic command and substring option for #guard_msgs (#11908)
This PR adds two features to the message testing commands:

## `#guard_panic` command

A new `#guard_panic` command that succeeds if the nested command
produces a panic message. Unlike `#guard_msgs`, it does not check the
exact message content, only that a panic occurred.

This is useful for testing commands that are expected to panic, where
the exact panic message text may be volatile. It is particularly useful
when minimizing a panic discovered "in the wild", while ensuring the
panic behaviour is preserved.

## `substring := true` option for `#guard_msgs`

Adds a `substring := true` option to `#guard_msgs` that checks if the
docstring appears as a substring of the output (after whitespace
normalization), rather than requiring an exact match. This is useful
when you only care about part of the message.

Example:
```lean
/-- Unknown identifier -/
#guard_msgs (substring := true) in
example : α := x
```

## Refactoring

Also refactors `runAndCollectMessages` as a shared helper function used
by both `#guard_msgs` and `#guard_panic`.

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 01:34:49 +00:00
Leonardo de Moura
8154453bb5 feat: simplify have blocks in Sym.simp (#11920)
This PR implements support for simplifying `have` telescopes in
`Sym.simp`.
2026-01-07 00:10:47 +00:00
Lean stage0 autoupdater
11e4e44be0 chore: update stage0 2026-01-06 21:42:26 +00:00
Leonardo de Moura
c871f66cfa refactor: have telescope support (#11914)
This PR factors out the `have`-telescope support used in `simp`, and
implements it using the `MonadSimp` interface. The goal is to
use this nice infrastructure for both `Meta.simp` and `Sym.simp`.
2026-01-06 19:20:25 +00:00
Anne Baanen
0f866236c7 doc: write a guideline for tactic docstrings (#11406)
This PR covers tactic docstrings in the documentation style guide.

At the Mathlib Initiative we want to ensure that tactics have good
documentation. Since this will involve adding documentation to tactics
built into core Lean, I discussed with David that we should write a
shared set of documentation guidelines that allow me to do my work both
on the Lean and on the Mathlib repositories.

I have already shown an earlier version of this guideline to David who
made some helpful suggestions but would be away for a few days. So to
make sure the discussion doesn't get lost, I've made a PR with the
version I ended up with after the first round of comments.

---------

Co-authored-by: Robert J. Simmons <442315+robsimmons@users.noreply.github.com>
2026-01-06 04:40:20 +00:00
Leonardo de Moura
f6c8b8d974 perf: replaceS and instantiateRevBetaS (#11911)
This PR minimizes the number of expression allocations performed by
`replaceS` and `instantiateRevBetaS`.
2026-01-06 03:03:01 +00:00
Leonardo de Moura
175661b6c3 refactor: reorganize SymM and GrindM monad hierarchy (#11909)
This PR reorganizes the monad hierarchy for symbolic computation in
Lean.

## Motivation

We want a clean layering where:
1. A foundational monad (`SymM`) provides maximally shared terms and
structural/syntactic `isDefEq`
2. `GrindM` builds on this foundation, adding E-graphs, congruence
closure, and decision procedures
3. Symbolic execution / VCGen uses `GrindM` directly without introducing
a third monad

## Changes

The core symbolic computation layer still lives in `Lean.Meta.Sym`. This
monad (`SymM`) provides:
- Maximally shared terms with pointer-based equality
- Structural/syntactic `isDefEq` and matching (no reduction, predictable
cost)
- Monotonic local contexts (no `revert` or `clear`), enabling O(1)
metavariable validation
- Efficient `intro`, `apply`, and `simp` implementations

The name "Sym" reflects that this is infrastructure for symbolic
computation: symbolic simulation, verification condition generation, and
decision procedures.

### Updated hierarchy

```
Lean.Meta.Sym   -- SymM: shared terms, syntactic isDefEq, intro, apply, simp
Lean.Meta.Grind -- GrindM: E-graphs, congruence closure (extends SymM)
```

Symbolic execution is a usage pattern of `GrindM` operating on
`Grind.Goal`, not a separate monad. This keeps the API surface minimal:
users learn two monads, and VCGen is "how you use `GrindM`" (for users
that want to use `grind`) rather than a third abstraction to understand.
2026-01-06 01:12:07 +00:00
Leonardo de Moura
fd88637948 perf: add PersistentHashMap.findKeyD and PersistentHashSet.findD (#11907)
This PR implements `PersistentHashMap.findKeyD` and
`PersistentHashSet.findD`. The motivation is avoid two memory
allocations (`Prod.mk` and `Option.some`) when the collections contains
the key.
2026-01-05 20:04:49 +00:00
Leonardo de Moura
7376772cbd perf: use update.*! at AlphaShareCommon (#11906)
This PR tries to minimize the number of expressions created at
`AlphaShareCommon`.
2026-01-05 19:11:01 +00:00
Kim Morrison
c358b0c734 feat: add guards for grind patterns for getElem?_eq_none theorems (#11761)
This PR adds some `grind_pattern` `guard` conditions to potentially
expensive theorems.
2026-01-05 08:55:02 +00:00
Kim Morrison
8207919728 chore: cleanup grind List tests (#11903)
Some of these tests were last investigated a long time ago: happily many
of the failing tests now work due to subsequent improvements to grind.
2026-01-05 05:02:33 +00:00
Kim Morrison
06b7b022b3 chore: cleanup some grind tests about palindromes (#11902) 2026-01-05 03:55:17 +00:00
Kim Morrison
460b3c3e43 fix: grind propagates 0 * a = 0 for CommSemiring (#11881)
This PR fixes an issue where `grind` failed to prove `f ≠ 0` from `f * r
≠ 0` when using `Lean.Grind.CommSemiring`, but succeeded with
`Lean.Grind.Semiring`.

The `propagateMul` propagator handles `0 * a = 0` and `a * 0 = 0` rules
for semirings that don't have full ring support in grind. Previously,
`CommSemiring` was excluded because it uses a ring envelope for
normalization, but that approach doesn't propagate these equalities back
to the original terms. Now `CommSemiring` also uses `propagateMul`.

Reported as
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Grind.20failure.20for.20CommSemiring.2C.20not.20Semiring

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 03:14:35 +00:00
Kim Morrison
b46688d683 feat: add Nat.gcd_left_comm and Int.gcd_left_comm (#11901)
This PR adds `gcd_left_comm` lemmas for both `Nat` and `Int`:

- `Nat.gcd_left_comm`: `gcd m (gcd n k) = gcd n (gcd m k)`
- `Int.gcd_left_comm`: `gcd a (gcd b c) = gcd b (gcd a c)`

These lemmas establish the left-commutativity property for gcd,
complementing the existing `gcd_comm` and `gcd_assoc` lemmas.

Upstreamed from
https://github.com/leanprover-community/mathlib4/pull/33235

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 03:12:50 +00:00
Leonardo de Moura
82f60a7ff3 feat: pre and post may return "done" in Sym.simp (#11900)
This PR adds a `done` flag to the result returned by `Simproc`s in
`Sym.simp`.

The `done` flag controls whether simplification should continue after
the result:
- `done = false` (default): Continue with subsequent simplification
steps
- `done = true`: Stop processing, return this result as final

## Use cases for `done = true`

### In `pre` simprocs
Skip simplification of certain subterms entirely:
```
def skipLambdas : Simproc := fun e =>
  if e.isLambda then return .rfl (done := true)
  else return .rfl
```

### In `post` simprocs
Perform single-pass normalization without recursive simplification:
```
def singlePassNormalize : Simproc := fun e =>
  if let some (e', h) ← tryNormalize e then
    return .step e' h (done := true)
  else return .rfl
```
With `done = true`, the result `e'` won't be recursively simplified.
2026-01-05 02:10:06 +00:00
Kim Morrison
6bf2486e13 chore: include comparator and lean4export in release process (#11899)
This PR includes https://github.com/leanprover/lean4export/ and
https://github.com/leanprover/comparator/ in the monthly release
workflow.
2026-01-05 01:08:50 +00:00
Leonardo de Moura
f1c903ca65 feat: simplify lambdas in Sym.simp (#11898)
This PR adds support for simplifying lambda expressions in `Sym.simp`.
It is much more efficient than standard simp for very large lambda
expressions with many binders. The key idea is to generate a custom
function extensionality theorem for the type of the lambda being
simplified.

This technique is compatible with the standard `simp` tactic, and will
be ported in a separate PR.

<img width="581" height="455" alt="image"
src="https://github.com/user-attachments/assets/5911dc6c-03f0-48ed-843b-b8cb4f67ee61"
/>

### `lambda` benchmark summary

| Lambda size | MetaM (ms) | SymM (ms) | Speedup |
|-------------|------------|-----------|---------|
| 50          | 22.7       | 0.74      | ~31×    |
| 100         | 120.5      | 1.75      | ~69×    |
| 150         | 359.6      | 2.90      | ~124×   |
| 200         | 809.5      | 4.51      | ~180×   |
2026-01-05 01:00:30 +00:00
Kim Morrison
35d8925c50 fix: avoid panic in TagDeclarationExtension.tag on partial elaboration (#11882)
This PR adds a guard to `TagDeclarationExtension.tag` to check if the
declaration name is anonymous and return early if so. This prevents a
panic that could occur when modifiers like `meta` or `noncomputable` are
used in combination with syntax errors.

Reproducer:
```lean
public meta section
def private
```

Previously this would panic with:
```
PANIC at Lean.EnvExtension.modifyState: called on `async` extension,
must set `asyncDecl` in that case
```

This follows the same pattern as the fix in #10131 for `addDocString`
and the existing guard in `markNotMeta`.

See
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/panic.20on.20doc-string/near/566110399

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 00:36:58 +00:00
Leonardo de Moura
9f404d8fbe chore: remove leftover (#11895) 2026-01-04 21:42:13 +00:00
Sebastian Ullrich
81c93aeae8 perf: ensure withTraceNodeBefore message is created lazily (#11893) 2026-01-04 20:38:39 +00:00
Leonardo de Moura
cf36ac986d perf: optimize simp congruence proofs (#11892)
This PR optimizes the construction on congruence proofs in `simp`.
It uses some of the ideas used in `Sym.simp`.
2026-01-04 19:37:21 +00:00
Leonardo de Moura
609d99e860 chore: include free variables (#11894)
This PR includes free variable in a `simp` benchmark to stress the
default `simp` matching procedure.
2026-01-04 18:51:18 +00:00
Leonardo de Moura
78c9a01bb2 feat: check Sym.simp thresholds (#11890)
This PR ensures that `Sym.simp` checks thresholds for maximum recursion
depth and maximum number of steps. It also invokes `checkSystem`.
Additionally, this PR simplifies the main loop. Assigned metavariables
and `zetaDelta` reduction are now handled by installing `pre`/`post`
methods.
2026-01-04 04:27:46 +00:00
Leonardo de Moura
a2cf78ac4a perf: Sym.Simp.DiscrTree retrieval (#11889)
This PR improves the discrimination tree retrieval performance used by
`Sym.simp`.
2026-01-04 03:51:56 +00:00
Leonardo de Moura
bc72487aed refactor: Sym.simp (#11888)
This PR refactors `Sym.simp` to make it more general and customizable.
It also moves the code
to its own subdirectory `Meta/Sym/Simp`.
2026-01-04 02:17:23 +00:00
Leonardo de Moura
b40dabdecd feat: add discrimination tree retrieval for Sym (#11886)
This PR adds `getMatch` and `getMatchWithExtra` for retrieving patterns
from
discrimination trees in the symbolic simulation framework. 
The PR also adds uses `DiscrTree` to implement indexing in `Sym.simp`.
2026-01-03 20:28:07 +00:00
Leonardo de Moura
19df2c41b3 feat: add insertPattern for discrimination tree insertion in Sym (#11884)
This PR adds discrimination tree support for the symbolic simulation
framework.
The new `DiscrTree.lean` module converts `Pattern` values into
discrimination
tree keys, treating proof/instance arguments and pattern variables as
wildcards
(`Key.star`). Motivation: efficient pattern retrieval during rewriting.
2026-01-03 19:27:43 +00:00
Henrik Böving
ce8fdb1aa7 chore: fix typo (#11883) 2026-01-03 11:36:50 +00:00
Kim Morrison
fab1897f28 feat: add with_unfolding_none tactic (#11880)
This PR adds a `with_unfolding_none` tactic that sets the transparency
mode to `.none`, in which no definitions are unfolded. This complements
the existing `with_unfolding_all` tactic and provides tactic-level
access to the `TransparencyMode.none` added in
https://github.com/leanprover/lean4/pull/11810.

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 08:36:51 +00:00
Leonardo de Moura
3804a1df8d doc: structural matching and definitional equality (#11878)
This PR documents assumptions made by the symbolic simulation framework
regarding structural matching and definitional equality.
2026-01-02 21:47:16 +00:00
Leonardo de Moura
514a5fddc6 refactor: DiscrTree (#11875)
This PR adds the directory `Meta/DiscrTree` and reorganizes the code
into different files. Motivation: we are going to have new functions for
retrieving simplification theorems for the new structural simplifier.
2026-01-02 19:53:45 +00:00
Henrik Böving
d8f0507d2a perf: faster getLine (#11874)
This PR improves the performance of `getLine` by coalescing the locking
of the underlying `FILE*`.

Unfortunately we cannot use `getline` or `fgets` for this as our code
needs to handle `\0` chars
and Windows.
2026-01-02 19:08:18 +00:00
Henrik Böving
4eb5b5776d perf: inline IsUTF8FirstByte (#11872)
This PR marks IsUTF8FirstByte as inline.

I have a use case where it shows up significantly in the profile.
2026-01-02 11:21:54 +00:00
Sebastian Graf
6642061623 fix: make mvcgen with tac fail if tac fails on one of the VCs (#11871)
This PR makes `mvcgen with tac` fail if `tac` fails on one of the VCs,
just as `induction ... with tac` fails if `tac` fails on one of the
goals. The old behavior can be recovered by writing `mvcgen with try
tac` instead.
2026-01-02 10:52:25 +00:00
Leonardo de Moura
4e8b5cfc46 test: benchmark Sym and Meta simplifiers (#11870)
This PR adds simple benchmarks for comparing the `MetaM` and `SymM`
simplifiers. The `SymM` simplifier is still working in progress.

### Big picture across benchmarks

| Benchmark | MetaM scaling | SymM scaling | Speedup (approx.) |

|-------------------------|-------------------|--------------|-------------------|
| `trans_chain` | Linear | Linear | ~8–9× |
| `congr_arg_explosion` | Super-linear | Linear | ~100× |
| `many_rewrites` | Super-linear | Linear | ~10–16× |

<img width="598" height="455" alt="image"
src="https://github.com/user-attachments/assets/8bd9021b-b9cf-4fc0-aab4-3118d87f7c22"
/>

<img width="644" height="455" alt="image"
src="https://github.com/user-attachments/assets/0234dc11-0be7-441a-83b6-c309d20a2663"
/>

<img width="611" height="455" alt="image"
src="https://github.com/user-attachments/assets/df79d057-25ed-49d9-a8f3-5285e5fc7013"
/>
2026-01-02 03:59:54 +00:00
Leonardo de Moura
c07ee77d33 feat: add Meta.Context.cacheInferType (#11869)
This PR adds configuration flag `Meta.Context.cacheInferType`. You can
use it to disable the `inferType` cache at `MetaM`. We use this flag to
implement `SymM` because it has its own cache based on pointer equality.
2026-01-02 03:21:43 +00:00
Leonardo de Moura
b82f969e5b feat: add Sym.Simp.Theorem.rewrite? (#11868)
This PR implements `Sym.Simp.Theorem.rewrite?` for rewriting terms using
equational theorems in `Sym`.
2026-01-02 02:23:37 +00:00
Leonardo de Moura
97c23abf8e feat: main loop for Sym.simp (#11866)
This PR implements the core simplification loop for the `Sym` framework,
with efficient congruence-based argument rewriting.
2026-01-01 23:21:22 +00:00
Leonardo de Moura
ef9777ec0d feat: add getCongrInfo to Sym (#11860)
This PR adds `CongrInfo` analysis for function applications in the
symbolic simulator framework. `CongrInfo` determines how to build
congruence proofs for rewriting subterms efficiently, categorizing
functions into:

- `none`: no arguments can be rewritten (e.g., proofs)
- `fixedPrefix`: common case where implicit/instance arguments form a
fixed prefix and explicit arguments can be rewritten (e.g., `HAdd.hAdd`,
`Eq`)
- `interlaced`: rewritable and non-rewritable arguments alternate (e.g.,
`HEq`)
- `congrTheorem`: uses auto-generated congruence theorems for functions
with dependent proof arguments (e.g., `Array.eraseIdx`)
2026-01-01 17:27:08 +00:00
Henrik Böving
b7360969ed feat: bv_decide can handle structure fields with parametric width (#11858)
This PR changes `bv_decide`'s heuristic for what kinds of structures to
split on to also allow
splitting on structures where the fields have dependently typed widths.
For example:
```lean
structure Byte (w : Nat) where
  /-- A two's complement integer value of width `w`. -/
  val : BitVec w
  /-- A per-bit poison mask of width `w`. -/
  poison : BitVec w
```
This is to allow handling situations such as `(x : Byte 8)` where the
width becomes concrete after
splitting is done.
2026-01-01 13:36:33 +00:00
Leonardo de Moura
9b1b932242 feat: add shareCommonInc (#11857)
This PR adds an incremental variant of `shareCommon` for expressions
constructed from already-shared subterms. We use this when an expression
`e` was produced by a Lean API (e.g., `inferType`, `mkApp4`) that does
not preserve maximal sharing, but the inputs to that API were already
maximally shared. Unlike `shareCommon`, this function does not use a
local `Std.HashMap ExprPtr Expr` to track visited nodes. This is more
efficient when the number of new (unshared) nodes is small, which is the
common case when wrapping API calls that build a few constructor nodes
around shared inputs.
2026-01-01 05:40:33 +00:00
Leonardo de Moura
d4563a818f feat: simplifier for Sym (#11856)
This PR adds the basic infrastructure for the structural simplifier used
by the symbolic simulation (`Sym`) framework.
2026-01-01 04:34:50 +00:00
Paul Reichert
e8781f12c0 feat: use MonadAttach in the takeWhileM and dropWhileM iterator combinators (#11852)
This PR changes the definition of the iterator combinators `takeWhileM`
and `dropWhileM` so that they use `MonadAttach`. This is only relevant
in rare cases, but makes it sometimes possible to prove such combinators
finite when the finiteness depends on properties of the monadic
predicate.
2025-12-31 12:38:21 +00:00
Leonardo de Moura
1ca4faae18 fix: Sym.intro for have-declarations (#11851)
This PR fixes `Sym/Intro.lean` support for `have`-declarations.
2025-12-31 01:36:23 +00:00
Leonardo de Moura
3a5887276c fix: handle assigned metavariables during pattern matching (#11850)
This PR fixes a bug in the new pattern matching procedure for the Sym
framework. It was not correctly handling assigned metavariables during
pattern matching.

It also improves the support for free variables.
2025-12-31 00:50:55 +00:00
Leonardo de Moura
e086b9b5c6 fix: zetaDelta at Sym/Pattern.lean (#11849)
This PR fixes missing zetaDelta support at the pattern
matching/unification procedure in the new Sym framework.
2025-12-30 23:47:22 +00:00
Leonardo de Moura
16ae74e98e fix: bug at Name.beq (#11848)
This PR fixes a bug at `Name.beq` reported by
gasstationcodemanager@gmail.com
2025-12-30 18:22:47 +00:00
Henrik Böving
2a28cd98fc feat: allow bv_decide users to configure the SAT solver (#11847)
This PR adds a new `solverMode` field to `bv_decide`'s configuration,
allowing users to configure
the SAT solver for different kinds of workloads.
2025-12-30 13:17:20 +00:00
Leonardo de Moura
bba35e4532 perf: add performance comparison tests for SymM vs MetaM (#11838)
This PR adds performance comparison tests between the new `SymM` monad
and the standard `MetaM` for `intros`/`apply` operations.

The tests solve problems of the form:
```lean
let z := 0; ∀ x, ∃ y, x = z + y ∧ let z := z + x; ∀ x, ∃ y, x = z + y ∧ ... ∧ True
```
using repeated `intros` and `apply` with `Exists.intro`, `And.intro`,
`Eq.refl`, and `True.intro`.

**Results show 10-20x speedup:**

| Size | MetaM | SymM | Speedup |
|------|-------|------|---------|
| 1000 | 226ms | 21ms | 10.8x |
| 2000 | 582ms | 44ms | 13.2x |
| 3000 | 1.08s | 72ms | 15.0x |
| 4000 | 1.72s | 101ms | 17.0x |
| 5000 | 2.49s | 125ms | 19.9x |
| 6000 | 3.45s | 157ms | 22.0x |
2025-12-30 02:42:04 +00:00
Leonardo de Moura
17581a2628 feat: add backward chaining rule application to Sym (#11837)
This PR adds `BackwardRule` for efficient goal transformation via
backward chaining in `SymM`.

`BackwardRule` stores a theorem expression, precomputed pattern for
fast unification, and argument indices that become new subgoals. The
subgoal ordering lists non-dependent goals first to match the behavior
of `MetaM.apply`.

`BackwardRule.apply` unifies the goal type with the rule's pattern,
assigns the goal metavariable to the theorem application, and returns
new subgoals for unassigned arguments.
2025-12-30 00:23:08 +00:00
Paul Reichert
05664b15a3 fix: update naming of FinitenessRelation fields in the sigmaIterator.lean benchmark (#11836)
This PR fixes a broken benchmark that uses an outdated naming of
`FinitenessRelation` and `ProductivenessRelation`'s fields.
2025-12-29 23:13:13 +00:00
Sofia Rodrigues
00e569fe62 Merge branch 'master' of https://github.com/leanprover/lean4 into sofia/async-http 2025-12-29 13:21:09 -03:00
Sofia Rodrigues
59031e2908 feat: uri decidable 2025-12-26 19:58:47 -03:00
Sofia Rodrigues
207c7776a6 feat: request smuggling check 2025-12-26 17:20:54 -03:00
Sofia Rodrigues
c6b0245929 fix: test with wrong content-length order 2025-12-26 17:11:24 -03:00
Sofia Rodrigues
d2ec777a4e feat: add limit to bodycollect 2025-12-26 17:01:00 -03:00
Sofia Rodrigues
1fb0ab22c9 feat: add property in headers 2025-12-26 16:33:34 -03:00
Sofia Rodrigues
e1ece4838e feat: add more tests for uri, specialize the userinfo type 2025-12-26 14:48:36 -03:00
Sofia Rodrigues
e024d60260 feat: change parsing of uri 2025-12-24 17:51:50 -03:00
Sofia Rodrigues
ebd0056bfa fix: recv selector of bytestream 2025-12-23 21:40:30 -03:00
Sofia Rodrigues
998b7a98ad feat: HasAll in headers 2025-12-19 21:14:21 -03:00
Sofia Rodrigues
be1b96fa27 feat: keep alive timeout 2025-12-18 03:08:16 -03:00
Sofia Rodrigues
d4a378b50f reverse: files 2025-12-18 02:39:30 -03:00
Sofia Rodrigues
e8e5902f9a fix: server timeout 2025-12-18 02:39:04 -03:00
Sofia Rodrigues
eae30712cf feat: change build functions 2025-12-17 22:53:41 -03:00
Sofia Rodrigues
2eeb73bfae reverse: signal 2025-12-17 21:07:44 -03:00
Sofia Rodrigues
4493731335 remove: useless files 2025-12-17 21:00:54 -03:00
Sofia Rodrigues
5103fd944b feat: future 2025-12-17 20:59:20 -03:00
Sofia Rodrigues
c2ea05793f fix: tests 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
9756d5946f fix: tests 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
6a889eda3a feat: doc 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
9e9688d021 fix: connection fork 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
876547d404 feat: more tests 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
4f1795248f test: add test 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
3efb149d85 fix: context 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
b4bee04324 fix: cancellationctx 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
c5930d8284 fix: keep alive behavior 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
09287a574c feat: cancellation backwards 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
24a776e8a0 fix: comments 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
778289c5e6 fix: docs 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
597beb0a48 feat: add more tests 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
7f492f75a5 feat: contextual fixes 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
f26bf10cf1 fix: context 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
f135a4830a fix: ext chunk 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
31b8ed5157 fix: gramatic issues 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
b9f9518d15 fix: grammatical issues 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
2bb0503dc0 fix: parser 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
e11e1b9937 fix: trailer 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
7cca5e070b feat: parse chunk 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
2a3ec888ee fix: trailers parsing 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
a3a970e553 fix: string changes 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
e5bcdfe020 fix: multiple small problems 2025-12-17 20:57:20 -03:00
Sofia Rodrigues
12f33eebd4 fix: weird behaviro when message as not sent :) 2025-12-17 20:57:18 -03:00
Sofia Rodrigues
5fd23f0878 fix: test 2025-12-17 20:57:09 -03:00
Sofia Rodrigues
7afd19513b fix: details of connection: close 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
342e614f0f fix: remove client related 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
55645fa51b fix: tests 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
3aeb1cce3c fix: bug fixes and improvement in performance 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
c1683ec5bc fix: test 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
52e6863ad0 feat: header changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
bfc7cb1b27 feat: small improvements in tests and client 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
8d6baae17b fix: import structure 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
d169f2606d fix: test 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
25634a78f1 fix: copyright header 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
3e969253b3 feat: limits and tests 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
60f16b7532 feat: header detection and duplication 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
3b7381d326 fix: loop 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
b4f919468b fix: remove small useless things 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
0d90d45418 feat: remove useless variable 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
6326c7d3b3 fix: small issues with chunks and comments 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
2c08b50839 fix: protocol 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
595db1cf64 fix: headers 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
2f86695614 refactor: part of the connection API 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
7b269375f6 feat: big refactor 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
83b17191d2 fix: remove log 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
123c5209d1 feat: improve chunk extensions and handling of shutdown 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
ee98ed7535 fix: comment 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
ad3b3b6fd8 fix: remove macro 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
0577251413 fix: copyright header 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
2abcad5e6e fix: behavior of the client 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
78ec06d3cc feat: closePeerConnection 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
36c1416ac9 feat: small changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
9042768059 fix: selectors 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
183086a5bd fix: remove orphaned modules 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
4b68a44976 fix: http 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
2d29158568 fix: update to master 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
0a4823baab feat: small changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
f431c97297 fix: style changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
ce0a6a99a6 fix: comments 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
94d17e0ca3 fix: comments 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
f054f7d679 fix: comment and bytebuffer 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
dd701fd809 feat: small changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
5244656a14 feat: add header value validation 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
183ce44d55 fix: bytestream 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
9b58239b4b feat: tests and small changes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
60eca9a897 fix: funnel imports 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
c89e865a41 fix: remove orphaned module 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
cbfa6ed78c feat: http 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
426b21b9ab fix: async 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
7ab3b6fed8 fix: streammap 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
15066ffb64 feat: cancellation 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
3b70b4e74a fix: simplify 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
2e48a50fb6 fix: async 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
78de8de671 fix: small comments 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
021a56f4a7 fix: async 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
4586e4acbf fix: streammap 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
b6b2fd7a87 fix: async stream 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
ef7f651f2d fix: channel 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
9bbe37b656 fix: stream map 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
26b208abe7 feat: basics stream map 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
97fb044377 fix: channel 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
8f302823b7 fix: wrong function 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
448988cdb4 fix: small fixes 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
9f1f701cef feat: async traits 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
a2c5207f9d fix: stream can only return one type 2025-12-17 20:57:08 -03:00
Sofia Rodrigues
b499386bc1 fix: remove useless function 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
4f6bfcca78 feat: remove outparams 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
ff27df47cb feat: async type classes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
5b3ce9d804 feat: http client 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
e83ecd5e1b refactor: http 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
2b130c09ff feat: rename 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
a33134efa9 fix: test 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
6aefaeea6a fix: timeout 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
b7a209a10e fix: update to master 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
abe970846f feat: small changes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
8dcfd41ea2 fix: small changes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
5632fc881c feat: improve comment of serveConnection 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
a5d327fa44 fix: style changes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
16c660ffe1 fix: comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
9a1417add3 fix: bytestream comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
97945791e6 fix: comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
93a14968ee fix: comment and bytebuffer 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
4cee3d3eaf fix: url parser 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
ca246c5923 feat: small changes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
dfd0ed400e fix: test and small comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
850be6c8e8 fix: merge 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
8a586a8b8d feat: add header value validation 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
491be56c1f fix: remove useless coe 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
95152c8ca0 fix: bytestream 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
942c4ba3a0 feat: tests and small changes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
537105018d fix: imports 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
4244af7ddc fix: funnel imports 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
ddb0e62764 fix: remove orphaned module 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
97b22ecf92 fix: imports 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
3b1cfca2d1 fix: coe option 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
1e0d86ebcc fix: copyright notice 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
7944ec0160 feat: http 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
278b46398e fix: async 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
7b052b02ab fix: streammap 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
96668994d4 feat: cancellation 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
bb74e1bccf fix: simplify 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
a7cd25f1ff fix: async 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
f88c758b0e fix: small comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
e2c331ab7e fix: async 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
1ed788ab9e fix: streammap 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
2ac72964e2 fix: async stream 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
969bd9242f fix: channel 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
19d88b8a92 fix: stream map 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
1729756bcc feat: basics stream map 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
c9a753b55d fix: channel 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
3ec6c66cec fix: wrong function 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
0936da3b78 fix: small fixes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
31adf6837f feat: async traits 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
6efb2f8e59 fix: stream can only return one type 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
b98472e911 fix: remove useless function 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
3d4f30c232 feat: remove outparams 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
179d51f13d feat: async type classes 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
a59e0b48ba fix: function names 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
5e0ede4f8d fix: notes and concurrently 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
718b9741b7 feat: countAliveTokens and background 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
514e3ba0e8 fix: name and remove backgroudn 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
45d1fbc5ae test: async context test 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
dfa8bf7a81 feat: add selector.cancelled function 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
0495667e6f fix: comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
5a1aa2ea06 feat: add contextual monad 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
71abb2a3e8 fix: comment 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
fcfe7e98b9 fix: comments 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
a6e7210793 feat: context 2025-12-17 20:57:07 -03:00
Sofia Rodrigues
40f26ec349 feat: future 2025-12-17 19:28:01 -03:00
835 changed files with 19544 additions and 3215 deletions

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: actionlint
uses: raven-actions/actionlint@v2
with:

View File

@@ -67,13 +67,13 @@ jobs:
if: runner.os == 'macOS'
- name: Checkout
if: (!endsWith(matrix.os, '-with-cache'))
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
# the default is to use a virtual merge commit between the PR and master: just use the PR
ref: ${{ github.event.pull_request.head.sha }}
- name: Namespace Checkout
if: endsWith(matrix.os, '-with-cache')
uses: namespacelabs/nscloud-checkout-action@v7
uses: namespacelabs/nscloud-checkout-action@v8
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Open Nix shell once

View File

@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
# the default is to use a virtual merge commit between the PR and master: just use the PR
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -8,7 +8,7 @@ jobs:
check-stage0-on-queue:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

View File

@@ -50,7 +50,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
# don't schedule nightlies on forks
if: github.event_name == 'schedule' && github.repository == 'leanprover/lean4' || inputs.action == 'release nightly' || (startsWith(github.ref, 'refs/tags/') && github.repository == 'leanprover/lean4')
- name: Set Nightly
@@ -434,7 +434,7 @@ jobs:
with:
path: artifacts
- name: Release
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
with:
files: artifacts/*/*
fail_on_unmatched_files: true
@@ -455,7 +455,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
# needed for tagging
fetch-depth: 0
@@ -480,7 +480,7 @@ jobs:
echo -e "\n*Full commit log*\n" >> diff.md
git log --oneline "$last_tag"..HEAD | sed 's/^/* /' >> diff.md
- name: Release Nightly
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
with:
body_path: diff.md
prerelease: true

View File

@@ -6,7 +6,7 @@ jobs:
check-lean-files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Verify .lean files start with a copyright header.
run: |

View File

@@ -71,7 +71,7 @@ jobs:
GH_TOKEN: ${{ secrets.PR_RELEASES_TOKEN }}
- name: Release (short format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }}
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -86,7 +86,7 @@ jobs:
- name: Release (SHA-suffixed format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }} (${{ steps.workflow-info.outputs.sourceHeadSha }})
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -387,7 +387,7 @@ jobs:
# Checkout the Batteries repository with all branches
- name: Checkout Batteries repository
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: leanprover-community/batteries
token: ${{ secrets.MATHLIB4_BOT }}
@@ -447,7 +447,7 @@ jobs:
# Checkout the mathlib4 repository with all branches
- name: Checkout mathlib4 repository
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: leanprover-community/mathlib4-nightly-testing
token: ${{ secrets.MATHLIB4_BOT }}
@@ -530,7 +530,7 @@ jobs:
# Checkout the reference manual repository with all branches
- name: Checkout mathlib4 repository
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: leanprover/reference-manual
token: ${{ secrets.MANUAL_PR_BOT }}

View File

@@ -27,7 +27,7 @@ jobs:
# This action should push to an otherwise protected branch, so it
# uses a deploy key with write permissions, as suggested at
# https://stackoverflow.com/a/76135647/946226
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ssh-key: ${{secrets.STAGE0_SSH_KEY}}
- run: echo "should_update_stage0=yes" >> "$GITHUB_ENV"

View File

@@ -810,7 +810,7 @@ Docstrings for constants should have the following structure:
The **short summary** should be 13 sentences (ideally 1) and provide
enough information for most readers to quickly decide whether the
docstring is relevant to their task. The first (or only) sentence of
constant is relevant to their task. The first (or only) sentence of
the short summary should be a *sentence fragment* in which the subject
is implied to be the documented item, written in present tense
indicative, or a *noun phrase* that characterizes the documented
@@ -1123,6 +1123,110 @@ infix:50 " ⇔ " => Bijection
recommended_spelling "bij" for "⇔" in [Bijection, «term_⇔_»]
```
#### Tactics
Docstrings for tactics should have the following structure:
* Short summary
* Details
* Variants
* Examples
Sometimes more than one declaration is needed to implement what the user
sees as a single tactic. In that case, only one declaration should have
the associated docstring, and the others should have the `tactic_alt`
attribute to mark them as an implementation detail.
The **short summary** should be 13 sentences (ideally 1) and provide
enough information for most readers to quickly decide whether the
tactic is relevant to their task. The first (or only) sentence of
the short summary should be a full sentence in which the subject
is an example invocation of the tactic, written in present tense
indicative. If the example tactic invocation names parameters, then the
short summary may refer to them. For the example invocation, prefer the
simplest or most typical example. Explain more complicated forms in the
variants section. If needed, abbreviate the invocation by naming part of
the syntax and expanding it in the next sentence. The summary should be
written as a single paragraph.
**Details**, if needed, may be 1-3 paragraphs that describe further
relevant information. They may insert links as needed. This section
should fully explain the scope of the tactic: its syntax format,
on which goals it works and what the resulting goal(s) look like. It
should be clear whether the tactic fails if it does not close the main
goal and whether it creates any side goals. The details may include
explanatory examples that cant necessarily be machine checked and
dont fit the format.
If the tactic is extensible using `macro_rules`, mention this in the
details, with a link to `lean-manual://section/tactic-macro-extension`
and give a one-line example. If the tactic provides an attribute or a
command that allows the user to extend its behavior, the documentation
on how to extend the tactic belongs to that attribute or command. In the
tactic docstring, use a single sentence to refer the reader to this
further documentation.
**Variants**, if needed, should be a bulleted list describing different
options and forms of the same tactic. The reader should be able to parse
and understand the parts of a tactic invocation they are hovering over,
using this list. Each list item should describe an individual variant
and take one of two formats: the **short summary** as above, or a
**named list item**. A named list item consists of a title in bold
followed by an indented short paragraph.
Variants should be explained from the perspective of the tactic's users, not
their implementers. A tactic that is implemented as a single Lean parser may
have multiple variants from the perspective of users, while a tactic that is
implemented as multiple parsers may have no variants, but merely an optional
part of the syntax.
**Examples** should start with the line `Examples:` (or `Example:` if
theres exactly one). The section should consist of a sequence of code
blocks, each showing a Lean declaration (usually with the `example`
keyword) that invokes the tactic. When the effect of the tactic is not
clear from the code, you can use code comments to describe this. Do
not include text between examples, because it can be unclear whether
the text refers to the code before or after the example.
##### Example
````
`rw [e]` uses the expression `e` as a rewrite rule on the main goal,
then tries to close the goal by "cheap" (reducible) `rfl`.
If `e` is a defined constant, then the equational theorems associated with `e`
are used. This provides a convenient way to unfold `e`. If `e` has parameters,
the tactic will try to fill these in by unification with the matching part of
the target. Parameters are only filled in once per rule, restricting which
later rewrites can be found. Parameters that are not filled in after
unification will create side goals. If the `rfl` fails to close the main goal,
no error is raised.
`rw` may fail to rewrite terms "under binders", such as `∀ x, ...` or `∃ x,
...`. `rw` can also fail with a "motive is type incorrect" error in the context
of dependent types. In these cases, consider using `simp only`.
* `rw [e₁, ... eₙ]` applies the given rules sequentially.
* `rw [← e]` or `rw [<- e]` applies the rewrite in the reverse direction.
* `rw [e] at l` rewrites with `e` at location(s) `l`.
* `rw (occs := .pos L) [e]`, where `L` is a literal list of natural numbers,
only rewrites the given occurrences in the target. Occurrences count from 1.
* `rw (occs := .neg L) [e]`, where `L` is a literal list of natural numbers,
skips rewriting the given occurrences in the target. Occurrences count from 1.
Examples:
```lean
example {a b : Nat} (h : a + a = b) : (a + a) + (a + a) = b + b := by rw [h]
```
```lean
example {f : Nat -> Nat} (h : ∀ x, f x = 1) (a b : Nat) : f a = f b := by
rw [h] -- `rw` instantiates `h` only once, so this is equivalent to: `rw [h a]`
-- goal: ⊢ 1 = f b
rw [h] -- equivalent to: `rw [h b]`
```
````
## Dictionary

View File

@@ -338,12 +338,14 @@ where
deps := deps.union k {indMod}
return deps
abbrev Explanations := Std.HashMap (ModuleIdx × NeedsKind) (Option (Name × Name))
/--
Calculates the same as `calcNeeds` but tracing each module to a use-def declaration pair or
`none` if merely a recorded extra use.
-/
def getExplanations (env : Environment) (i : ModuleIdx) :
Std.HashMap (ModuleIdx × NeedsKind) (Option (Name × Name)) := Id.run do
def getExplanations (s : State) (i : ModuleIdx) : Explanations := Id.run do
let env := s.env
let mut deps := default
for ci in env.header.moduleData[i]!.constants do
-- Added guard for cases like `structure` that are still exported even if private
@@ -364,18 +366,25 @@ def getExplanations (env : Environment) (i : ModuleIdx) :
where
/-- Accumulate the results from expression `e` into `deps`. -/
visitExpr (k : NeedsKind) name e deps :=
let env := s.env
Lean.Expr.foldConsts e deps fun c deps => Id.run do
let mut deps := deps
if let some c := getDepConstName? env c then
if let some j := env.getModuleIdxFor? c then
let k := { k with isMeta := k.isMeta && !isDeclMeta' env c }
if
if let some (some (name', _)) := deps[(j, k)]? then
decide (name.toString.length < name'.toString.length)
else true
then
deps := deps.insert (j, k) (name, c)
deps := addExplanation j k name c deps
for indMod in (indirectModUseExt.getState env)[c]?.getD #[] do
if s.transDeps[i]!.has k indMod then
deps := addExplanation indMod k name (`_indirect ++ c) deps
return deps
addExplanation (j : ModuleIdx) (k : NeedsKind) (use def_ : Name) (deps : Explanations) : Explanations :=
if
if let some (some (name', _)) := deps[(j, k)]? then
decide (use.toString.length < name'.toString.length)
else true
then
deps.insert (j, k) (use, def_)
else deps
partial def initStateFromEnv (env : Environment) : State := Id.run do
let mut s := { env }
@@ -542,7 +551,7 @@ def visitModule (pkg : Name) (srcSearchPath : SearchPath)
let mut imp : Import := { k with module := s.modNames[j]! }
let mut j := j
if args.trace then
IO.eprintln s!"`{imp}` is needed"
IO.eprintln s!"`{imp}` is needed{if needs.has k j then " (calculated)" else ""}"
if args.addPublic && !k.isExported &&
-- also add as public if previously `public meta`, which could be from automatic porting
(s.transDepsOrig[i]!.has { k with isExported := true } j || s.transDepsOrig[i]!.has { k with isExported := true, isMeta := true } j) then
@@ -660,7 +669,7 @@ def visitModule (pkg : Name) (srcSearchPath : SearchPath)
modify fun s => { s with transDeps := s.transDeps.set! i newTransDepsI }
if args.explain then
let explanation := getExplanations s.env i
let explanation := getExplanations s i
let sanitize n := if n.hasMacroScopes then (sanitizeName n).run' { options := {} } else n
let run (imp : Import) := do
let j := s.env.getModuleIdx? imp.module |>.get!

View File

@@ -142,3 +142,15 @@ repositories:
branch: master
dependencies:
- verso-web-components
- name: comparator
url: https://github.com/leanprover/comparator
toolchain-tag: true
stable-branch: false
branch: master
- name: lean4export
url: https://github.com/leanprover/lean4export
toolchain-tag: true
stable-branch: false
branch: master

View File

@@ -695,7 +695,7 @@ endif()
set(STDLIBS Init Std Lean Leanc)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
list(APPEND STDLIBS Lake)
list(APPEND STDLIBS Lake LeanChecker)
endif()
add_custom_target(make_stdlib ALL
@@ -758,6 +758,12 @@ if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
DEPENDS lake_shared
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make lake
VERBATIM)
add_custom_target(leanchecker ALL
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
DEPENDS lake_shared
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make leanchecker
VERBATIM)
endif()
if(PREV_STAGE)

View File

@@ -102,7 +102,7 @@ noncomputable def strongIndefiniteDescription {α : Sort u} (p : α → Prop) (h
xp.val, fun _ => xp.property)
(fun hp => choice h, fun h => absurd h hp)
/-- the Hilbert epsilon Function -/
/-- The Hilbert epsilon function. -/
noncomputable def epsilon {α : Sort u} [h : Nonempty α] (p : α Prop) : α :=
(strongIndefiniteDescription p h).val

View File

@@ -144,7 +144,7 @@ instance : ToBool Bool where
Converts the result of the monadic action `x` to a `Bool`. If it is `true`, returns it and ignores
`y`; otherwise, runs `y` and returns its result.
This a monadic counterpart to the short-circuiting `||` operator, usually accessed via the `<||>`
This is a monadic counterpart to the short-circuiting `||` operator, usually accessed via the `<||>`
operator.
-/
@[macro_inline] def orM {m : Type u Type v} {β : Type u} [Monad m] [ToBool β] (x y : m β) : m β := do
@@ -161,7 +161,7 @@ recommended_spelling "orM" for "<||>" in [orM, «term_<||>_»]
Converts the result of the monadic action `x` to a `Bool`. If it is `true`, returns `y`; otherwise,
returns the original result of `x`.
This a monadic counterpart to the short-circuiting `&&` operator, usually accessed via the `<&&>`
This is a monadic counterpart to the short-circuiting `&&` operator, usually accessed via the `<&&>`
operator.
-/
@[macro_inline] def andM {m : Type u Type v} {β : Type u} [Monad m] [ToBool β] (x y : m β) : m β := do

View File

@@ -337,7 +337,7 @@ inductive Exists {α : Sort u} (p : α → Prop) : Prop where
An indication of whether a loop's body terminated early that's used to compile the `for x in xs`
notation.
A collection's `ForIn` or `ForIn'` instance describe's how to iterate over its elements. The monadic
A collection's `ForIn` or `ForIn'` instance describes how to iterate over its elements. The monadic
action that represents the body of the loop returns a `ForInStep α`, where `α` is the local state
used to implement features such as `let mut`.
-/
@@ -510,12 +510,12 @@ abbrev SSuperset [HasSSubset α] (a b : α) := SSubset b a
/-- Notation type class for the union operation ``. -/
class Union (α : Type u) where
/-- `a b` is the union of`a` and `b`. -/
/-- `a b` is the union of `a` and `b`. -/
union : α α α
/-- Notation type class for the intersection operation `∩`. -/
class Inter (α : Type u) where
/-- `a ∩ b` is the intersection of`a` and `b`. -/
/-- `a ∩ b` is the intersection of `a` and `b`. -/
inter : α α α
/-- Notation type class for the set difference `\`. -/
@@ -538,10 +538,10 @@ infix:50 " ⊇ " => Superset
/-- Strict superset relation: `a ⊃ b` -/
infix:50 "" => SSuperset
/-- `a b` is the union of`a` and `b`. -/
/-- `a b` is the union of `a` and `b`. -/
infixl:65 " " => Union.union
/-- `a ∩ b` is the intersection of`a` and `b`. -/
/-- `a ∩ b` is the intersection of `a` and `b`. -/
infixl:70 "" => Inter.inter
/--

View File

@@ -125,6 +125,22 @@ instance instDecidableEmpEq (ys : Array α) : Decidable (#[] = ys) :=
| [] => isTrue rfl
| _ :: _ => isFalse (fun h => Array.noConfusion rfl (heq_of_eq h) (fun h => List.noConfusion rfl h))
@[inline]
def instDecidableEqEmpImpl (xs : Array α) : Decidable (xs = #[]) :=
decidable_of_iff xs.isEmpty <| by rcases xs with <;> simp [Array.isEmpty]
@[inline]
def instDecidableEmpEqImpl (xs : Array α) : Decidable (#[] = xs) :=
decidable_of_iff xs.isEmpty <| by rcases xs with <;> simp [Array.isEmpty]
@[csimp]
theorem instDecidableEqEmp_csimp : @instDecidableEqEmp = @instDecidableEqEmpImpl :=
Subsingleton.allEq _ _
@[csimp]
theorem instDecidableEmpEq_csimp : @instDecidableEmpEq = @instDecidableEmpEqImpl :=
Subsingleton.allEq _ _
theorem beq_eq_decide [BEq α] (xs ys : Array α) :
(xs == ys) = if h : xs.size = ys.size then
decide ( (i : Nat) (h' : i < xs.size), xs[i] == ys[i]'(h h')) else false := by

View File

@@ -115,7 +115,8 @@ theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.si
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]?
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]? where
guard xs.size i
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..

View File

@@ -67,6 +67,9 @@ theorem none_eq_getElem?_iff {l : BitVec w} : none = l[n]? ↔ w ≤ n := by
@[simp]
theorem getElem?_eq_none {l : BitVec w} (h : w n) : l[n]? = none := getElem?_eq_none_iff.mpr h
grind_pattern BitVec.getElem?_eq_none => l[n]? where
guard w n
theorem getElem?_eq (l : BitVec w) (i : Nat) :
l[i]? = if h : i < w then some l[i] else none := by
split <;> simp_all

View File

@@ -113,6 +113,8 @@ theorem gcd_eq_right_iff_dvd (hb : 0 ≤ b) : gcd a b = b ↔ b a := by
theorem gcd_assoc (a b c : Int) : gcd (gcd a b) c = gcd a (gcd b c) := Nat.gcd_assoc ..
theorem gcd_left_comm (a b c : Int) : gcd a (gcd b c) = gcd b (gcd a c) := Nat.gcd_left_comm ..
theorem gcd_mul_left (m n k : Int) : gcd (m * n) (m * k) = m.natAbs * gcd n k := by
simp [gcd_eq_natAbs_gcd_natAbs, Nat.gcd_mul_left, natAbs_mul]

View File

@@ -10,6 +10,7 @@ public import Init.Classical
public import Init.Ext
set_option doc.verso true
set_option linter.missingDocs true
public section
@@ -349,14 +350,24 @@ abbrev PlausibleIterStep.casesOn {IsPlausibleStep : IterStep α β → Prop}
end IterStep
/--
The typeclass providing the step function of an iterator in `Iter (α := α) β` or
`IterM (α := α) m β`.
The step function of an iterator in `Iter (α := α) β` or `IterM (α := α) m β`.
In order to allow intrinsic termination proofs when iterating with the `step` function, the
step object is bundled with a proof that it is a "plausible" step for the given current iterator.
-/
class Iterator (α : Type w) (m : Type w Type w') (β : outParam (Type w)) where
/--
A relation that governs the allowed steps from a given iterator.
The "plausible" steps are those which make sense for a given state; plausibility can ensure
properties such as the successor iterator being drawn from the same collection, that an iterator
resulting from a skip will return the same next value, or that the next item yielded is next one
in the original collection.
-/
IsPlausibleStep : IterM (α := α) m β IterStep (IterM (α := α) m β) β Prop
/--
Carries out a step of iteration.
-/
step : (it : IterM (α := α) m β) m (Shrink <| PlausibleIterStep <| IsPlausibleStep it)
section Monadic
@@ -369,7 +380,7 @@ def IterM.mk {α : Type w} (it : α) (m : Type w → Type w') (β : Type w) :
IterM (α := α) m β :=
it
@[deprecated IterM.mk (since := "2025-12-01"), inline, expose]
@[deprecated IterM.mk (since := "2025-12-01"), inline, expose, inherit_doc IterM.mk]
def Iterators.toIterM := @IterM.mk
@[simp]
@@ -377,6 +388,7 @@ theorem IterM.mk_internalState {α m β} (it : IterM (α := α) m β) :
.mk it.internalState m β = it :=
rfl
set_option linter.missingDocs false in
@[deprecated IterM.mk_internalState (since := "2025-12-01")]
def Iterators.toIterM_internalState := @IterM.mk_internalState
@@ -459,8 +471,10 @@ number of steps.
-/
inductive IterM.IsPlausibleIndirectOutput {α β : Type w} {m : Type w Type w'} [Iterator α m β]
: IterM (α := α) m β β Prop where
/-- The output value could plausibly be emitted in the next step. -/
| direct {it : IterM (α := α) m β} {out : β} : it.IsPlausibleOutput out
it.IsPlausibleIndirectOutput out
/-- The output value could plausibly be emitted in a step after the next step. -/
| indirect {it it' : IterM (α := α) m β} {out : β} : it'.IsPlausibleSuccessorOf it
it'.IsPlausibleIndirectOutput out it.IsPlausibleIndirectOutput out
@@ -470,7 +484,9 @@ finitely many steps. This relation is reflexive.
-/
inductive IterM.IsPlausibleIndirectSuccessorOf {α β : Type w} {m : Type w Type w'}
[Iterator α m β] : IterM (α := α) m β IterM (α := α) m β Prop where
/-- Every iterator is a plausible indirect successor of itself. -/
| refl (it : IterM (α := α) m β) : it.IsPlausibleIndirectSuccessorOf it
/-- The iterator is a plausible successor of one of the current iterator's successors. -/
| cons_right {it'' it' it : IterM (α := α) m β} (h' : it''.IsPlausibleIndirectSuccessorOf it')
(h : it'.IsPlausibleSuccessorOf it) : it''.IsPlausibleIndirectSuccessorOf it
@@ -595,8 +611,10 @@ number of steps.
-/
inductive Iter.IsPlausibleIndirectOutput {α β : Type w} [Iterator α Id β] :
Iter (α := α) β β Prop where
/-- The output value could plausibly be emitted in the next step. -/
| direct {it : Iter (α := α) β} {out : β} : it.IsPlausibleOutput out
it.IsPlausibleIndirectOutput out
/-- The output value could plausibly be emitted in a step after the next step. -/
| indirect {it it' : Iter (α := α) β} {out : β} : it'.IsPlausibleSuccessorOf it
it'.IsPlausibleIndirectOutput out it.IsPlausibleIndirectOutput out
@@ -627,7 +645,9 @@ finitely many steps. This relation is reflexive.
-/
inductive Iter.IsPlausibleIndirectSuccessorOf {α : Type w} {β : Type w} [Iterator α Id β] :
Iter (α := α) β Iter (α := α) β Prop where
/-- Every iterator is a plausible indirect successor of itself. -/
| refl (it : Iter (α := α) β) : IsPlausibleIndirectSuccessorOf it it
/-- The iterator is a plausible indirect successor of one of the current iterator's successors. -/
| cons_right {it'' it' it : Iter (α := α) β} (h' : it''.IsPlausibleIndirectSuccessorOf it')
(h : it'.IsPlausibleSuccessorOf it) : it''.IsPlausibleIndirectSuccessorOf it
@@ -701,6 +721,11 @@ recursion over finite iterators. See also `IterM.finitelyManySteps` and `Iter.fi
-/
structure IterM.TerminationMeasures.Finite
(α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β] where
/--
The wrapped iterator.
In the wrapper, its finiteness is used as a termination measure.
-/
it : IterM (α := α) m β
/--
@@ -827,6 +852,11 @@ recursion over productive iterators. See also `IterM.finitelyManySkips` and `Ite
-/
structure IterM.TerminationMeasures.Productive
(α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β] where
/--
The wrapped iterator.
In the wrapper, its productivity is used as a termination measure.
-/
it : IterM (α := α) m β
/--
@@ -930,6 +960,9 @@ library.
-/
class LawfulDeterministicIterator (α : Type w) (m : Type w Type w') [Iterator α m β]
where
/--
Every iterator with state `α` in monad `m` has exactly one plausible step.
-/
isPlausibleStep_eq_eq : it : IterM (α := α) m β, step, it.IsPlausibleStep = (· = step)
namespace Iterators
@@ -940,14 +973,13 @@ This structure provides a more convenient way to define `Finite α m` instances
-/
structure FinitenessRelation (α : Type w) (m : Type w Type w') {β : Type w}
[Iterator α m β] where
/-
A well-founded relation such that if `it'` is a successor iterator of `it`, then
`Rel it' it`.
/--
A well-founded relation such that if `it'` is a successor iterator of `it`, then `Rel it' it`.
-/
Rel (it' it : IterM (α := α) m β) : Prop
/- A proof that `Rel` is well-founded. -/
/-- `Rel` is well-founded. -/
wf : WellFounded Rel
/- A proof that if `it'` is a successor iterator of `it`, then `Rel it' it`. -/
/-- If `it'` is a successor iterator of `it`, then `Rel it' it`. -/
subrelation : {it it'}, it'.IsPlausibleSuccessorOf it Rel it' it
theorem Finite.of_finitenessRelation
@@ -967,14 +999,13 @@ This structure provides a more convenient way to define `Productive α m` instan
-/
structure ProductivenessRelation (α : Type w) (m : Type w Type w') {β : Type w}
[Iterator α m β] where
/-
A well-founded relation such that if `it'` is obtained from `it` by skipping, then
`Rel it' it`.
/--
A well-founded relation such that if `it'` is obtained from `it` by skipping, then `Rel it' it`.
-/
Rel : (IterM (α := α) m β) (IterM (α := α) m β) Prop
/- A proof that `Rel` is well-founded. -/
/-- `Rel` is well-founded. -/
wf : WellFounded Rel
/- A proof that if `it'` is obtained from `it` by skipping, then `Rel it' it`. -/
/-- If `it'` is obtained from `it` by skipping, then `Rel it' it`. -/
subrelation : {it it'}, it'.IsPlausibleSkipSuccessorOf it Rel it' it
theorem Productive.of_productivenessRelation

View File

@@ -9,6 +9,8 @@ prelude
public import Init.Data.Iterators.Consumers.Loop
public import Init.Data.Iterators.Consumers.Monadic.Access
set_option linter.missingDocs true
@[expose] public section
namespace Std

View File

@@ -8,6 +8,8 @@ module
prelude
public import Init.Data.Iterators.Basic
set_option linter.missingDocs true
public section
namespace Std
@@ -57,8 +59,8 @@ theorem IterM.not_isPlausibleNthOutputStep_yield {α β : Type w} {m : Type w
/--
`IteratorAccess α m` provides efficient implementations for random access or iterators that support
it. `it.nextAtIdx? n` either returns the step in which the `n`-th value of `it` is emitted
(necessarily of the form `.yield _ _`) or `.done` if `it` terminates before emitting the `n`-th
it. `it.nextAtIdx? n` either returns the step in which the `n`th value of `it` is emitted
(necessarily of the form `.yield _ _`) or `.done` if `it` terminates before emitting the `n`th
value.
For monadic iterators, the monadic effects of this operation may differ from manually iterating
@@ -68,6 +70,11 @@ is guaranteed to plausible in the sense of `IterM.IsPlausibleNthOutputStep`.
This class is experimental and users of the iterator API should not explicitly depend on it.
-/
class IteratorAccess (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β] where
/--
`nextAtIdx? it n` either returns the step in which the `n`th value of `it` is emitted
(necessarily of the form `.yield _ _`) or `.done` if `it` terminates before emitting the `n`th
value.
-/
nextAtIdx? (it : IterM (α := α) m β) (n : Nat) :
m (PlausibleIterStep (it.IsPlausibleNthOutputStep n))

View File

@@ -11,6 +11,8 @@ public import Init.Data.Iterators.Consumers.Monadic.Total
public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
public import Init.WFExtrinsicFix
set_option linter.missingDocs true
@[expose] public section
/-!

View File

@@ -11,6 +11,8 @@ public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
public import Init.WFExtrinsicFix
public import Init.Data.Iterators.Consumers.Monadic.Total
set_option linter.missingDocs true
public section
/-!
@@ -70,6 +72,9 @@ provided by the standard library.
@[ext]
class IteratorLoop (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
(n : Type x Type x') where
/--
Iteration over the iterator `it` in the manner expected by `for` loops.
-/
forIn : (_liftBind : (γ : Type w) (δ : Type x) (γ n δ) m γ n δ) (γ : Type x),
(plausible_forInStep : β γ ForInStep γ Prop)
(it : IterM (α := α) m β) γ
@@ -82,7 +87,9 @@ end Typeclasses
structure IteratorLoop.WithWF (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
{γ : Type x} (PlausibleForInStep : β γ ForInStep γ Prop)
(hwf : IteratorLoop.WellFounded α m PlausibleForInStep) where
/-- Internal implementation detail of the iterator library. -/
it : IterM (α := α) m β
/-- Internal implementation detail of the iterator library. -/
acc : γ
instance IteratorLoop.WithWF.instWellFoundedRelation
@@ -163,6 +170,7 @@ Asserts that a given `IteratorLoop` instance is equal to `IteratorLoop.defaultIm
-/
class LawfulIteratorLoop (α : Type w) (m : Type w Type w') (n : Type x Type x')
[Monad m] [Monad n] [Iterator α m β] [i : IteratorLoop α m n] where
/-- The implementation of `IteratorLoop.forIn` in `i` is equal to the default implementation. -/
lawful lift [LawfulMonadLiftBindFunction lift] γ it init
(Pl : β γ ForInStep γ Prop) (wf : IteratorLoop.WellFounded α m Pl)
(f : (b : β) it.IsPlausibleIndirectOutput b (c : γ) n (Subtype (Pl b c))) :
@@ -219,6 +227,7 @@ instance IterM.instForInOfIteratorLoop {m : Type w → Type w'} {n : Type w →
haveI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
instForInOfForIn'
/-- Internal implementation detail of the iterator library. -/
@[always_inline, inline]
def IterM.Partial.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoop α m n] [MonadLiftT m n] [Monad n] :
@@ -226,6 +235,7 @@ def IterM.Partial.instForIn' {m : Type w → Type w'} {n : Type w → Type w''}
forIn' it init f :=
haveI := @IterM.instForIn'; forIn' it.it init f
/-- Internal implementation detail of the iterator library. -/
@[always_inline, inline]
def IterM.Total.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoop α m n] [MonadLiftT m n] [Monad n]

View File

@@ -8,6 +8,8 @@ module
prelude
public import Init.Data.Iterators.Basic
set_option linter.missingDocs true
public section
namespace Std
@@ -16,6 +18,9 @@ namespace Std
A wrapper around an iterator that provides partial consumers. See `IterM.allowNontermination`.
-/
structure IterM.Partial {α : Type w} (m : Type w Type w') (β : Type w) where
/--
The wrapped iterator, which was wrapped by `IterM.allowNontermination`.
-/
it : IterM (α := α) m β
/--

View File

@@ -9,12 +9,19 @@ prelude
public import Init.Data.Iterators.Basic
set_option doc.verso true
set_option linter.missingDocs true
public section
namespace Std
/--
A wrapper around an iterator that provides total consumers. See `IterM.ensureTermination`.
-/
structure IterM.Total {α : Type w} (m : Type w Type w') (β : Type w) where
/--
The wrapped iterator, which was wrapped by `IterM.ensureTermination`.
-/
it : IterM (α := α) m β
/--

View File

@@ -8,6 +8,8 @@ module
prelude
public import Init.Data.Iterators.Basic
set_option linter.missingDocs true
public section
namespace Std
@@ -16,6 +18,9 @@ namespace Std
A wrapper around an iterator that provides partial consumers. See `Iter.allowNontermination`.
-/
structure Iter.Partial {α : Type w} (β : Type w) where
/--
The wrapped iterator, which was wrapped by `Iter.allowNontermination`.
-/
it : Iter (α := α) β
/--

View File

@@ -9,6 +9,8 @@ prelude
public import Init.Data.Stream
public import Init.Data.Iterators.Consumers.Access
set_option linter.missingDocs true
public section
namespace Std

View File

@@ -9,12 +9,19 @@ prelude
public import Init.Data.Iterators.Basic
set_option doc.verso true
set_option linter.missingDocs true
public section
namespace Std
/--
A wrapper around an iterator that provides total consumers. See `Iter.ensureTermination`.
-/
structure Iter.Total {α : Type w} (β : Type w) where
/--
The wrapped iterator, which was wrapped by `Iter.ensureTermination`.
-/
it : Iter (α := α) β
/--

View File

@@ -9,3 +9,4 @@ prelude
public import Init.Data.Iterators.Lemmas.Consumers.Monadic
public import Init.Data.Iterators.Lemmas.Consumers.Collect
public import Init.Data.Iterators.Lemmas.Consumers.Loop
public import Init.Data.Iterators.Lemmas.Consumers.Access

View File

@@ -0,0 +1,26 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
public import Init.Data.Iterators.Consumers.Access
namespace Std.Iter
open Std.Iterators
public theorem atIdxSlow?_eq_match [Iterator α Id β] [Productive α Id]
{n : Nat} {it : Iter (α := α) β} :
it.atIdxSlow? n =
(match it.step.val with
| .yield it' out =>
match n with
| 0 => some out
| n + 1 => it'.atIdxSlow? n
| .skip it' => it'.atIdxSlow? n
| .done => none) := by
fun_induction it.atIdxSlow? n <;> simp_all
end Std.Iter

View File

@@ -72,7 +72,7 @@ def PostconditionT.liftWithProperty {α : Type w} {m : Type w → Type w'} {P :
P, x
/--
Given a function `f : α → β`, returns a a function `PostconditionT m α → PostconditionT m β`,
Given a function `f : α → β`, returns a function `PostconditionT m α → PostconditionT m β`,
turning `PostconditionT m` into a functor.
The postcondition of the `x.map f` states that the return value is the image under `f` of some
@@ -85,7 +85,7 @@ protected def PostconditionT.map {m : Type w → Type w'} [Functor m] {α : Type
(fun a => f a.val, _, rfl) <$> x.operation
/--
Given a function `α → PostconditionT m β`, returns a a function
Given a function `α → PostconditionT m β`, returns a function
`PostconditionT m α → PostconditionT m β`, turning `PostconditionT m` into a monad.
-/
@[always_inline, inline, expose]
@@ -287,6 +287,12 @@ theorem PostconditionT.run_attachLift {m : Type w → Type w'} [Monad m] [MonadA
{x : m α} : (attachLift x).run = x := by
simp [attachLift, run_eq_map, WeaklyLawfulMonadAttach.map_attach]
@[simp]
theorem PostconditionT.operation_attachLift {m : Type w Type w'} [Monad m] [MonadAttach m]
{α : Type w} {x : m α} : (attachLift x : PostconditionT m α).operation =
MonadAttach.attach x := by
rfl
instance {m : Type w Type w'} {n : Type w Type w''} [MonadLift m n] :
MonadLift (PostconditionT m) (PostconditionT n) where
monadLift x := _, monadLift x.operation

View File

@@ -11,7 +11,7 @@ public import Init.Core
public section
/--
The `BEq α` and `Hashable α` instances on `α` are compatible. This means that that `a == b` implies
The `BEq α` and `Hashable α` instances on `α` are compatible. This means that `a == b` implies
`hash a = hash b`.
This is automatic if the `BEq` instance is lawful.

View File

@@ -169,10 +169,10 @@ Examples:
| a::as, b::bs, eqv => eqv a b && isEqv as bs eqv
| _, _, _ => false
@[simp] theorem isEqv_nil_nil : isEqv ([] : List α) [] eqv = true := rfl
@[simp] theorem isEqv_nil_cons : isEqv ([] : List α) (a::as) eqv = false := rfl
@[simp] theorem isEqv_cons_nil : isEqv (a::as : List α) [] eqv = false := rfl
theorem isEqv_cons₂ : isEqv (a::as) (b::bs) eqv = (eqv a b && isEqv as bs eqv) := rfl
@[simp, grind =] theorem isEqv_nil_nil : isEqv ([] : List α) [] eqv = true := rfl
@[simp, grind =] theorem isEqv_nil_cons : isEqv ([] : List α) (a::as) eqv = false := rfl
@[simp, grind =] theorem isEqv_cons_nil : isEqv (a::as : List α) [] eqv = false := rfl
@[grind =] theorem isEqv_cons₂ : isEqv (a::as) (b::bs) eqv = (eqv a b && isEqv as bs eqv) := rfl
/-! ## Lexicographic ordering -/
@@ -717,6 +717,7 @@ Examples:
* `["red", "green", "blue"].leftpad 3 "blank" = ["red", "green", "blue"]`
* `["red", "green", "blue"].leftpad 1 "blank" = ["red", "green", "blue"]`
-/
@[simp, grind =]
def leftpad (n : Nat) (a : α) (l : List α) : List α := replicate (n - length l) a ++ l
@@ -730,6 +731,7 @@ Examples:
* `["red", "green", "blue"].rightpad 3 "blank" = ["red", "green", "blue"]`
* `["red", "green", "blue"].rightpad 1 "blank" = ["red", "green", "blue"]`
-/
@[simp, grind =]
def rightpad (n : Nat) (a : α) (l : List α) : List α := l ++ replicate (n - length l) a
/-! ### reduceOption -/

View File

@@ -50,7 +50,7 @@ Users that want to use `mapM` with `Applicative` should use `mapA` instead.
Applies the monadic action `f` to every element in the list, left-to-right, and returns the list of
results.
This implementation is tail recursive. `List.mapM'` is a a non-tail-recursive variant that may be
This implementation is tail recursive. `List.mapM'` is a non-tail-recursive variant that may be
more convenient to reason about. `List.forM` is the variant that discards the results and
`List.mapA` is the variant that works with `Applicative`.
-/
@@ -107,7 +107,7 @@ Applies the monadic action `f` to the corresponding elements of two lists, left-
at the end of the shorter list. `zipWithM f as bs` is equivalent to `mapM id (zipWith f as bs)`
for lawful `Monad` instances.
This implementation is tail recursive. `List.zipWithM'` is a a non-tail-recursive variant that may
This implementation is tail recursive. `List.zipWithM'` is a non-tail-recursive variant that may
be more convenient to reason about.
-/
@[inline, expose]

View File

@@ -2941,9 +2941,6 @@ theorem getLast?_replicate {a : α} {n : Nat} : (replicate n a).getLast? = if n
/-! ### leftpad -/
-- We unfold `leftpad` and `rightpad` for verification purposes.
attribute [simp, grind =] leftpad rightpad
-- `length_leftpad` and `length_rightpad` are in `Init.Data.List.Nat.Basic`.
theorem leftpad_prefix {n : Nat} {a : α} {l : List α} :

View File

@@ -223,6 +223,16 @@ theorem testBit_lt_two_pow {x i : Nat} (lt : x < 2^i) : x.testBit i = false := b
exfalso
exact Nat.not_le_of_gt lt (ge_two_pow_of_testBit p)
theorem testBit_of_two_pow_le_and_two_pow_add_one_gt {n i : Nat}
(hle : 2^i n) (hgt : n < 2^(i + 1)) : n.testBit i = true := by
rcases exists_ge_and_testBit_of_ge_two_pow hle with i', _, _
have : i = i' := by
false_or_by_contra
have : 2 ^ (i + 1) 2 ^ i' := Nat.pow_le_pow_of_le (by decide) (by omega)
have : n.testBit i' = false := testBit_lt_two_pow (by omega)
simp_all only [Bool.false_eq_true]
rwa [this]
theorem lt_pow_two_of_testBit (x : Nat) (p : i, i n testBit x i = false) : x < 2^n := by
apply Decidable.by_contra
intro not_lt
@@ -231,6 +241,10 @@ theorem lt_pow_two_of_testBit (x : Nat) (p : ∀i, i ≥ n → testBit x i = fal
have test_false := p _ i_ge_n
simp [test_true] at test_false
theorem testBit_log2 {n : Nat} (h : n 0) : n.testBit n.log2 = true := by
have := log2_eq_iff (n := n) (k := n.log2) (by omega)
apply testBit_of_two_pow_le_and_two_pow_add_one_gt <;> omega
private theorem succ_mod_two : succ x % 2 = 1 - x % 2 := by
induction x with
| zero =>

View File

@@ -129,6 +129,9 @@ theorem gcd_assoc (m n k : Nat) : gcd (gcd m n) k = gcd m (gcd n k) :=
(Nat.dvd_trans (gcd_dvd_right m (gcd n k)) (gcd_dvd_right n k)))
instance : Std.Associative gcd := gcd_assoc
theorem gcd_left_comm (m n k : Nat) : gcd m (gcd n k) = gcd n (gcd m k) := by
rw [ gcd_assoc, gcd_assoc, gcd_comm m n]
@[simp] theorem gcd_one_right (n : Nat) : gcd n 1 = 1 := (gcd_comm n 1).trans (gcd_one_left n)
theorem gcd_mul_left (m n k : Nat) : gcd (m * n) (m * k) = m * gcd n k := by

View File

@@ -10,7 +10,7 @@ import all Init.Data.Nat.Bitwise.Basic
public import Init.Data.Nat.MinMax
public import Init.Data.Nat.Log2
import all Init.Data.Nat.Log2
public import Init.Data.Nat.Power2
public import Init.Data.Nat.Power2.Basic
public import Init.Data.Nat.Mod
import Init.TacticsExtra
import Init.BinderPredicates

View File

@@ -6,66 +6,5 @@ Authors: Leonardo de Moura
module
prelude
public import Init.Data.Nat.Linear
public section
namespace Nat
theorem nextPowerOfTwo_dec {n power : Nat} (h₁ : power > 0) (h₂ : power < n) : n - power * 2 < n - power := by
have : power * 2 = power + power := by simp +arith
rw [this, Nat.sub_add_eq]
exact Nat.sub_lt (Nat.zero_lt_sub_of_lt h₂) h₁
/--
Returns the least power of two that's greater than or equal to `n`.
Examples:
* `Nat.nextPowerOfTwo 0 = 1`
* `Nat.nextPowerOfTwo 1 = 1`
* `Nat.nextPowerOfTwo 2 = 2`
* `Nat.nextPowerOfTwo 3 = 4`
* `Nat.nextPowerOfTwo 5 = 8`
-/
def nextPowerOfTwo (n : Nat) : Nat :=
go 1 (by decide)
where
go (power : Nat) (h : power > 0) : Nat :=
if power < n then
go (power * 2) (Nat.mul_pos h (by decide))
else
power
termination_by n - power
decreasing_by simp_wf; apply nextPowerOfTwo_dec <;> assumption
/--
A natural number `n` is a power of two if there exists some `k : Nat` such that `n = 2 ^ k`.
-/
def isPowerOfTwo (n : Nat) := k, n = 2 ^ k
theorem isPowerOfTwo_one : isPowerOfTwo 1 :=
0, by decide
theorem isPowerOfTwo_mul_two_of_isPowerOfTwo (h : isPowerOfTwo n) : isPowerOfTwo (n * 2) :=
have k, h := h
k+1, by simp [h, Nat.pow_succ]
theorem pos_of_isPowerOfTwo (h : isPowerOfTwo n) : n > 0 := by
have k, h := h
rw [h]
apply Nat.pow_pos
decide
theorem isPowerOfTwo_nextPowerOfTwo (n : Nat) : n.nextPowerOfTwo.isPowerOfTwo := by
apply isPowerOfTwo_go
apply isPowerOfTwo_one
where
isPowerOfTwo_go (power : Nat) (h₁ : power > 0) (h₂ : power.isPowerOfTwo) : (nextPowerOfTwo.go n power h₁).isPowerOfTwo := by
unfold nextPowerOfTwo.go
split
. exact isPowerOfTwo_go (power*2) (Nat.mul_pos h₁ (by decide)) (Nat.isPowerOfTwo_mul_two_of_isPowerOfTwo h₂)
. assumption
termination_by n - power
decreasing_by simp_wf; apply nextPowerOfTwo_dec <;> assumption
end Nat
public import Init.Data.Nat.Power2.Basic
public import Init.Data.Nat.Power2.Lemmas

View File

@@ -0,0 +1,71 @@
/-
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Data.Nat.Linear
public section
namespace Nat
theorem nextPowerOfTwo_dec {n power : Nat} (h₁ : power > 0) (h₂ : power < n) : n - power * 2 < n - power := by
have : power * 2 = power + power := by simp +arith
rw [this, Nat.sub_add_eq]
exact Nat.sub_lt (Nat.zero_lt_sub_of_lt h₂) h₁
/--
Returns the least power of two that's greater than or equal to `n`.
Examples:
* `Nat.nextPowerOfTwo 0 = 1`
* `Nat.nextPowerOfTwo 1 = 1`
* `Nat.nextPowerOfTwo 2 = 2`
* `Nat.nextPowerOfTwo 3 = 4`
* `Nat.nextPowerOfTwo 5 = 8`
-/
def nextPowerOfTwo (n : Nat) : Nat :=
go 1 (by decide)
where
go (power : Nat) (h : power > 0) : Nat :=
if power < n then
go (power * 2) (Nat.mul_pos h (by decide))
else
power
termination_by n - power
decreasing_by simp_wf; apply nextPowerOfTwo_dec <;> assumption
/--
A natural number `n` is a power of two if there exists some `k : Nat` such that `n = 2 ^ k`.
-/
def isPowerOfTwo (n : Nat) := k, n = 2 ^ k
theorem isPowerOfTwo_one : isPowerOfTwo 1 :=
0, by decide
theorem isPowerOfTwo_mul_two_of_isPowerOfTwo (h : isPowerOfTwo n) : isPowerOfTwo (n * 2) :=
have k, h := h
k+1, by simp [h, Nat.pow_succ]
theorem pos_of_isPowerOfTwo (h : isPowerOfTwo n) : n > 0 := by
have k, h := h
rw [h]
apply Nat.pow_pos
decide
theorem isPowerOfTwo_nextPowerOfTwo (n : Nat) : n.nextPowerOfTwo.isPowerOfTwo := by
apply isPowerOfTwo_go
apply isPowerOfTwo_one
where
isPowerOfTwo_go (power : Nat) (h₁ : power > 0) (h₂ : power.isPowerOfTwo) : (nextPowerOfTwo.go n power h₁).isPowerOfTwo := by
unfold nextPowerOfTwo.go
split
. exact isPowerOfTwo_go (power*2) (Nat.mul_pos h₁ (by decide)) (Nat.isPowerOfTwo_mul_two_of_isPowerOfTwo h₂)
. assumption
termination_by n - power
decreasing_by simp_wf; apply nextPowerOfTwo_dec <;> assumption
end Nat

View File

@@ -0,0 +1,62 @@
/-
Copyright (c) George Rennie. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: George Rennie
-/
module
prelude
import all Init.Data.Nat.Power2.Basic
public import Init.Data.Nat.Bitwise.Lemmas
public section
/-!
# Further lemmas about `Nat.isPowerOfTwo`, with the convenience of having bitwise lemmas available.
-/
namespace Nat
theorem not_isPowerOfTwo_zero : ¬isPowerOfTwo 0 := by
rw [isPowerOfTwo, not_exists]
intro x
have := one_le_pow x 2 (by decide)
omega
theorem and_sub_one_testBit_log2 {n : Nat} (h : n 0) (hpow2 : ¬n.isPowerOfTwo) :
(n &&& (n - 1)).testBit n.log2 := by
rw [testBit_and, Bool.and_eq_true]
constructor
· exact testBit_log2 (by omega)
· by_cases n = 2^n.log2
· rw [isPowerOfTwo, not_exists] at hpow2
have := hpow2 n.log2
trivial
· have := log2_eq_iff (n := n) (k := n.log2) (by omega)
have : (n - 1).log2 = n.log2 := by rw [log2_eq_iff] <;> omega
rw [this]
exact testBit_log2 (by omega)
theorem and_sub_one_eq_zero_iff_isPowerOfTwo {n : Nat} (h : n 0) :
(n &&& (n - 1)) = 0 n.isPowerOfTwo := by
constructor
· intro hbitwise
false_or_by_contra
rename_i hpow2
have := and_sub_one_testBit_log2 h hpow2
rwa [hbitwise, zero_testBit n.log2, Bool.false_eq_true] at this
· intro hpow2
rcases hpow2 with _, hpow2
rw [hpow2, and_two_pow_sub_one_eq_mod, mod_self]
theorem ne_zero_and_sub_one_eq_zero_iff_isPowerOfTwo {n : Nat} :
((n 0) (n &&& (n - 1)) = 0) n.isPowerOfTwo := by
match h : n with
| 0 => simp [not_isPowerOfTwo_zero]
| n + 1 => simp; exact and_sub_one_eq_zero_iff_isPowerOfTwo (by omega)
@[inline]
instance {n : Nat} : Decidable n.isPowerOfTwo :=
decidable_of_iff _ ne_zero_and_sub_one_eq_zero_iff_isPowerOfTwo
end Nat

View File

@@ -46,7 +46,7 @@ theorem ne_of_cmp_ne_eq {α : Type u} {cmp : αα → Ordering} [Std.ReflCm
end ReflCmp
/-- A typeclasses for ordered types for which `compare a a = .eq` for all `a`. -/
/-- A typeclass for ordered types for which `compare a a = .eq` for all `a`. -/
abbrev ReflOrd (α : Type u) [Ord α] := ReflCmp (compare : α α Ordering)
@[simp]

View File

@@ -246,8 +246,12 @@ class InfinitelyUpwardEnumerable (α : Type u) [UpwardEnumerable α] where
This propositional typeclass ensures that `UpwardEnumerable.succ?` is injective.
-/
class LinearlyUpwardEnumerable (α : Type u) [UpwardEnumerable α] where
/-- The implementation of `UpwardEnumerable.succ?` for `α` is injective. -/
eq_of_succ?_eq : a b : α, UpwardEnumerable.succ? a = UpwardEnumerable.succ? b a = b
/--
If a type is infinitely upwardly enumerable, then every element has a successor.
-/
theorem UpwardEnumerable.isSome_succ? {α : Type u} [UpwardEnumerable α]
[InfinitelyUpwardEnumerable α] {a : α} : (succ? a).isSome :=
InfinitelyUpwardEnumerable.isSome_succ? a

View File

@@ -40,7 +40,7 @@ class Rcc.Sliceable (α : Type u) (β : outParam (Type v)) (γ : outParam (Type
This typeclass indicates how to obtain slices of elements of {lit}`α` over ranges in the index type
{lit}`β`, the ranges being left-closed right-open.
The type of resulting the slices is {lit}`γ`.
The type of the resulting slices is {lit}`γ`.
-/
class Rco.Sliceable (α : Type u) (β : outParam (Type v)) (γ : outParam (Type w)) where
/--

View File

@@ -1396,6 +1396,7 @@ scalar value.
public def IsUTF8FirstByte (c : UInt8) : Prop :=
c &&& 0x80 = 0 c &&& 0xe0 = 0xc0 c &&& 0xf0 = 0xe0 c &&& 0xf8 = 0xf0
@[inline]
public instance {c : UInt8} : Decidable c.IsUTF8FirstByte :=
inferInstanceAs <| Decidable (c &&& 0x80 = 0 c &&& 0xe0 = 0xc0 c &&& 0xf0 = 0xe0 c &&& 0xf8 = 0xf0)

View File

@@ -57,4 +57,10 @@ theorem length_map {f : Char → Char} {s : String} : (s.map f).length = s.lengt
theorem map_eq_empty {f : Char Char} {s : String} : s.map f = "" s = "" := by
simp [ toList_eq_nil_iff]
@[simp]
theorem map_idempotent {s : String} (h : (c : Char) f (f c) = f c) : (s.map f |>.map f) = s.map f := by
apply String.ext
simp [String.toList_map, List.map_map]
exact fun c _ => h c
end String

View File

@@ -230,7 +230,7 @@ Examples:
* `"Orange".toLower = "orange"`
* `"ABc123".toLower = "abc123"`
-/
@[inline] def toLower (s : String) : String :=
@[inline, expose] def toLower (s : String) : String :=
s.map Char.toLower
/--

View File

@@ -119,7 +119,7 @@ instance (s : Slice) : Std.Iterator (ForwardSliceSearcher s) Id (SearchStep s) w
-- **Invariant 1:** we have already covered everything up until `stackPos - needlePos` (exclusive),
-- with matches and rejections.
-- **Invariant 2:** `stackPos - needlePos` is a valid position
-- **Invariant 3:** the range from from `stackPos - needlePos` to `stackPos` (exclusive) is a
-- **Invariant 3:** the range from `stackPos - needlePos` to `stackPos` (exclusive) is a
-- prefix of the pattern.
if h₁ : stackPos < s.rawEndPos then
let stackByte := s.getUTF8Byte stackPos h₁

View File

@@ -20,7 +20,7 @@ functionality for searching for various kinds of pattern matches in slices to it
provide subslices according to matches etc. The key design principles behind this module are:
- Instead of providing one function per kind of pattern the API is generic over various kinds of
patterns. Thus it only provides e.g. one kind of function for looking for the position of the
first occurence of a pattern. Currently the supported patterns are:
first occurrence of a pattern. Currently the supported patterns are:
- {name}`Char`
- {lean}`Char → Bool`
- {name}`String` and {name}`String.Slice` (partially: doing non trivial searches backwards is not

View File

@@ -796,7 +796,8 @@ theorem getElem?_eq_none {xs : Vector α n} (h : n ≤ i) : xs[i]? = none := by
-- This is a more aggressive pattern than for `List/Array.getElem?_eq_none`, because
-- `length/size` won't appear.
grind_pattern Vector.getElem?_eq_none => xs[i]?
grind_pattern Vector.getElem?_eq_none => xs[i]? where
guard n i
@[simp] theorem getElem?_eq_getElem {xs : Vector α n} {i : Nat} (h : i < n) : xs[i]? = some xs[i] :=
getElem?_pos ..

View File

@@ -366,9 +366,11 @@ instance : GetElem? (List α) Nat α fun as i => i < as.length where
theorem none_eq_getElem?_iff {l : List α} {i : Nat} : none = l[i]? length l i := by
simp [eq_comm (a := none)]
@[grind =]
theorem getElem?_eq_none (h : length l i) : l[i]? = none := getElem?_eq_none_iff.mpr h
grind_pattern getElem?_eq_none => l.length, l[i]? where
guard l.length i
instance : LawfulGetElem (List α) Nat α fun as i => i < as.length where
getElem?_def as i h := by
split <;> simp_all

View File

@@ -21,6 +21,8 @@ structure Config where
/-- If `suggestions` is `true`, `grind` will invoke the currently configured library suggestion engine on the current goal,
and add attempt to use the resulting suggestions as additional parameters to the `grind` tactic. -/
suggestions : Bool := false
/-- If `locals` is `true`, `grind` will add all definitions from the current file. -/
locals : Bool := false
/-- Maximum number of case-splits in a proof search branch. It does not include splits performed during normalization. -/
splits : Nat := 9
/-- Maximum number of E-matching (aka heuristic theorem instantiation) rounds before each case split. -/

View File

@@ -766,7 +766,7 @@ def Poly.cancelVar (c : Int) (x : Var) (p : Poly) : Poly :=
(fun _ _ _ _ => a.toPoly_k.pow k)
(fun _ _ _ _ => a.toPoly_k.pow k)
(fun _ _ _ => a.toPoly_k.pow k)
a) = match (generalizing := false) a with
a) = match a with
| num n => Poly.num (n ^ k)
| .intCast n => .num (n^k)
| .natCast n => .num (n^k)

View File

@@ -132,6 +132,11 @@ structure Config where
Unused `have`s are still removed if `zeta` or `zetaUnused` are true.
-/
zetaHave : Bool := true
/--
If `locals` is `true`, `dsimp` will unfold all definitions from the current file.
For local theorems, use `+suggestions` instead.
-/
locals : Bool := false
deriving Inhabited, BEq
end DSimp
@@ -297,6 +302,11 @@ structure Config where
and attempt to use the resulting suggestions as parameters to the `simp` tactic.
-/
suggestions : Bool := false
/--
If `locals` is `true`, `simp` will unfold all definitions from the current file.
For local theorems, use `+suggestions` instead.
-/
locals : Bool := false
deriving Inhabited, BEq
-- Configuration object for `simp_all`

View File

@@ -523,7 +523,7 @@ macro_rules
| `(bif $c then $t else $e) => `(cond $c $t $e)
/--
Haskell-like pipe operator `<|`. `f <| x` means the same as the same as `f x`,
Haskell-like pipe operator `<|`. `f <| x` means the same as `f x`,
except that it parses `x` with lower precedence, which means that `f <| g <| x`
is interpreted as `f (g x)` rather than `(f g) x`.
-/
@@ -557,7 +557,7 @@ macro_rules
| `($a |> $f) => `($f $a)
/--
Alternative syntax for `<|`. `f $ x` means the same as the same as `f x`,
Alternative syntax for `<|`. `f $ x` means the same as `f x`,
except that it parses `x` with lower precedence, which means that `f $ g $ x`
is interpreted as `f (g x)` rather than `(f g) x`.
-/
@@ -782,9 +782,16 @@ Position reporting for `#guard_msgs`:
-/
syntax guardMsgsPositions := &"positions" " := " guardMsgsPositionsArg
/--
Substring matching for `#guard_msgs`:
- `substring := true` checks that the docstring appears as a substring of the output.
- `substring := false` (the default) requires exact matching (modulo whitespace normalization).
-/
syntax guardMsgsSubstring := &"substring" " := " (&"true" <|> &"false")
set_option linter.missingDocs false in
syntax guardMsgsSpecElt :=
guardMsgsFilter <|> guardMsgsWhitespace <|> guardMsgsOrdering <|> guardMsgsPositions
guardMsgsFilter <|> guardMsgsWhitespace <|> guardMsgsOrdering <|> guardMsgsPositions <|> guardMsgsSubstring
set_option linter.missingDocs false in
syntax guardMsgsSpec := "(" guardMsgsSpecElt,* ")"
@@ -860,6 +867,11 @@ Position reporting:
`#guard_msgs` appears.
- `positions := false` does not report position info.
Substring matching:
- `substring := true` checks that the docstring appears as a substring of the output
(after whitespace normalization). This is useful when you only care about part of the message.
- `substring := false` (the default) requires exact matching (modulo whitespace normalization).
For example, `#guard_msgs (error, drop all) in cmd` means to check errors and drop
everything else.
@@ -873,6 +885,13 @@ The top-level command elaborator only runs the linters if `#guard_msgs` is not p
syntax (name := guardMsgsCmd)
(plainDocComment)? "#guard_msgs" (ppSpace guardMsgsSpec)? " in" ppLine command : command
/--
`#guard_panic in cmd` runs `cmd` and succeeds if the command produces a panic message.
This is useful for testing that a command panics without matching the exact (volatile) panic text.
-/
syntax (name := guardPanicCmd)
"#guard_panic" " in" ppLine command : command
/--
Format and print the info trees for a given command.
This is mostly useful for debugging info trees.

View File

@@ -67,7 +67,7 @@ syntax unifConstraint := term patternIgnore(" =?= " <|> " ≟ ") term
syntax unifConstraintElem := colGe unifConstraint ", "?
syntax (docComment)? attrKind "unif_hint" (ppSpace ident)? (ppSpace bracketedBinder)*
" where " withPosition(unifConstraintElem*) patternIgnore(atomic("|" noWs "-") <|> "") unifConstraint : command
" where " withPosition(unifConstraintElem*) patternIgnore(atomic("|" noWs "-") <|> "") ppSpace unifConstraint : command
macro_rules
| `($[$doc?:docComment]? $kind:attrKind unif_hint $(n)? $bs* where $[$cs₁ $cs₂]* |- $t₁ $t₂) => do
@@ -120,7 +120,7 @@ calc
_ = z := pyz
```
It is also possible to write the *first* relation as `<lhs>\n _ = <rhs> :=
<proof>`. This is useful for aligning relation symbols, especially on longer:
<proof>`. This is useful for aligning relation symbols, especially on longer
identifiers:
```
calc abc

View File

@@ -375,6 +375,10 @@ theorem congr {α : Sort u} {β : Sort v} {f₁ f₂ : α → β} {a₁ a₂ :
theorem congrFun {α : Sort u} {β : α Sort v} {f g : (x : α) β x} (h : Eq f g) (a : α) : Eq (f a) (g a) :=
h rfl
/-- Similar to `congrFun` but `β` does not depend on `α`. -/
theorem congrFun' {α : Sort u} {β : Sort v} {f g : α β} (h : Eq f g) (a : α) : Eq (f a) (g a) :=
h rfl
/-!
Initialize the Quotient Module, which effectively adds the following definitions:
```
@@ -903,7 +907,7 @@ instance [Inhabited α] : Inhabited (ULift α) where
Lifts a type or proposition to a higher universe level.
`PULift α` wraps a value of type `α`. It is a generalization of
`PLift` that allows lifting values who's type may live in `Sort s`.
`PLift` that allows lifting values whose type may live in `Sort s`.
It also subsumes `PLift`.
-/
-- The universe variable `r` is written first so that `ULift.{r} α` can be used
@@ -3521,7 +3525,7 @@ instance : DecidableEq String.Pos.Raw :=
/--
A region or slice of some underlying string.
A substring contains an string together with the start and end byte positions of a region of
A substring contains a string together with the start and end byte positions of a region of
interest. Actually extracting a substring requires copying and memory allocation, while many
substrings of the same underlying string may exist with very little overhead, and they are more
convenient than tracking the bounds by hand.

View File

@@ -38,6 +38,12 @@ theorem eq_false_of_decide {p : Prop} {_ : Decidable p} (h : decide p = false) :
theorem implies_congr {p₁ p₂ : Sort u} {q₁ q₂ : Sort v} (h₁ : p₁ = p₂) (h₂ : q₁ = q₂) : (p₁ q₁) = (p₂ q₂) :=
h₁ h₂ rfl
theorem implies_congr_left {p₁ p₂ : Sort u} {q : Sort v} (h : p₁ = p₂) : (p₁ q) = (p₂ q) :=
h rfl
theorem implies_congr_right {p : Sort u} {q₁ q₂ : Sort v} (h : q₁ = q₂) : (p q₁) = (p q₂) :=
h rfl
theorem iff_congr {p₁ p₂ q₁ q₂ : Prop} (h₁ : p₁ p₂) (h₂ : q₁ q₂) : (p₁ q₁) (p₂ q₂) :=
Iff.of_eq (propext h₁ propext h₂ rfl)

View File

@@ -150,7 +150,7 @@ def parent (p : FilePath) : Option FilePath :=
/--
Extracts the last element of a path if it is a file or directory name.
Returns `none ` if the last entry is a special name (such as `.` or `..`) or if the path is the root
Returns `none` if the last entry is a special name (such as `.` or `..`) or if the path is the root
directory.
-/
def fileName (p : FilePath) : Option String :=

View File

@@ -561,7 +561,7 @@ Waits for the task to finish, then returns its result.
return t.get
/--
Waits until any of the tasks in the list has finished, then return its result.
Waits until any of the tasks in the list has finished, then returns its result.
-/
@[extern "lean_io_wait_any"] opaque waitAny (tasks : @& List (Task α))
(h : tasks.length > 0 := by exact Nat.zero_lt_succ _) : BaseIO α :=
@@ -679,7 +679,7 @@ File handles wrap the underlying operating system's file descriptors. There is n
to close a file: when the last reference to a file handle is dropped, the file is closed
automatically.
Handles have an associated read/write cursor that determines the where reads and writes occur in the
Handles have an associated read/write cursor that determines where reads and writes occur in the
file.
-/
opaque FS.Handle : Type := Unit
@@ -790,7 +790,7 @@ An exception is thrown if the file cannot be opened.
/--
Acquires an exclusive or shared lock on the handle. Blocks to wait for the lock if necessary.
Acquiring a exclusive lock while already possessing a shared lock will **not** reliably succeed: it
Acquiring an exclusive lock while already possessing a shared lock will **not** reliably succeed: it
works on Unix-like systems but not on Windows.
-/
@[extern "lean_io_prim_handle_lock"] opaque lock (h : @& Handle) (exclusive := true) : IO Unit
@@ -798,7 +798,7 @@ works on Unix-like systems but not on Windows.
Tries to acquire an exclusive or shared lock on the handle and returns `true` if successful. Will
not block if the lock cannot be acquired, but instead returns `false`.
Acquiring a exclusive lock while already possessing a shared lock will **not** reliably succeed: it
Acquiring an exclusive lock while already possessing a shared lock will **not** reliably succeed: it
works on Unix-like systems but not on Windows.
-/
@[extern "lean_io_prim_handle_try_lock"] opaque tryLock (h : @& Handle) (exclusive := true) : IO Bool
@@ -1350,7 +1350,7 @@ def withTempFile [Monad m] [MonadFinally m] [MonadLiftT IO m] (f : Handle → Fi
removeFile path
/--
Creates a temporary directory in the most secure manner possible, providing a its path to an `IO`
Creates a temporary directory in the most secure manner possible, providing its path to an `IO`
action. Afterwards, all files in the temporary directory are recursively deleted, regardless of how
or when they were created.
@@ -1480,7 +1480,7 @@ possible to close the child's standard input before the process terminates, whic
@[extern "lean_io_process_spawn"] opaque spawn (args : SpawnArgs) : IO (Child args.toStdioConfig)
/--
Blocks until the child process has exited and return its exit code.
Blocks until the child process has exited and returns its exit code.
-/
@[extern "lean_io_process_child_wait"] opaque Child.wait {cfg : @& StdioConfig} : @& Child cfg IO UInt32
@@ -1586,7 +1586,7 @@ end Process
/--
POSIX-style file permissions.
The `FileRight` structure describes these permissions for a file's owner, members of it's designated
The `FileRight` structure describes these permissions for a file's owner, members of its designated
group, and all others.
-/
structure AccessRight where
@@ -1863,7 +1863,7 @@ unsafe def Runtime.markPersistent (a : α) : BaseIO α := return a
set_option linter.unusedVariables false in
/--
Discards the passed owned reference. This leads to `a` any any object reachable from it never being
Discards the passed owned reference. This leads to `a` and any object reachable from it never being
freed. This can be a useful optimization for eliding deallocation time of big object graphs that are
kept alive close to the end of the process anyway (in which case calling `Runtime.markPersistent`
would be similarly costly to deallocation). It is still considered a safe operation as it cannot

View File

@@ -369,6 +369,12 @@ In this setting all definitions that are not opaque are unfolded.
-/
syntax (name := withUnfoldingAll) "with_unfolding_all " tacticSeq : tactic
/--
`with_unfolding_none tacs` executes `tacs` using the `.none` transparency setting.
In this setting no definitions are unfolded.
-/
syntax (name := withUnfoldingNone) "with_unfolding_none " tacticSeq : tactic
/-- `first | tac | ...` runs each `tac` until one succeeds, or else fails. -/
syntax (name := first) "first " withPosition((ppDedent(ppLine) colGe "| " tacticSeq)+) : tactic

View File

@@ -58,6 +58,9 @@ syntax (name := attemptAll) "attempt_all " withPosition((ppDedent(ppLine) colGe
/-- Helper internal tactic for implementing the tactic `try?` with parallel execution. -/
syntax (name := attemptAllPar) "attempt_all_par " withPosition((ppDedent(ppLine) colGe "| " tacticSeq)+) : tactic
/-- Helper internal tactic for implementing the tactic `try?` with parallel execution, returning first success. -/
syntax (name := firstPar) "first_par " withPosition((ppDedent(ppLine) colGe "| " tacticSeq)+) : tactic
/-- Helper internal tactic used to implement `evalSuggest` in `try?` -/
syntax (name := tryResult) "try_suggestions " tactic* : tactic

View File

@@ -463,7 +463,7 @@ variable {motive : α → Sort v}
variable (h : α Nat)
variable (F : (x : α) ((y : α) InvImage (· < ·) h y x motive y) motive x)
/-- Helper gadget that prevents reduction of `Nat.eager n` unless `n` evalutes to a ground term. -/
/-- Helper gadget that prevents reduction of `Nat.eager n` unless `n` evaluates to a ground term. -/
def Nat.eager (n : Nat) : Nat :=
if Nat.beq n n = true then n else n
@@ -474,8 +474,8 @@ A well-founded fixpoint operator specialized for `Nat`-valued measures. Given a
its higher order function argument `F` to invoke its argument only on values `y` that are smaller
than `x` with regard to `h`.
In contrast to to `WellFounded.fix`, this fixpoint operator reduces on closed terms. (More precisely:
when `h x` evalutes to a ground value)
In contrast to `WellFounded.fix`, this fixpoint operator reduces on closed terms. (More precisely:
when `h x` evaluates to a ground value)
-/
def Nat.fix : (x : α) motive x :=

View File

@@ -147,18 +147,11 @@ inductive Alt where
| alt (ctorName : Name) (params : Array Param) (code : Code)
| default (code : Code)
structure FunDecl where
fvarId : FVarId
binderName : Name
params : Array Param
type : Expr
value : Code
inductive FunDecl where
| mk (fvarId : FVarId) (binderName : Name) (params : Array Param) (type : Expr) (value : Code)
structure Cases where
typeName : Name
resultType : Expr
discr : FVarId
alts : Array Alt
inductive Cases where
| mk (typeName : Name) (resultType : Expr) (discr : FVarId) (alts : Array Alt)
deriving Inhabited
inductive Code where
@@ -173,6 +166,57 @@ inductive Code where
end
@[inline]
def FunDecl.fvarId : FunDecl FVarId
| .mk (fvarId := fvarId) .. => fvarId
@[inline]
def FunDecl.binderName : FunDecl Name
| .mk (binderName := binderName) .. => binderName
@[inline]
def FunDecl.params : FunDecl Array Param
| .mk (params := params) .. => params
@[inline]
def FunDecl.type : FunDecl Expr
| .mk (type := type) .. => type
@[inline]
def FunDecl.value : FunDecl Code
| .mk (value := value) .. => value
@[inline]
def FunDecl.updateBinderName : FunDecl Name FunDecl
| .mk fvarId _ params type value, new =>
.mk fvarId new params type value
@[inline]
def FunDecl.toParam (decl : FunDecl) (borrow : Bool) : Param :=
match decl with
| .mk fvarId binderName _ type .. => fvarId, binderName, type, borrow
@[inline]
def Cases.typeName : Cases Name
| .mk (typeName := typeName) .. => typeName
@[inline]
def Cases.resultType : Cases Expr
| .mk (resultType := resultType) .. => resultType
@[inline]
def Cases.discr : Cases FVarId
| .mk (discr := discr) .. => discr
@[inline]
def Cases.alts : Cases Array Alt
| .mk (alts := alts) .. => alts
@[inline]
def Cases.updateAlts : Cases Array Alt Cases
| .mk typeName resultType discr _, new =>
.mk typeName resultType discr new
deriving instance Inhabited for Alt
deriving instance Inhabited for FunDecl
@@ -281,14 +325,18 @@ private unsafe def updateAltImp (alt : Alt) (ps' : Array Param) (k' : Code) : Al
@[inline] private unsafe def updateAltsImp (c : Code) (alts : Array Alt) : Code :=
match c with
| .cases cs => if ptrEq cs.alts alts then c else .cases { cs with alts }
| .cases cs => if ptrEq cs.alts alts then c else .cases <| cs.updateAlts alts
| _ => unreachable!
@[implemented_by updateAltsImp] opaque Code.updateAlts! (c : Code) (alts : Array Alt) : Code
@[inline] private unsafe def updateCasesImp (c : Code) (resultType : Expr) (discr : FVarId) (alts : Array Alt) : Code :=
match c with
| .cases cs => if ptrEq cs.alts alts && ptrEq cs.resultType resultType && cs.discr == discr then c else .cases { cs with discr, resultType, alts }
| .cases cs =>
if ptrEq cs.alts alts && ptrEq cs.resultType resultType && cs.discr == discr then
c
else
.cases <| cs.typeName, resultType, discr, alts
| _ => unreachable!
@[implemented_by updateCasesImp] opaque Code.updateCases! (c : Code) (resultType : Expr) (discr : FVarId) (alts : Array Alt) : Code
@@ -368,7 +416,7 @@ private unsafe def updateFunDeclCoreImp (decl: FunDecl) (type : Expr) (params :
if ptrEq type decl.type && ptrEq params decl.params && ptrEq value decl.value then
decl
else
{ decl with type, params, value }
decl.fvarId, decl.binderName, params, type, value
/--
Low-level update `FunDecl` function. It does not update the local context.
@@ -378,7 +426,7 @@ to be updated.
@[implemented_by updateFunDeclCoreImp] opaque FunDecl.updateCore (decl : FunDecl) (type : Expr) (params : Array Param) (value : Code) : FunDecl
def Cases.extractAlt! (cases : Cases) (ctorName : Name) : Alt × Cases :=
let found i := (cases.alts[i], { cases with alts := cases.alts.eraseIdx i })
let found i := (cases.alts[i]!, cases.updateAlts (cases.alts.eraseIdx! i))
if let some i := cases.alts.findFinIdx? fun | .alt ctorName' .. => ctorName == ctorName' | _ => false then
found i
else if let some i := cases.alts.findFinIdx? fun | .default _ => true | _ => false then

View File

@@ -48,7 +48,7 @@ where
if alts.isEmpty then
throwError "`Code.bind` failed, empty `cases` found"
let resultType mkCasesResultType alts
return .cases { c with alts, resultType }
return .cases c.typeName, resultType, c.discr, alts
| .return fvarId => f fvarId
| .jmp fvarId .. =>
unless ( read).contains fvarId do

View File

@@ -137,7 +137,7 @@ mutual
/- We only collect the variables in the scope of the function application being specialized. -/
if let some funDecl findFunDecl? fvarId then
if ctx.abstract funDecl.fvarId then
modify fun s => { s with params := s.params.push <| { funDecl with borrow := false } }
modify fun s => { s with params := s.params.push <| funDecl.toParam false }
else
collectFunDecl funDecl
modify fun s => { s with decls := s.decls.push <| .fun funDecl }

View File

@@ -359,7 +359,7 @@ def mkLetDecl (binderName : Name) (type : Expr) (value : LetValue) : CompilerM L
def mkFunDecl (binderName : Name) (type : Expr) (params : Array Param) (value : Code) : CompilerM FunDecl := do
let fvarId mkFreshFVarId
let binderName ensureNotAnonymous binderName `_f
let funDecl := { fvarId, binderName, type, params, value }
let funDecl := fvarId, binderName, params, type, value
modifyLCtx fun lctx => lctx.addFunDecl funDecl
return funDecl
@@ -397,7 +397,7 @@ private unsafe def updateFunDeclImp (decl : FunDecl) (type : Expr) (params : Arr
if ptrEq type decl.type && ptrEq params decl.params && ptrEq value decl.value then
return decl
else
let decl := { decl with type, params, value }
let decl := decl.fvarId, decl.binderName, params, type, value
modifyLCtx fun lctx => lctx.addFunDecl decl
return decl

View File

@@ -119,7 +119,7 @@ partial def internalizeFunDecl (decl : FunDecl) : InternalizeM FunDecl := do
let params decl.params.mapM internalizeParam
let value internalizeCode decl.value
let fvarId mkNewFVarId decl.fvarId
let decl := { decl with binderName, fvarId, params, type, value }
let decl := fvarId, binderName, params, type, value
modifyLCtx fun lctx => lctx.addFunDecl decl
return decl
@@ -139,7 +139,7 @@ partial def internalizeCode (code : Code) : InternalizeM Code := do
let alts c.alts.mapM fun
| .alt ctorName params k => return .alt ctorName ( params.mapM internalizeParam) ( internalizeAltCode k)
| .default k => return .default ( internalizeAltCode k)
return .cases { c with discr, alts, resultType }
return .cases c.typeName, resultType, discr, alts
end

View File

@@ -229,10 +229,8 @@ where
| _, _ => return Code.updateLet! code decl ( go k)
| .fun decl k =>
if let some replacement := ( read)[decl.fvarId]? then
let newDecl := { decl with
binderName := replacement,
value := ( go decl.value)
}
let newValue go decl.value
let newDecl := decl.fvarId, replacement, decl.params, decl.type, newValue
modifyLCtx fun lctx => lctx.addFunDecl newDecl
return .jp newDecl ( go k)
else

View File

@@ -4,16 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Compiler.Options
public import Lean.Compiler.IR
public import Lean.Compiler.LCNF.Passes
public import Lean.Compiler.LCNF.ToDecl
public import Lean.Compiler.LCNF.Check
import Lean.Meta.Match.MatcherInfo
public section
namespace Lean.Compiler.LCNF
/--
We do not generate code for `declName` if

View File

@@ -35,7 +35,7 @@ def LetDecl.applyRenaming (decl : LetDecl) (r : Renaming) : CompilerM LetDecl :=
mutual
partial def FunDecl.applyRenaming (decl : FunDecl) (r : Renaming) : CompilerM FunDecl := do
if let some binderName := r.get? decl.fvarId then
let decl := { decl with binderName }
let decl := decl.updateBinderName binderName
modifyLCtx fun lctx => lctx.addFunDecl decl
decl.updateValue ( decl.value.applyRenaming r)
else

View File

@@ -268,7 +268,7 @@ where
else
altsNew := altsNew.push (alt.updateCode k)
modify fun s => s.insert decl.fvarId jpAltMap
let value := LCNF.attachCodeDecls decls (.cases { cases with alts := altsNew })
let value := LCNF.attachCodeDecls decls (.cases <| cases.updateAlts altsNew)
let decl decl.updateValue value
let code := .jp decl ( visit k)
return LCNF.attachCodeDecls jpAltDecls code

View File

@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Compiler.LCNF.SpecInfo
public import Lean.Compiler.LCNF.MonadScope
@@ -13,7 +12,7 @@ import Lean.Compiler.LCNF.Simp
import Lean.Compiler.LCNF.ToExpr
import Lean.Compiler.LCNF.Level
import Lean.Compiler.LCNF.Closure
import Lean.Meta.Transform
namespace Lean.Compiler.LCNF
namespace Specialize
@@ -116,7 +115,7 @@ def isGround [TraverseFVar α] (e : α) : SpecializeM Bool := do
match findFunDecl? fnFVarId with
-- This ascription to `Bool` is required to avoid this being inferred as `Prop`,
-- even with a type specified on the `let` binding.
| some { params, .. } => pure ((args.size < params.size) : Bool)
| some (.mk (params := params) ..) => pure ((args.size < params.size) : Bool)
| none => pure false
| _ => pure false
let fvarId := decl.fvarId

View File

@@ -72,7 +72,7 @@ partial def visitCode (code : Code) : M Code := do
modify fun s => { s with projMap := s.projMap.erase base }
let resultType toMonoType ( k.inferType)
let alts := #[.alt ctorInfo.name params k]
return .cases { typeName, resultType, discr := base, alts }
return .cases typeName, resultType, base, alts
| _ => return code.updateLet! ( decl.updateValue ( visitLetValue decl.value)) ( visitCode k)
| .fun decl k =>
let decl decl.updateValue ( visitCode decl.value)

View File

@@ -4,13 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Compiler.InitAttr
public import Lean.Compiler.LCNF.ToLCNF
import Lean.Meta.Transform
import Lean.Meta.Match.MatcherInfo
public section
namespace Lean.Compiler.LCNF
/--
Inline constants tagged with the `[macro_inline]` attribute occurring in `e`.

View File

@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.AppBuilder
public import Lean.Compiler.CSimpAttr
@@ -12,9 +11,8 @@ public import Lean.Compiler.ImplementedByAttr
public import Lean.Compiler.LCNF.Bind
public import Lean.Compiler.NeverExtractAttr
import Lean.Meta.CasesInfo
import Lean.Meta.WHNF
public section
namespace Lean.Compiler.LCNF
namespace ToLCNF
@@ -65,7 +63,7 @@ That is, our goal is to try to promote the pre join points `_alt.<idx>` into a p
partial def bindCases (jpDecl : FunDecl) (cases : Cases) : CompilerM Code := do
let (alts, s) visitAlts cases.alts |>.run {}
let resultType mkCasesResultType alts
let result := .cases { cases with alts, resultType }
let result := .cases cases.typeName, resultType, cases.discr, alts
let result := s.foldl (init := result) fun result _ altJp => .jp altJp result
return .jp jpDecl result
where
@@ -149,7 +147,7 @@ where
if alts.isEmpty then
throwError "`Code.bind` failed, empty `cases` found"
let resultType mkCasesResultType alts
return .cases { c with alts, resultType }
return .cases c.typeName, resultType, c.discr, alts
| .return fvarId => return .jmp jpDecl.fvarId #[.fvar fvarId]
| .jmp .. | .unreach .. => return code
@@ -185,7 +183,7 @@ where
result instead of a join point that takes a closure.
-/
eraseParam auxParam
let auxFunDecl := { auxParam with params := #[], value := .cases cases : FunDecl }
let auxFunDecl := auxParam.fvarId, auxParam.binderName, #[], auxParam.type, .cases cases
modifyLCtx fun lctx => lctx.addFunDecl auxFunDecl
let auxFunDecl auxFunDecl.etaExpand
go seq (i - 1) (.fun auxFunDecl c)
@@ -599,7 +597,7 @@ where
let (altType, alt) visitAlt numParams args[i]!
resultType := joinTypes altType resultType
alts := alts.push alt
let cases : Cases := { typeName, discr := discrFVarId, resultType, alts }
let cases := typeName, resultType, discrFVarId, alts
let auxDecl mkAuxParam resultType
pushElement (.cases auxDecl cases)
let result := .fvar auxDecl.fvarId

View File

@@ -205,7 +205,7 @@ partial def decToMono (c : Cases) (_ : c.typeName == ``Decidable) : ToMonoM Code
eraseParams ps
let ctorName := if ctorName == ``Decidable.isTrue then ``Bool.true else ``Bool.false
return .alt ctorName #[] ( k.toMono)
return .cases { c with resultType, alts, typeName := ``Bool }
return .cases ``Bool, resultType, c.discr, alts
/-- Eliminate `cases` for `Nat`. -/
partial def casesNatToMono (c: Cases) (_ : c.typeName == ``Nat) : ToMonoM Code := do
@@ -226,7 +226,7 @@ partial def casesNatToMono (c: Cases) (_ : c.typeName == ``Nat) : ToMonoM Code :
return .alt ``Bool.false #[] (.let oneDecl (.let subOneDecl ( k.toMono)))
else
return .alt ``Bool.true #[] ( k.toMono)
return .let zeroDecl (.let isZeroDecl (.cases { discr := isZeroDecl.fvarId, resultType, alts, typeName := ``Bool }))
return .let zeroDecl (.let isZeroDecl (.cases ``Bool, resultType, isZeroDecl.fvarId, alts))
/-- Eliminate `cases` for `Int`. -/
partial def casesIntToMono (c: Cases) (_ : c.typeName == ``Int) : ToMonoM Code := do
@@ -251,7 +251,7 @@ partial def casesIntToMono (c: Cases) (_ : c.typeName == ``Int) : ToMonoM Code :
let absDecl := { fvarId := p.fvarId, binderName := p.binderName, type := natType, value := .const ``Int.natAbs [] #[.fvar c.discr] }
modifyLCtx fun lctx => lctx.addLetDecl absDecl
return .alt ``Bool.false #[] (.let absDecl ( k.toMono))
return .let zeroNatDecl (.let zeroIntDecl (.let isNegDecl (.cases { discr := isNegDecl.fvarId, resultType, alts, typeName := ``Bool })))
return .let zeroNatDecl (.let zeroIntDecl (.let isNegDecl (.cases ``Bool, resultType, isNegDecl.fvarId, alts)))
/-- Eliminate `cases` for `UInt` types. -/
partial def casesUIntToMono (c : Cases) (uintName : Name) (_ : c.typeName == uintName) : ToMonoM Code := do
@@ -317,13 +317,13 @@ partial def casesThunkToMono (c : Cases) (_ : c.typeName == ``Thunk) : ToMonoM C
let letValue := .const ``Thunk.get [] #[.erased, .fvar c.discr]
let letDecl mkLetDecl ( mkFreshBinderName `_x) anyExpr letValue
let paramType := .const `PUnit []
let decl := {
fvarId := p.fvarId
binderName := p.binderName
type := ( mkArrow paramType anyExpr)
params := #[ mkAuxParam paramType]
value := .let letDecl (.return letDecl.fvarId)
}
let decl :=
p.fvarId,
p.binderName,
#[ mkAuxParam paramType],
( mkArrow paramType anyExpr),
.let letDecl (.return letDecl.fvarId)
modifyLCtx fun lctx => lctx.addFunDecl decl
let k k.toMono
return .fun decl k
@@ -418,7 +418,7 @@ partial def Code.toMono (code : Code) : ToMonoM Code := do
let ps mkFieldParamsForComputedFields ctorInfo.type ctorInfo.numParams numNewFields ps
let k k.toMono
return .alt implCtorName ps k
return .cases { discr := c.discr, resultType, typeName, alts }
return .cases typeName, resultType, c.discr, alts
else
let alts c.alts.mapM fun alt =>
match alt with

View File

@@ -193,6 +193,28 @@ partial def findEntryAux [BEq α] : Node α β → USize → α → Option (α
def findEntry? {_ : BEq α} {_ : Hashable α} : PersistentHashMap α β α Option (α × β)
| { root }, k => findEntryAux root (hash k |>.toUSize) k
partial def findKeyDAtAux [BEq α] (keys : Array α) (vals : Array β) (heq : keys.size = vals.size) (i : Nat) (k : α) (k₀ : α) : α :=
if h : i < keys.size then
let k' := keys[i]
if k == k' then k'
else findKeyDAtAux keys vals heq (i+1) k k₀
else k₀
partial def findKeyDAux [BEq α] : Node α β USize α α α
| .entries entries, h, k, k₀ =>
let j := (mod2Shift h shift).toNat
match entries[j]! with
| .null => k₀
| .ref node => findKeyDAux node (div2Shift h shift) k k₀
| .entry k' _ => if k == k' then k' else k₀
| .collision keys vals heq, _, k, k₀ => findKeyDAtAux keys vals heq 0 k k₀
/--
A more efficient `m.findEntry? a |>.map (·.1) |>.getD a₀`
-/
@[inline] def findKeyD {_ : BEq α} {_ : Hashable α} (m : PersistentHashMap α β) (a : α) (a₀ : α) : α :=
findKeyDAux m.root (hash a |>.toUSize) a a₀
partial def containsAtAux [BEq α] (keys : Array α) (vals : Array β) (heq : keys.size = vals.size) (i : Nat) (k : α) : Bool :=
if h : i < keys.size then
let k' := keys[i]

View File

@@ -45,6 +45,9 @@ variable {_ : BEq α} {_ : Hashable α}
| some (a, _) => some a
| none => none
@[inline] def findD (s : PersistentHashSet α) (a : α) (a₀ : α) : α :=
s.set.findKeyD a a₀
@[inline] def contains (s : PersistentHashSet α) (a : α) : Bool :=
s.set.contains a

View File

@@ -45,26 +45,29 @@ def toAttributeKind (attrKindStx : Syntax) : MacroM AttributeKind := do
def mkAttrKindGlobal : Syntax :=
mkNode ``Lean.Parser.Term.attrKind #[mkNullNode]
def elabAttr [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLiftT IO m] (attrInstance : Syntax) : m Attribute := do
/- attrInstance := ppGroup $ leading_parser attrKind >> attrParser -/
let attrKind liftMacroM <| toAttributeKind attrInstance[0]
let attr := attrInstance[1]
let attr liftMacroM <| expandMacros attr
let attrName if attr.getKind == ``Parser.Attr.simple then
pure attr[0].getId.eraseMacroScopes
else match attr.getKind with
| .str _ s => pure <| Name.mkSimple s
| _ => throwErrorAt attr "Unknown attribute"
let .ok _impl := getAttributeImpl ( getEnv) attrName
| throwError "Unknown attribute `[{attrName}]`"
if let .ok impl := getAttributeImpl ( getEnv) attrName then
if regularInitAttr.getParam? ( getEnv) impl.ref |>.isSome then -- skip `builtin_initialize` attributes
recordExtraModUseFromDecl (isMeta := true) impl.ref
/- The `AttrM` does not have sufficient information for expanding macros in `args`.
So, we expand them before here before we invoke the attributer handlers implemented using `AttrM`. -/
return { kind := attrKind, name := attrName, stx := attr }
def elabAttr [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLiftT IO m] [MonadFinally m] (attrInstance : Syntax) : m Attribute := do
-- Resolving the attribute itself can be done in the private scope; running the attribute handler
-- will later be done in a scope determined by `applyAttributesCore`.
withoutExporting do
/- attrInstance := ppGroup $ leading_parser attrKind >> attrParser -/
let attrKind liftMacroM <| toAttributeKind attrInstance[0]
let attr := attrInstance[1]
let attr liftMacroM <| expandMacros attr
let attrName if attr.getKind == ``Parser.Attr.simple then
pure attr[0].getId.eraseMacroScopes
else match attr.getKind with
| .str _ s => pure <| Name.mkSimple s
| _ => throwErrorAt attr "Unknown attribute"
let .ok _impl := getAttributeImpl ( getEnv) attrName
| throwError "Unknown attribute `[{attrName}]`"
if let .ok impl := getAttributeImpl ( getEnv) attrName then
if regularInitAttr.getParam? ( getEnv) impl.ref |>.isSome then -- skip `builtin_initialize` attributes
recordExtraModUseFromDecl (isMeta := true) impl.ref
/- The `AttrM` does not have sufficient information for expanding macros in `args`.
So, we expand them before here before we invoke the attributer handlers implemented using `AttrM`. -/
return { kind := attrKind, name := attrName, stx := attr }
def elabAttrs [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLog m] [MonadLiftT IO m] (attrInstances : Array Syntax) : m (Array Attribute) := do
def elabAttrs [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLog m] [MonadLiftT IO m] [MonadFinally m] (attrInstances : Array Syntax) : m (Array Attribute) := do
let mut attrs := #[]
for attr in attrInstances do
try
@@ -74,7 +77,7 @@ def elabAttrs [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadM
return attrs
-- leading_parser "@[" >> sepBy1 attrInstance ", " >> "]"
def elabDeclAttrs [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLog m] [MonadLiftT IO m] (stx : Syntax) : m (Array Attribute) :=
def elabDeclAttrs [Monad m] [MonadEnv m] [MonadResolveName m] [MonadError m] [MonadMacroAdapter m] [MonadRecDepth m] [MonadTrace m] [MonadOptions m] [AddMessageContext m] [MonadLog m] [MonadLiftT IO m] [MonadFinally m] (stx : Syntax) : m (Array Attribute) :=
elabAttrs stx[1].getSepArgs
end Lean.Elab

View File

@@ -573,11 +573,16 @@ def elabDefaultOrNonempty : TermElab := fun stx expectedType? => do
| some expectedType =>
try
mkDefault expectedType
catch ex => try
catch _ => try
mkOfNonempty expectedType
catch _ =>
if stx[1].isNone then
throw ex
throwError "\
failed to synthesize '{.ofConstName ``Inhabited}' or '{.ofConstName ``Nonempty}' instance for\
{indentExpr expectedType}\n\
\n\
If this type is defined using the 'structure' or 'inductive' command, \
you can try adding a 'deriving Nonempty' clause to it."
else
-- It is in the context of an `unsafe` constant. We can use sorry instead.
-- Another option is to make a recursive application since it is unsafe.

View File

@@ -11,10 +11,13 @@ public import Lean.Server.CodeActions.Attr
public section
/-! `#guard_msgs` command for testing commands
/-! `#guard_msgs` and `#guard_panic` commands for testing commands
This module defines a command to test that another command produces the expected messages.
See the docstring on the `#guard_msgs` command.
This module defines commands to test that other commands produce expected messages:
- `#guard_msgs`: tests that a command produces exactly the expected messages
- `#guard_panic`: tests that a command produces a panic message (without checking the exact text)
See the docstrings on the individual commands.
-/
open Lean Parser.Tactic Elab Command
@@ -88,6 +91,8 @@ structure GuardMsgsSpec where
ordering : MessageOrdering := .exact
/-- Whether to report position information. -/
reportPositions : Bool := false
/-- Whether to check for substring containment instead of exact match. -/
substring : Bool := false
def parseGuardMsgsFilterAction (action? : Option (TSyntax ``guardMsgsFilterAction)) :
CommandElabM FilterSpec := do
@@ -118,7 +123,7 @@ def parseGuardMsgsSpec (spec? : Option (TSyntax ``guardMsgsSpec)) : CommandElabM
| `(guardMsgsSpec| ($[$elts:guardMsgsSpecElt],*)) => pure elts
| _ => throwUnsupportedSyntax
let defaultFilterFn := cfg.filterFn
let mut { whitespace, ordering, reportPositions .. } := cfg
let mut { whitespace, ordering, reportPositions, substring .. } := cfg
let mut p? : Option (Message FilterSpec) := none
let pushP (action : FilterSpec) (msgP : Message Bool) (p? : Option (Message FilterSpec))
(msg : Message) : FilterSpec :=
@@ -136,9 +141,11 @@ def parseGuardMsgsSpec (spec? : Option (TSyntax ``guardMsgsSpec)) : CommandElabM
| `(guardMsgsSpecElt| ordering := sorted) => ordering := .sorted
| `(guardMsgsSpecElt| positions := true) => reportPositions := true
| `(guardMsgsSpecElt| positions := false) => reportPositions := false
| `(guardMsgsSpecElt| substring := true) => substring := true
| `(guardMsgsSpecElt| substring := false) => substring := false
| _ => throwUnsupportedSyntax
let filterFn := p?.getD defaultFilterFn
return { filterFn, whitespace, ordering, reportPositions }
return { filterFn, whitespace, ordering, reportPositions, substring }
/-- An info tree node corresponding to a failed `#guard_msgs` invocation,
used for code action support. -/
@@ -176,22 +183,31 @@ def MessageOrdering.apply (mode : MessageOrdering) (msgs : List String) : List S
| .exact => msgs
| .sorted => msgs |>.toArray.qsort (· < ·) |>.toList
/--
Runs a command and collects all messages (sync and async) it produces.
Clears the snapshot tasks after collection.
Returns the collected messages.
-/
def runAndCollectMessages (cmd : Syntax) : CommandElabM MessageLog := do
-- do not forward snapshot as we don't want messages assigned to it to leak outside
withReader ({ · with snap? := none }) do
-- The `#guard_msgs` command is special-cased in `elabCommandTopLevel` to ensure linters only run once.
elabCommandTopLevel cmd
-- collect sync and async messages
let msgs := ( get).messages ++
( get).snapshotTasks.foldl (· ++ ·.get.getAll.foldl (· ++ ·.diagnostics.msgLog) .empty) .empty
-- clear async messages as we don't want them to leak outside
modify ({ · with snapshotTasks := #[] })
return msgs
@[builtin_command_elab Lean.guardMsgsCmd] def elabGuardMsgs : CommandElab
| `(command| $[$dc?:docComment]? #guard_msgs%$tk $(spec?)? in $cmd) => do
let expected : String := ( dc?.mapM (getDocStringText ·)).getD ""
|>.trimAscii |>.copy |> removeTrailingWhitespaceMarker
let { whitespace, ordering, filterFn, reportPositions } parseGuardMsgsSpec spec?
-- do not forward snapshot as we don't want messages assigned to it to leak outside
withReader ({ · with snap? := none }) do
-- The `#guard_msgs` command is special-cased in `elabCommandTopLevel` to ensure linters only run once.
elabCommandTopLevel cmd
-- collect sync and async messages
let msgs := ( get).messages ++
( get).snapshotTasks.foldl (· ++ ·.get.getAll.foldl (· ++ ·.diagnostics.msgLog) {}) {}
-- clear async messages as we don't want them to leak outside
modify ({ · with snapshotTasks := #[] })
let mut toCheck : MessageLog := .empty
let mut toPassthrough : MessageLog := .empty
let { whitespace, ordering, filterFn, reportPositions, substring } parseGuardMsgsSpec spec?
let msgs runAndCollectMessages cmd
let mut toCheck : MessageLog := MessageLog.empty
let mut toPassthrough : MessageLog := MessageLog.empty
for msg in msgs.toList do
if msg.isSilent then
continue
@@ -207,7 +223,13 @@ def MessageOrdering.apply (mode : MessageOrdering) (msgs : List String) : List S
let strings toCheck.toList.mapM (messageToString · reportPos?)
let strings := ordering.apply strings
let res := "---\n".intercalate strings |>.trimAscii |>.copy
if whitespace.apply expected == whitespace.apply res then
let passed := if substring then
-- Substring mode: check that expected appears within res (after whitespace normalization)
(whitespace.apply res).contains (whitespace.apply expected)
else
-- Exact mode: check equality (after whitespace normalization)
whitespace.apply expected == whitespace.apply res
if passed then
-- Passed. Only put toPassthrough messages back on the message log
modify fun st => { st with messages := toPassthrough }
else
@@ -257,4 +279,24 @@ def guardMsgsCodeAction : CommandCodeAction := fun _ _ _ node => do
}
}]
@[builtin_command_elab Lean.guardPanicCmd] def elabGuardPanic : CommandElab
| `(command| #guard_panic in $cmd) => do
let msgs runAndCollectMessages cmd
-- Check if any message contains "PANIC"
let mut foundPanic := false
for msg in msgs.toList do
if msg.isSilent then continue
let msgStr msg.data.toString
if msgStr.contains "PANIC" then
foundPanic := true
break
if foundPanic then
-- Success - clear the messages so they don't appear
modify fun st => { st with messages := MessageLog.empty }
else
-- Failed - put the messages back and add our error
modify fun st => { st with messages := msgs }
logError "Expected a PANIC but none was found"
| _ => throwUnsupportedSyntax
end Lean.Elab.Tactic.GuardMsgs

View File

@@ -29,72 +29,76 @@ private def inductiveSyntaxToView (modifiers : Modifiers) (decl : Syntax) (isCoi
let (binders, type?) := expandOptDeclSig decl[2]
let declId := decl[1]
let name, declName, levelNames, docString? Term.expandDeclId ( getCurrNamespace) ( Term.getLevelNames) declId modifiers
if modifiers.isMeta then
modifyEnv (markMeta · declName)
addDeclarationRangesForBuiltin declName modifiers.stx decl
/-
Relates to issue
https://github.com/leanprover/lean4/issues/10503
-/
if declName.hasMacroScopes && isCoinductive then
throwError "Coinductive predicates are not allowed inside of macro scopes"
let ctors decl[4].getArgs.mapM fun ctor => withRef ctor do
/-
```
def ctor := leading_parser optional docComment >> "\n| " >> declModifiers >> rawIdent >> optDeclSig
```
-/
let modifiersStx := ctor[2]
let mut ctorModifiers elabModifiers modifiersStx
if let some leadingDocComment := ctor[0].getOptional? then
if ctorModifiers.docString?.isSome then
logErrorAt leadingDocComment "Duplicate doc string"
ctorModifiers := { ctorModifiers with
docString? := some (leadingDocComment, doc.verso.get ( getOptions)) }
if ctorModifiers.isPrivate && modifiers.isPrivate then
let hint do
let .original .. := modifiersStx.getHeadInfo | pure .nil
let some range := modifiersStx[2].getRangeWithTrailing? | pure .nil
-- Drop the doc comment from both the `declModifiers` and outer `ctor`, as well as
-- everything after the constructor name (yielding invalid syntax with the desired range)
let previewSpan? := ctor.modifyArgs (·[2...4].toArray.modify 0 (·.modifyArgs (·[1...*])))
MessageData.hint "Remove `private` modifier from constructor" #[{
suggestion := ""
span? := Syntax.ofRange range
previewSpan?
toCodeActionTitle? := some fun _ => "Delete `private` modifier"
}]
throwError m!"Constructor cannot be marked `private` because it is already in a `private` inductive datatype" ++ hint
if ctorModifiers.isProtected && modifiers.isPrivate then
throwError "Constructor cannot be `protected` because it is in a `private` inductive datatype"
checkValidCtorModifier ctorModifiers
let ctorName := ctor.getIdAt 3
let ctorName := declName ++ ctorName
let ctorName withRef ctor[3] <| applyVisibility ctorModifiers ctorName
let (binders, type?) := expandOptDeclSig ctor[4]
addDeclarationRangesFromSyntax ctorName ctor ctor[3]
-- In the case of mutual inductives, this is the earliests point where we can establish the
-- correct scope for each individual inductive declaration (used e.g. to infer ctor visibility
-- below), so let's do that now.
withExporting (isExporting := !isPrivateName declName) do
if modifiers.isMeta then
modifyEnv (markMeta · ctorName)
return { ref := ctor, declId := ctor[3], modifiers := ctorModifiers, declName := ctorName, binders := binders, type? := type? : CtorView }
let computedFields (decl[5].getOptional?.map (·[1].getArgs) |>.getD #[]).mapM fun cf => withRef cf do
return { ref := cf, modifiers := cf[0], fieldId := cf[1].getId, type := cf[3], matchAlts := cf[4] }
let classes getOptDerivingClasses decl[6]
if decl[3][0].isToken ":=" then
-- https://github.com/leanprover/lean4/issues/5236
withRef decl[0] <| Linter.logLintIf Linter.linter.deprecated decl[3]
"`inductive ... :=` has been deprecated in favor of `inductive ... where`"
return {
ref := decl
shortDeclName := name
derivingClasses := classes
allowIndices := true
allowSortPolymorphism := true
declId, modifiers, isClass, declName, levelNames
binders, type?, ctors
computedFields
docString?
isCoinductive := isCoinductive
}
modifyEnv (markMeta · declName)
addDeclarationRangesForBuiltin declName modifiers.stx decl
/-
Relates to issue
https://github.com/leanprover/lean4/issues/10503
-/
if declName.hasMacroScopes && isCoinductive then
throwError "Coinductive predicates are not allowed inside of macro scopes"
let ctors decl[4].getArgs.mapM fun ctor => withRef ctor do
/-
```
def ctor := leading_parser optional docComment >> "\n| " >> declModifiers >> rawIdent >> optDeclSig
```
-/
let modifiersStx := ctor[2]
let mut ctorModifiers elabModifiers modifiersStx
if let some leadingDocComment := ctor[0].getOptional? then
if ctorModifiers.docString?.isSome then
logErrorAt leadingDocComment "Duplicate doc string"
ctorModifiers := { ctorModifiers with
docString? := some (leadingDocComment, doc.verso.get ( getOptions)) }
if ctorModifiers.isPrivate && modifiers.isPrivate then
let hint do
let .original .. := modifiersStx.getHeadInfo | pure .nil
let some range := modifiersStx[2].getRangeWithTrailing? | pure .nil
-- Drop the doc comment from both the `declModifiers` and outer `ctor`, as well as
-- everything after the constructor name (yielding invalid syntax with the desired range)
let previewSpan? := ctor.modifyArgs (·[2...4].toArray.modify 0 (·.modifyArgs (·[1...*])))
MessageData.hint "Remove `private` modifier from constructor" #[{
suggestion := ""
span? := Syntax.ofRange range
previewSpan?
toCodeActionTitle? := some fun _ => "Delete `private` modifier"
}]
throwError m!"Constructor cannot be marked `private` because it is already in a `private` inductive datatype" ++ hint
if ctorModifiers.isProtected && modifiers.isPrivate then
throwError "Constructor cannot be `protected` because it is in a `private` inductive datatype"
checkValidCtorModifier ctorModifiers
let ctorName := ctor.getIdAt 3
let ctorName := declName ++ ctorName
let ctorName withRef ctor[3] <| applyVisibility ctorModifiers ctorName
let (binders, type?) := expandOptDeclSig ctor[4]
addDeclarationRangesFromSyntax ctorName ctor ctor[3]
if modifiers.isMeta then
modifyEnv (markMeta · ctorName)
return { ref := ctor, declId := ctor[3], modifiers := ctorModifiers, declName := ctorName, binders := binders, type? := type? : CtorView }
let computedFields (decl[5].getOptional?.map (·[1].getArgs) |>.getD #[]).mapM fun cf => withRef cf do
return { ref := cf, modifiers := cf[0], fieldId := cf[1].getId, type := cf[3], matchAlts := cf[4] }
let classes getOptDerivingClasses decl[6]
if decl[3][0].isToken ":=" then
-- https://github.com/leanprover/lean4/issues/5236
withRef decl[0] <| Linter.logLintIf Linter.linter.deprecated decl[3]
"`inductive ... :=` has been deprecated in favor of `inductive ... where`"
return {
ref := decl
shortDeclName := name
derivingClasses := classes
allowIndices := true
allowSortPolymorphism := true
declId, modifiers, isClass, declName, levelNames
binders, type?, ctors
computedFields
docString?
isCoinductive := isCoinductive
}
private def isInductiveFamily (numParams : Nat) (indFVar : Expr) : TermElabM Bool := do
let indFVarType inferType indFVar

View File

@@ -886,7 +886,7 @@ private def generalize (discrs : Array Discr) (matchType : Expr) (altViews : Arr
let matchType' forallBoundedTelescope matchType discrs.size fun ds type => do
let type mkForallFVars ys type
let (discrs', ds') := Array.unzip <| Array.zip discrExprs ds |>.filter fun (di, _) => di.isFVar
let type type.replaceFVarsM discrs' ds'
let type := type.replaceFVars discrs' ds'
mkForallFVars ds type
if ( isTypeCorrect matchType') then
let discrs := discrs ++ ys.map fun y => { expr := y : Discr }
@@ -1119,11 +1119,11 @@ private def elabMatchAux (generalizing? : Option Bool) (discrStxs : Array Syntax
withRef altLHS.ref do
for d in altLHS.fvarDecls do
if d.hasExprMVar then
-- This code path is a vestige prior to fixing #8099, but it is still appears to be
-- important for testcase 1300.lean.
tryPostpone
withExistingLocalDecls altLHS.fvarDecls do
runPendingTacticsAt d.type
if ( instantiateMVars d.type).hasExprMVar then
throwMVarError m!"Invalid match expression: The type of pattern variable '{d.toExpr}' contains metavariables:{indentExpr d.type}"
for p in altLHS.patterns do
if ( Match.instantiatePatternMVars p).hasExprMVar then
tryPostpone

View File

@@ -8,6 +8,7 @@ module
prelude
public import Std.Tactic.BVDecide.LRAT.Parser
public import Lean.CoreM
public import Std.Tactic.BVDecide.Syntax
public section
@@ -146,7 +147,7 @@ solvers the solver is run with `timeout` in seconds as a maximum time limit to s
Note: This function currently assume that the solver has the same CLI as CaDiCal.
-/
def satQuery (solverPath : System.FilePath) (problemPath : System.FilePath) (proofOutput : System.FilePath)
(timeout : Nat) (binaryProofs : Bool) :
(timeout : Nat) (binaryProofs : Bool) (mode : Frontend.SolverMode) :
CoreM SolverResult := do
let cmd := solverPath.toString
let mut args := #[
@@ -156,17 +157,12 @@ def satQuery (solverPath : System.FilePath) (problemPath : System.FilePath) (pro
s!"--binary={binaryProofs}",
"--quiet",
/-
This sets the magic parameters of cadical to optimize for UNSAT search.
Given the fact that we are mostly interested in proving things and expect user goals to be
provable this is a fine value to set
-/
"--unsat",
/-
Bitwuzla sets this option and it does improve performance practically:
https://github.com/bitwuzla/bitwuzla/blob/0e81e616af4d4421729884f01928b194c3536c76/src/sat/cadical.cpp#L34
-/
"--shrink=0"
]
args := args ++ solverModeFlags mode
-- We implement timeouting ourselves because cadicals -t option is not available on Windows.
let out? runInterruptible timeout { cmd, args, stdin := .piped, stdout := .piped, stderr := .null }
@@ -190,6 +186,12 @@ def satQuery (solverPath : System.FilePath) (problemPath : System.FilePath) (pro
throwError s!"Error {err} while parsing:\n{stdout}"
else
throwError s!"The external prover produced unexpected output, stdout:\n{stdout}stderr:\n{stderr}"
where
solverModeFlags (mode : Frontend.SolverMode) : Array String :=
match mode with
| .proof => #["--unsat"]
| .counterexample => #["--sat"]
| .default => #["--default"]
end External

View File

@@ -344,7 +344,14 @@ def lratBitblaster (goal : MVarId) (ctx : TacticContext) (reflectionResult : Ref
let res
withTraceNode `Meta.Tactic.sat (fun _ => return "Obtaining external proof certificate") do
runExternal cnf ctx.solver ctx.lratPath ctx.config.trimProofs ctx.config.timeout ctx.config.binaryProofs
runExternal
cnf
ctx.solver
ctx.lratPath
ctx.config.trimProofs
ctx.config.timeout
ctx.config.binaryProofs
ctx.config.solverMode
match res with
| .ok cert =>

View File

@@ -4,13 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Henrik Böving
-/
module
prelude
public import Lean.Elab.Tactic.BVDecide.Frontend.BVDecide.Reflect
public import Std.Tactic.BVDecide.Reflect
import Lean.Meta.LitValues
public section
/-!
Provides the logic for reifying `BitVec` expressions.
-/

View File

@@ -4,10 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Henrik Böving
-/
module
prelude
public import Lean.Elab.Tactic.BVDecide.Frontend.BVDecide.ReifiedLemmas
import Lean.Meta.LitValues
public section
/-!

View File

@@ -131,7 +131,7 @@ Run an external SAT solver on the `CNF` to obtain an LRAT proof.
This will obtain an `LratCert` if the formula is UNSAT and throw errors otherwise.
-/
def runExternal (cnf : CNF Nat) (solver : System.FilePath) (lratPath : System.FilePath)
(trimProofs : Bool) (timeout : Nat) (binaryProofs : Bool) :
(trimProofs : Bool) (timeout : Nat) (binaryProofs : Bool) (solverMode : Frontend.SolverMode) :
CoreM (Except (Array (Bool × Nat)) LratCert) := do
IO.FS.withTempFile fun cnfHandle cnfPath => do
withTraceNode `Meta.Tactic.sat (fun _ => return "Serializing SAT problem to DIMACS file") do
@@ -141,7 +141,7 @@ def runExternal (cnf : CNF Nat) (solver : System.FilePath) (lratPath : System.Fi
let res
withTraceNode `Meta.Tactic.sat (fun _ => return "Running SAT solver") do
External.satQuery solver cnfPath lratPath timeout binaryProofs
External.satQuery solver cnfPath lratPath timeout binaryProofs solverMode
if let .sat assignment := res then
return .error assignment

View File

@@ -195,16 +195,16 @@ where
return false
let ctorTyp := ( getConstInfoCtor constInfo.ctors.head!).type
let analyzer state arg := do return state || ( typeCasesRelevant ( arg.fvarId!.getType))
let interesting forallTelescope ctorTyp fun args _ => args.foldlM (init := false) analyzer
let interesting forallTelescope ctorTyp fun args _ =>
-- Note: Important not to short circuit here so that we collect information about all
-- arguments in case we want to split recursively.
args.foldlM (init := false) fun state arg => do
return state || ( typeCasesRelevant ( arg.fvarId!.getType))
return interesting
typeCasesRelevant (expr : Expr) : PreProcessM Bool := do
match_expr expr with
| BitVec n => return ( getNatValue? n).isSome
| _ =>
let some const := expr.getAppFn.constName? | return false
analyzeConst const
let some const := expr.getAppFn.constName? | return false
analyzeConst const
end Frontend.Normalize
end Lean.Elab.Tactic.BVDecide

View File

@@ -369,6 +369,33 @@ def withoutRecover (x : TacticM α) : TacticM α :=
def withRecover (recover : Bool) (x : TacticM α) : TacticM α :=
withReader (fun ctx => { ctx with recover }) x
/-! ## Message log utilities -/
/-- Execute an action while suppressing any new messages it generates.
Restores the original message log after the action completes.
Useful for trying tactics without polluting the message log with errors from failed attempts. -/
def withSuppressedMessages (action : TacticM α) : TacticM α := do
let initialLog Core.getMessageLog
try
action
finally
Core.setMessageLog initialLog
/-- Execute an action and return any new messages it generates.
Restores the original message log afterward.
Useful for inspecting messages produced by a tactic without committing them. -/
def withCapturedMessages (action : TacticM α) : TacticM (α × List Message) := do
let initialLog Core.getMessageLog
let initialMsgCount := initialLog.toList.length
let result action
let newMsgs := ( Core.getMessageLog).toList.drop initialMsgCount
Core.setMessageLog initialLog
return (result, newMsgs)
/-- Check if any messages in the list are errors. -/
def hasErrorMessages (msgs : List Message) : Bool :=
msgs.any (·.severity == .error)
/--
Like `throwErrorAt`, but, if recovery is enabled, logs the error instead.
-/

View File

@@ -193,7 +193,7 @@ def mkSpecTheoremFromStx (ref : Syntax) (proof : Expr) (prio : Nat := eval_prio
mkSpecTheorem type (.stx ( mkFreshId) ref proof) prio
def addSpecTheoremEntry (d : SpecTheorems) (e : SpecTheorem) : SpecTheorems :=
{ d with specs := d.specs.insertCore e.keys e }
{ d with specs := d.specs.insertKeyValue e.keys e }
def addSpecTheorem (ext : SpecExtension) (declName : Name) (prio : Nat) (attrKind : AttributeKind) : MetaM Unit := do
let thm mkSpecTheoremFromConst declName prio

View File

@@ -436,7 +436,7 @@ where
let some tactic := tactic | return vcs
let mut newVCs := #[]
for vc in vcs do
let vcs try evalTacticAt tactic vc catch _ => pure [vc]
let vcs evalTacticAt tactic vc
newVCs := newVCs ++ vcs
return newVCs

View File

@@ -320,6 +320,9 @@ def evalApplyLikeTactic (tac : MVarId → Expr → MetaM (List MVarId)) (e : Syn
@[builtin_tactic Lean.Parser.Tactic.withUnfoldingAll] def evalWithUnfoldingAll : Tactic := fun stx =>
withTransparency TransparencyMode.all <| evalTactic stx[1]
@[builtin_tactic Lean.Parser.Tactic.withUnfoldingNone] def evalWithUnfoldingNone : Tactic := fun stx =>
withTransparency TransparencyMode.none <| evalTactic stx[1]
/--
Elaborate `stx`. If it is a free variable, return it. Otherwise, assert it, and return the free variable.
Note that, the main goal is updated when `Meta.assert` is used in the second case. -/

View File

@@ -22,8 +22,9 @@ structure Context extends Tactic.Context where
open Meta.Grind (Goal)
structure State where
state : Meta.Grind.State
goals : List Goal
symState : Meta.Sym.State
grindState : Meta.Grind.State
goals : List Goal
structure SavedState where
term : Term.SavedState
@@ -288,8 +289,8 @@ open Grind
def liftGrindM (k : GrindM α) : GrindTacticM α := do
let ctx read
let s get
let (a, state) liftMetaM <| (Grind.withGTransparency k) ctx.methods.toMethodsRef ctx.ctx |>.run s.state
modify fun s => { s with state }
let ((a, grindState), symState) liftMetaM <| StateRefT'.run ((Grind.withGTransparency k) ctx.methods.toMethodsRef ctx.ctx |>.run s.grindState) s.symState
modify fun s => { s with grindState, symState }
return a
def replaceMainGoal (goals : List Goal) : GrindTacticM Unit := do
@@ -358,15 +359,17 @@ def mkEvalTactic' (elaborator : Name) (params : Params) : TermElabM (Goal → TS
let methods getMethods
let grindCtx readThe Meta.Grind.Context
let grindState get
let symState getThe Sym.State
-- **Note**: we discard changes to `Term.State`
let (subgoals, grindState') Term.TermElabM.run' (ctx := termCtx) (s := termState) do
let (subgoals, grindState', symState') Term.TermElabM.run' (ctx := termCtx) (s := termState) do
let (_, s) GrindTacticM.run
(ctx := { recover := false, methods, ctx := grindCtx, params, elaborator })
(s := { state := grindState, goals := [goal] }) do
(s := { grindState, symState, goals := [goal] }) do
evalGrindTactic stx.raw
pruneSolvedGoals
return (s.goals, s.state)
return (s.goals, s.grindState, s.symState)
set grindState'
set symState'
return subgoals
return eval
@@ -389,8 +392,9 @@ def GrindTacticM.runAtGoal (mvarId : MVarId) (params : Params) (k : GrindTacticM
let ctx readThe Meta.Grind.Context
/- Restore original config -/
let ctx := { ctx with config := params.config }
let state get
pure (methods, ctx, { state, goals })
let grindState get
let symState getThe Sym.State
return (methods, ctx, { grindState, symState, goals })
let tctx read
k { tctx with methods, ctx, params } |>.run state

View File

@@ -15,6 +15,7 @@ import Lean.Elab.Tactic.Grind.Lint
#grind_lint skip List.replicate_sublist_iff
#grind_lint skip List.Sublist.append
#grind_lint skip List.Sublist.middle
#grind_lint skip List.getLast?_pmap
#grind_lint skip Array.count_singleton
#grind_lint skip Array.foldl_empty
#grind_lint skip Array.foldr_empty

View File

@@ -182,6 +182,7 @@ open LibrarySuggestions in
def elabGrindSuggestions
(params : Grind.Params) (suggestions : Array Suggestion := #[]) : MetaM Grind.Params := do
let mut params := params
let mut added : Array Name := #[]
for p in suggestions do
let attr match p.flag with
| some flag => parseModifier flag
@@ -190,6 +191,7 @@ def elabGrindSuggestions
| .ematch kind =>
try
params addEMatchTheorem params (mkIdent p.name) p.name kind false (warn := false)
added := added.push p.name
catch _ => pure () -- Don't worry if library suggestions gave bad theorems.
| _ =>
-- We could actually support arbitrary grind modifiers,
@@ -197,26 +199,40 @@ def elabGrindSuggestions
-- but this would require a larger refactor.
-- Let's only do this if there is a prospect of a library suggestion engine supporting this.
throwError "unexpected modifier {p.flag}"
unless added.isEmpty do
trace[grind.debug.suggestions] "{added}"
return params
open LibrarySuggestions in
def elabGrindParamsAndSuggestions
(params : Grind.Params)
(ps : TSyntaxArray ``Parser.Tactic.grindParam)
(suggestions : Array Suggestion := #[])
(only : Bool) (lax : Bool := false) : TermElabM Grind.Params := do
let params elabGrindParams params ps (lax := lax) (only := only)
elabGrindSuggestions params suggestions
/-- Add all definitions from the current file. -/
def elabGrindLocals (params : Grind.Params) : MetaM Grind.Params := do
let env getEnv
let mut params := params
let mut added : Array Name := #[]
for (name, ci) in env.constants.map₂.toList do
-- Filter similar to LibrarySuggestions.isDeniedPremise (but inlined to avoid dependency)
-- Skip internal details, but allow private names (which are accessible from current module)
if name.isInternalDetail && !isPrivateName name then continue
if ( Meta.isInstance name) then continue
match ci with
| .defnInfo _ =>
try
params addEMatchTheorem params (mkIdent name) name (.default false) false (warn := false)
added := added.push name
catch _ => pure ()
| _ => continue
unless added.isEmpty do
trace[grind.debug.locals] "{added}"
return params
def mkGrindParams
(config : Grind.Config) (only : Bool) (ps : TSyntaxArray ``Parser.Tactic.grindParam) (mvarId : MVarId) :
TermElabM Grind.Params := do
let params if only then Grind.mkOnlyParams config else Grind.mkDefaultParams config
let suggestions if config.suggestions then
LibrarySuggestions.select mvarId { caller := some "grind" }
else
pure #[]
let mut params elabGrindParamsAndSuggestions params ps suggestions (only := only) (lax := config.lax)
let mut params elabGrindParams params ps (lax := config.lax) (only := only)
if config.suggestions then
params elabGrindSuggestions params ( LibrarySuggestions.select mvarId { caller := some "grind" })
if config.locals then
params elabGrindLocals params
trace[grind.debug.inj] "{params.extensions[0]!.inj.getOrigins.map (·.pp)}"
if params.anchorRefs?.isSome then
/-
@@ -289,21 +305,24 @@ def setGrindParams (stx : TSyntax `tactic) (params : Array Syntax) : TSyntax `ta
def getGrindParams (stx : TSyntax `tactic) : Array Syntax :=
stx.raw[grindParamsPos][1].getSepArgs
/-- Filter out `+suggestions` from the config syntax -/
def filterSuggestionsFromGrindConfig (config : TSyntax ``Lean.Parser.Tactic.optConfig) :
/-- Filter out `+suggestions` and `+locals` from the config syntax -/
def filterSuggestionsAndLocalsFromGrindConfig (config : TSyntax ``Lean.Parser.Tactic.optConfig) :
TSyntax ``Lean.Parser.Tactic.optConfig :=
let configItems := config.raw.getArgs
let filteredItems := configItems.filter fun item =>
-- Keep all items except +suggestions
-- Structure: null node -> configItem -> posConfigItem -> ["+", ident]
match item[0]? with
| some configItem => match configItem[0]? with
| some posConfigItem => match posConfigItem[1]? with
| some ident => !(posConfigItem.getKind == ``Lean.Parser.Tactic.posConfigItem && ident.getId == `suggestions)
| none => true
-- optConfig structure: (Tactic.optConfig [configItem1, configItem2, ...])
-- config.raw.getArgs returns #[null_node], so we need to filter the null node's children
let nullNode := config.raw[0]!
let configItems := nullNode.getArgs
let filteredItems := configItems.filter fun configItem =>
-- Keep all items except +suggestions and +locals
-- Structure: configItem -> posConfigItem -> ["+", ident]
match configItem[0]? with
| some posConfigItem => match posConfigItem[1]? with
| some ident =>
let id := ident.getId.eraseMacroScopes
!(posConfigItem.getKind == ``Lean.Parser.Tactic.posConfigItem && (id == `suggestions || id == `locals))
| none => true
| none => true
config.raw.setArgs filteredItems
config.raw.setArg 0 (nullNode.setArgs filteredItems)
private def elabGrindConfig' (config : TSyntax ``Lean.Parser.Tactic.optConfig) (interactive : Bool) : TacticM Grind.Config := do
if interactive then
@@ -345,7 +364,7 @@ def evalGrindTraceCore (stx : Syntax) (trace := true) (verbose := true) (useSorr
let finish Grind.Action.mkFinish
let goal :: _ Grind.getGoals
| -- Goal was closed during initialization
let configStx' := filterSuggestionsFromGrindConfig configStx
let configStx' := filterSuggestionsAndLocalsFromGrindConfig configStx
if termParamStxs.isEmpty then
let tac `(tactic| grind $configStx':optConfig only)
return #[tac]
@@ -357,7 +376,7 @@ def evalGrindTraceCore (stx : Syntax) (trace := true) (verbose := true) (useSorr
-- let saved ← saveState
match ( finish.run goal) with
| .closed seq =>
let configStx' := filterSuggestionsFromGrindConfig configStx
let configStx' := filterSuggestionsAndLocalsFromGrindConfig configStx
let tacs Grind.mkGrindOnlyTactics configStx' seq termParamStxs
let seq := Grind.Action.mkGrindSeq seq
let tac `(tactic| grind $configStx':optConfig => $seq:grindSeq)

View File

@@ -4,12 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Tactic.Injection
public import Lean.Meta.Tactic.Assumption
public import Lean.Elab.Tactic.ElabTerm
public section
namespace Lean.Elab.Tactic

View File

@@ -29,7 +29,7 @@ partial def headBetaUnderLambda (f : Expr) : Expr := Id.run do
builtin_initialize monotoneExt :
SimpleScopedEnvExtension (Name × Array DiscrTree.Key) (DiscrTree Name)
registerSimpleScopedEnvExtension {
addEntry := fun dt (n, ks) => dt.insertCore ks n
addEntry := fun dt (n, ks) => dt.insertKeyValue ks n
initial := {}
}

Some files were not shown because too many files have changed in this diff Show More