Skip to content

Commit c57d966

Browse files
committed
Merge remote-tracking branch 'origin/master' into getElem_simps
2 parents f6f7e21 + 1e752b0 commit c57d966

File tree

14 files changed

+292
-73
lines changed

14 files changed

+292
-73
lines changed

.github/workflows/awaiting-mathlib.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,29 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Check awaiting-mathlib label
13+
id: check-awaiting-mathlib-label
1314
if: github.event_name == 'pull_request'
1415
uses: actions/github-script@v7
1516
with:
1617
script: |
17-
const { labels } = context.payload.pull_request;
18-
if (labels.some(label => label.name == "awaiting-mathlib") && !labels.some(label => label.name == "builds-mathlib")) {
19-
core.setFailed('PR is marked "awaiting-mathlib" but "builds-mathlib" label has not been applied yet by the bot');
18+
const { labels, number: prNumber } = context.payload.pull_request;
19+
const hasAwaiting = labels.some(label => label.name == "awaiting-mathlib");
20+
const hasBreaks = labels.some(label => label.name == "breaks-mathlib");
21+
const hasBuilds = labels.some(label => label.name == "builds-mathlib");
22+
23+
if (hasAwaiting && hasBreaks) {
24+
core.setFailed('PR has both "awaiting-mathlib" and "breaks-mathlib" labels.');
25+
} else if (hasAwaiting && !hasBreaks && !hasBuilds) {
26+
core.info('PR is marked "awaiting-mathlib" but neither "breaks-mathlib" nor "builds-mathlib" labels are present.');
27+
core.setOutput('awaiting', 'true');
2028
}
29+
30+
- name: Wait for mathlib compatibility
31+
if: github.event_name == 'pull_request' && steps.check-awaiting-mathlib-label.outputs.awaiting == 'true'
32+
run: |
33+
echo "::notice title=Awaiting mathlib::PR is marked 'awaiting-mathlib' but neither 'breaks-mathlib' nor 'builds-mathlib' labels are present."
34+
echo "This check will remain in progress until the PR is updated with appropriate mathlib compatibility labels."
35+
# Keep the job running indefinitely to show "in progress" status
36+
while true; do
37+
sleep 3600 # Sleep for 1 hour at a time
38+
done

src/Init/Data/List/Pairwise.lean

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ open Nat
2424

2525
/-! ### Pairwise -/
2626

27-
theorem Pairwise.sublist : l₁ <+ l₂ → l₂.Pairwise R → l₁.Pairwise R
27+
@[grind →] theorem Pairwise.sublist : l₁ <+ l₂ → l₂.Pairwise R → l₁.Pairwise R
2828
| .slnil, h => h
2929
| .cons _ s, .cons _ h₂ => h₂.sublist s
3030
| .cons₂ _ s, .cons h₁ h₂ => (h₂.sublist s).cons fun _ h => h₁ _ (s.subset h)
@@ -37,11 +37,11 @@ theorem Pairwise.imp {α R S} (H : ∀ {a b}, R a b → S a b) :
3737
theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l → R a a' :=
3838
(pairwise_cons.1 p).1 _
3939

40-
theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
40+
@[grind →] theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
4141
(pairwise_cons.1 p).2
4242

4343
set_option linter.unusedVariables false in
44-
theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
44+
@[grind] theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
4545
| [], h => h
4646
| _ :: _, h => h.of_cons
4747

@@ -101,11 +101,11 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa
101101
· exact h₃.1 _ hx
102102
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
103103

104-
theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
104+
@[grind] theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
105105

106-
theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
106+
@[grind =] theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
107107

108-
theorem pairwise_map {l : List α} :
108+
@[grind =] theorem pairwise_map {l : List α} :
109109
(l.map f).Pairwise R ↔ l.Pairwise fun a b => R (f a) (f b) := by
110110
induction l
111111
· simp
@@ -115,11 +115,11 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
115115
(p : Pairwise S (map f l)) : Pairwise R l :=
116116
(pairwise_map.1 p).imp (H _ _)
117117

118-
theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
118+
@[grind] theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
119119
(p : Pairwise R l) : Pairwise S (map f l) :=
120120
pairwise_map.2 <| p.imp (H _ _)
121121

122-
theorem pairwise_filterMap {f : β → Option α} {l : List β} :
122+
@[grind =] theorem pairwise_filterMap {f : β → Option α} {l : List β} :
123123
Pairwise R (filterMap f l) ↔ Pairwise (fun a a' : β => ∀ b, f a = some b → ∀ b', f a' = some b' → R b b') l := by
124124
let _S (a a' : β) := ∀ b, f a = some b → ∀ b', f a' = some b' → R b b'
125125
induction l with
@@ -134,20 +134,20 @@ theorem pairwise_filterMap {f : β → Option α} {l : List β} :
134134
simpa [IH, e] using fun _ =>
135135
fun h a ha b hab => h _ _ ha hab, fun h a b ha hab => h _ ha _ hab⟩
136136

137-
theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
137+
@[grind] theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
138138
(H : ∀ a a' : α, R a a' → ∀ b, f a = some b → ∀ b', f a' = some b' → S b b') {l : List α} (p : Pairwise R l) :
139139
Pairwise S (filterMap f l) :=
140140
pairwise_filterMap.2 <| p.imp (H _ _)
141141

142-
theorem pairwise_filter {p : α → Prop} [DecidablePred p] {l : List α} :
142+
@[grind =] theorem pairwise_filter {p : α → Bool} {l : List α} :
143143
Pairwise R (filter p l) ↔ Pairwise (fun x y => p x → p y → R x y) l := by
144144
rw [← filterMap_eq_filter, pairwise_filterMap]
145145
simp
146146

147-
theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
147+
@[grind] theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
148148
Pairwise.sublist filter_sublist
149149

150-
theorem pairwise_append {l₁ l₂ : List α} :
150+
@[grind =] theorem pairwise_append {l₁ l₂ : List α} :
151151
(l₁ ++ l₂).Pairwise R ↔ l₁.Pairwise R ∧ l₂.Pairwise R ∧ ∀ a ∈ l₁, ∀ b ∈ l₂, R a b := by
152152
induction l₁ <;> simp [*, or_imp, forall_and, and_assoc, and_left_comm]
153153

@@ -157,13 +157,13 @@ theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y →
157157
(x : α) (xm : x ∈ l₂) (y : α) (ym : y ∈ l₁) : R x y := s (H y ym x xm)
158158
simp only [pairwise_append, and_left_comm]; rw [Iff.intro (this l₁ l₂) (this l₂ l₁)]
159159

160-
theorem pairwise_middle {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {a : α} {l₁ l₂ : List α} :
160+
@[grind =] theorem pairwise_middle {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {a : α} {l₁ l₂ : List α} :
161161
Pairwise R (l₁ ++ a :: l₂) ↔ Pairwise R (a :: (l₁ ++ l₂)) := by
162162
show Pairwise R (l₁ ++ ([a] ++ l₂)) ↔ Pairwise R ([a] ++ l₁ ++ l₂)
163163
rw [← append_assoc, pairwise_append, @pairwise_append _ _ ([a] ++ l₁), pairwise_append_comm s]
164164
simp only [mem_append, or_comm]
165165

166-
theorem pairwise_flatten {L : List (List α)} :
166+
@[grind =] theorem pairwise_flatten {L : List (List α)} :
167167
Pairwise R (flatten L) ↔
168168
(∀ l ∈ L, Pairwise R l) ∧ Pairwise (fun l₁ l₂ => ∀ x ∈ l₁, ∀ y ∈ l₂, R x y) L := by
169169
induction L with
@@ -174,16 +174,16 @@ theorem pairwise_flatten {L : List (List α)} :
174174
rw [and_comm, and_congr_left_iff]
175175
intros; exact ⟨fun h l' b c d e => h c d e l' b, fun h c d e l' b => h l' b c d e⟩
176176

177-
theorem pairwise_flatMap {R : β → β → Prop} {l : List α} {f : α → List β} :
177+
@[grind =] theorem pairwise_flatMap {R : β → β → Prop} {l : List α} {f : α → List β} :
178178
List.Pairwise R (l.flatMap f) ↔
179179
(∀ a ∈ l, Pairwise R (f a)) ∧ Pairwise (fun a₁ a₂ => ∀ x ∈ f a₁, ∀ y ∈ f a₂, R x y) l := by
180180
simp [List.flatMap, pairwise_flatten, pairwise_map]
181181

182-
theorem pairwise_reverse {l : List α} :
182+
@[grind =] theorem pairwise_reverse {l : List α} :
183183
l.reverse.Pairwise R ↔ l.Pairwise (fun a b => R b a) := by
184184
induction l <;> simp [*, pairwise_append, and_comm]
185185

186-
@[simp] theorem pairwise_replicate {n : Nat} {a : α} :
186+
@[simp, grind =] theorem pairwise_replicate {n : Nat} {a : α} :
187187
(replicate n a).Pairwise R ↔ n ≤ 1 ∨ R a a := by
188188
induction n with
189189
| zero => simp
@@ -205,10 +205,10 @@ theorem pairwise_reverse {l : List α} :
205205
simp
206206
· exact ⟨fun _ => h, Or.inr h⟩
207207

208-
theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
208+
@[grind] theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
209209
h.sublist (drop_sublist _ _)
210210

211-
theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
211+
@[grind] theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
212212
h.sublist (take_sublist _ _)
213213

214214
theorem pairwise_iff_forall_sublist : l.Pairwise R ↔ (∀ {a b}, [a,b] <+ l → R a b) := by
@@ -247,7 +247,7 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h :
247247
intro a b hab
248248
apply h <;> (apply hab.subset; simp)
249249

250-
theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h : ∀ x ∈ l, p x) :
250+
@[grind =] theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h : ∀ x ∈ l, p x) :
251251
Pairwise R (l.pmap f h) ↔
252252
Pairwise (fun b₁ b₂ => ∀ (h₁ : p b₁) (h₂ : p b₂), R (f b₁ h₁) (f b₂ h₂)) l := by
253253
induction l with
@@ -259,7 +259,7 @@ theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h
259259
rintro H _ b hb rfl
260260
exact H b hb _ _
261261

262-
theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
262+
@[grind] theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
263263
(h : ∀ x ∈ l, p x) {S : β → β → Prop}
264264
(hS : ∀ ⦃x⦄ (hx : p x) ⦃y⦄ (hy : p y), R x y → S (f x hx) (f y hy)) :
265265
Pairwise S (l.pmap f h) := by
@@ -268,15 +268,15 @@ theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f :
268268

269269
/-! ### Nodup -/
270270

271-
@[simp]
271+
@[simp, grind]
272272
theorem nodup_nil : @Nodup α [] :=
273273
Pairwise.nil
274274

275-
@[simp]
275+
@[simp, grind =]
276276
theorem nodup_cons {a : α} {l : List α} : Nodup (a :: l) ↔ a ∉ l ∧ Nodup l := by
277277
simp only [Nodup, pairwise_cons, forall_mem_ne]
278278

279-
theorem Nodup.sublist : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
279+
@[grind →] theorem Nodup.sublist : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
280280
Pairwise.sublist
281281

282282
theorem Sublist.nodup : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
@@ -303,7 +303,7 @@ theorem getElem?_inj {xs : List α}
303303
rw [mem_iff_getElem?]
304304
exact ⟨_, h₂⟩; exact ⟨_ , h₂.symm⟩
305305

306-
@[simp] theorem nodup_replicate {n : Nat} {a : α} :
306+
@[simp, grind =] theorem nodup_replicate {n : Nat} {a : α} :
307307
(replicate n a).Nodup ↔ n ≤ 1 := by simp [Nodup]
308308

309309
end List

src/Lean/Compiler/LCNF/PhaseExt.lean

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,37 @@ abbrev DeclExtState := PHashMap Name Decl
1313
private abbrev declLt (a b : Decl) :=
1414
Name.quickLt a.name b.name
1515

16-
private abbrev sortDecls (decls : Array Decl) : Array Decl :=
16+
private def sortedDecls (s : DeclExtState) : Array Decl :=
17+
let decls := s.foldl (init := #[]) fun ps _ v => ps.push v
1718
decls.qsort declLt
1819

1920
private abbrev findAtSorted? (decls : Array Decl) (declName : Name) : Option Decl :=
2021
let tmpDecl : Decl := default
2122
let tmpDecl := { tmpDecl with name := declName }
2223
decls.binSearch tmpDecl declLt
2324

24-
abbrev DeclExt := SimplePersistentEnvExtension Decl DeclExtState
25-
26-
def mkDeclExt (name : Name := by exact decl_name%) : IO DeclExt := do
27-
registerSimplePersistentEnvExtension {
28-
name := name
29-
addImportedFn := fun _ => {}
30-
addEntryFn := fun decls decl => decls.insert decl.name decl
31-
toArrayFn := (sortDecls ·.toArray)
32-
asyncMode := .sync -- compilation is non-parallel anyway
33-
replay? := some <| SimplePersistentEnvExtension.replayOfFilter
34-
(fun s d => !s.contains d.name) (fun decls decl => decls.insert decl.name decl)
25+
def DeclExt := PersistentEnvExtension Decl Decl DeclExtState
26+
27+
instance : Inhabited DeclExt :=
28+
inferInstanceAs (Inhabited (PersistentEnvExtension Decl Decl DeclExtState))
29+
30+
def mkDeclExt (name : Name := by exact decl_name%) : IO DeclExt :=
31+
registerPersistentEnvExtension {
32+
name,
33+
mkInitial := pure {},
34+
addImportedFn := fun _ => pure {},
35+
addEntryFn := fun s decl => s.insert decl.name decl
36+
exportEntriesFn := sortedDecls
37+
statsFn := fun s =>
38+
let numEntries := s.foldl (init := 0) (fun count _ _ => count + 1)
39+
format "number of local entries: " ++ format numEntries
40+
asyncMode := .sync,
41+
replay? := some <| fun oldState newState _ otherState =>
42+
newState.foldl (init := otherState) fun otherState k v =>
43+
if oldState.contains k then
44+
otherState
45+
else
46+
otherState.insert k v
3547
}
3648

3749
builtin_initialize baseExt : DeclExt ← mkDeclExt

src/Lean/Environment.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ private partial def AsyncConsts.findRec? (aconsts : AsyncConsts) (declName : Nam
454454
let c ← aconsts.findPrefix? declName
455455
if c.constInfo.name == declName then
456456
return c
457+
-- If privacy is the only difference between `declName` and `findPrefix?` result, we can assume
458+
-- `declName` does not exist according to the `add` invariant
459+
guard <| privateToUserName c.constInfo.name != privateToUserName declName
457460
let aconsts ← c.consts.get.get? AsyncConsts
458461
AsyncConsts.findRec? aconsts declName
459462

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/-
2+
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Leonardo de Moura
5+
-/
6+
prelude
7+
import Lean.Meta.Tactic.Grind.ENodeKey
8+
9+
namespace Lean.Meta.Grind
10+
11+
private def hashChild (e : Expr) : UInt64 :=
12+
match e with
13+
| .bvar .. | .mvar .. | .const .. | .fvar .. | .sort .. | .lit .. =>
14+
hash e
15+
| .app .. | .letE .. | .forallE .. | .lam .. | .mdata .. | .proj .. =>
16+
(unsafe ptrAddrUnsafe e).toUInt64
17+
18+
private def alphaHash (e : Expr) : UInt64 :=
19+
match e with
20+
| .bvar .. | .mvar .. | .const .. | .fvar .. | .sort .. | .lit .. =>
21+
hash e
22+
| .app f a => mixHash (hashChild f) (hashChild a)
23+
| .letE _ _ v b _ => mixHash (hashChild v) (hashChild b)
24+
| .forallE _ d b _ | .lam _ d b _ => mixHash (hashChild d) (hashChild b)
25+
| .mdata _ b => mixHash 13 (hashChild b)
26+
| .proj n i b => mixHash (mixHash (hash n) (hash i)) (hashChild b)
27+
28+
private def alphaEq (e₁ e₂ : Expr) : Bool := Id.run do
29+
match e₁ with
30+
| .bvar .. | .mvar .. | .const .. | .fvar .. | .sort .. | .lit .. =>
31+
e₁ == e₂
32+
| .app f₁ a₁ =>
33+
let .app f₂ a₂ := e₂ | false
34+
isSameExpr f₁ f₂ && isSameExpr a₁ a₂
35+
| .letE _ _ v₁ b₁ _ =>
36+
let .letE _ _ v₂ b₂ _ := e₂ | false
37+
isSameExpr v₁ v₂ && isSameExpr b₁ b₂
38+
| .forallE _ d₁ b₁ _ =>
39+
let .forallE _ d₂ b₂ _ := e₂ | false
40+
isSameExpr d₁ d₂ && isSameExpr b₁ b₂
41+
| .lam _ d₁ b₁ _ =>
42+
let .lam _ d₂ b₂ _ := e₂ | false
43+
isSameExpr d₁ d₂ && isSameExpr b₁ b₂
44+
| .mdata d₁ b₁ =>
45+
let .mdata d₂ b₂ := e₂ | false
46+
return isSameExpr b₁ b₂ && d₁ == d₂
47+
| .proj n₁ i₁ b₁ =>
48+
let .proj n₂ i₂ b₂ := e₂ | false
49+
n₁ == n₂ && i₁ == i₂ && isSameExpr b₁ b₂
50+
51+
structure AlphaKey where
52+
expr : Expr
53+
54+
instance : Hashable AlphaKey where
55+
hash k := alphaHash k.expr
56+
57+
instance : BEq AlphaKey where
58+
beq k₁ k₂ := alphaEq k₁.expr k₂.expr
59+
60+
structure AlphaShareCommon.State where
61+
map : PHashMap ENodeKey Expr := {}
62+
set : PHashSet AlphaKey := {}
63+
64+
abbrev AlphaShareCommonM := StateM AlphaShareCommon.State
65+
66+
private def save (e : Expr) (r : Expr) : AlphaShareCommonM Expr := do
67+
if let some r := (← get).set.find? { expr := r } then
68+
let r := r.expr
69+
modify fun { set, map } => {
70+
set
71+
map := map.insert { expr := e } r
72+
}
73+
return r
74+
else
75+
modify fun { set, map } => {
76+
set := set.insert { expr := r }
77+
map := map.insert { expr := e } r |>.insert { expr := r } r
78+
}
79+
return r
80+
81+
private abbrev visit (e : Expr) (k : AlphaShareCommonM Expr) : AlphaShareCommonM Expr := do
82+
if let some r := (← get).map.find? { expr := e } then
83+
return r
84+
else
85+
save e (← k)
86+
87+
/-- Similar to `shareCommon`, but handles alpha-equivalence. -/
88+
def shareCommonAlpha (e : Expr) : AlphaShareCommonM Expr :=
89+
go e
90+
where
91+
go (e : Expr) : AlphaShareCommonM Expr := do
92+
match e with
93+
| .bvar .. | .mvar .. | .const .. | .fvar .. | .sort .. | .lit .. =>
94+
if let some r := (← get).set.find? { expr := e } then
95+
return r.expr
96+
else
97+
modify fun { set, map } => { set := set.insert { expr := e }, map }
98+
return e
99+
| .app f a =>
100+
visit e (return mkApp (← go f) (← go a))
101+
| .letE n t v b nd =>
102+
visit e (return mkLet n t (← go v) (← go b) nd)
103+
| .forallE n d b bi =>
104+
visit e (return mkForall n bi (← go d) (← go b))
105+
| .lam n d b bi =>
106+
visit e (return mkLambda n bi (← go d) (← go b))
107+
| .mdata d b =>
108+
visit e (return mkMData d (← go b))
109+
| .proj n i b =>
110+
visit e (return mkProj n i (← go b))
111+
112+
end Lean.Meta.Grind

0 commit comments

Comments
 (0)