Skip to content

Commit eb443ae

Browse files
committed
fix: hard line break issue in Format
1 parent 4eccb5b commit eb443ae

19 files changed

+298
-72
lines changed

src/Init/Data/Format/Basic.lean

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,37 @@ private structure WorkItem where
142142
indent : Int
143143
activeTags : Nat
144144

145+
/--
146+
A directive for how a given work group should be flattened.
147+
148+
- `allow` indicates that the group is allowed to be flattened; its argument is `true` if
149+
there is sufficient space for it to be flattened (and so it should be), or `false` if not.
150+
- `disallow` means that this group should not be flattened irrespective of space concerns.
151+
This is used at levels of a `Format` outside of any flattening groups. It is necessary to track
152+
this so that mechanisms like post-hard-line-break flattening can know whether to attempt to start
153+
flattening.
154+
-/
155+
inductive FlattenDirective where
156+
| allow (fits : Bool)
157+
| disallow
158+
deriving BEq
159+
160+
/-- Whether the given directive indicates that flattening should occur. -/
161+
def FlattenDirective.shouldFlatten : FlattenDirective → Bool
162+
| allow true => true
163+
| _ => false
164+
145165
private structure WorkGroup where
146-
flatten : Bool
147-
flb : FlattenBehavior
148-
items : List WorkItem
166+
fld : FlattenDirective
167+
flb : FlattenBehavior
168+
items : List WorkItem
149169

150170
private partial def spaceUptoLine' : List WorkGroup → Nat → Nat → SpaceResult
151171
| [], _, _ => {}
152172
| { items := [], .. }::gs, col, w => spaceUptoLine' gs col w
153173
| g@{ items := i::is, .. }::gs, col, w =>
154174
merge w
155-
(spaceUptoLine i.f g.flatten (w + col - i.indent) w)
175+
(spaceUptoLine i.f g.fld.shouldFlatten (w + col - i.indent) w)
156176
(spaceUptoLine' ({ g with items := is }::gs) col)
157177

158178
/-- A monad in which we can pretty-print `Format` objects. -/
@@ -169,11 +189,11 @@ open MonadPrettyFormat
169189
private def pushGroup (flb : FlattenBehavior) (items : List WorkItem) (gs : List WorkGroup) (w : Nat) [Monad m] [MonadPrettyFormat m] : m (List WorkGroup) := do
170190
let k ← currColumn
171191
-- Flatten group if it + the remainder (gs) fits in the remaining space. For `fill`, measure only up to the next (ungrouped) line break.
172-
let g := { flatten := flb == FlattenBehavior.allOrNone, flb := flb, items := items : WorkGroup }
192+
let g := { fld := .allow (flb == FlattenBehavior.allOrNone), flb := flb, items := items : WorkGroup }
173193
let r := spaceUptoLine' [g] k (w-k)
174194
let r' := merge (w-k) r (spaceUptoLine' gs k)
175195
-- Prevent flattening if any item contains a hard line break, except within `fill` if it is ungrouped (=> unflattened)
176-
return { g with flatten := !r.foundFlattenedHardLine && r'.space <= w-k }::gs
196+
return { g with fld := .allow (!r.foundFlattenedHardLine && r'.space <= w-k) }::gs
177197

178198
private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGroup → m Unit
179199
| [] => pure ()
@@ -200,11 +220,15 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
200220
pushNewline i.indent.toNat
201221
let is := { i with f := text (s.extract (s.next p) s.endPos) }::is
202222
-- after a hard line break, re-evaluate whether to flatten the remaining group
203-
pushGroup g.flb is gs w >>= be w
223+
-- note that we shouldn't start flattening after a hard break outside a group
224+
if g.fld == .disallow then
225+
be w (gs' is)
226+
else
227+
pushGroup g.flb is gs w >>= be w
204228
| line =>
205229
match g.flb with
206230
| FlattenBehavior.allOrNone =>
207-
if g.flatten then
231+
if g.fld.shouldFlatten then
208232
-- flatten line = text " "
209233
pushOutput " "
210234
endTags i.activeTags
@@ -220,10 +244,10 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
220244
endTags i.activeTags
221245
pushGroup FlattenBehavior.fill is gs w >>= be w
222246
-- if preceding fill item fit in a single line, try to fit next one too
223-
if g.flatten then
247+
if g.fld.shouldFlatten then
224248
let gs'@(g'::_) ← pushGroup FlattenBehavior.fill is gs (w - " ".length)
225249
| panic "unreachable"
226-
if g'.flatten then
250+
if g'.fld.shouldFlatten then
227251
pushOutput " "
228252
endTags i.activeTags
229253
be w gs' -- TODO: use `return`
@@ -232,7 +256,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
232256
else
233257
breakHere
234258
| align force =>
235-
if g.flatten && !force then
259+
if g.fld.shouldFlatten && !force then
236260
-- flatten (align false) = nil
237261
endTags i.activeTags
238262
be w (gs' is)
@@ -247,7 +271,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
247271
endTags i.activeTags
248272
be w (gs' is)
249273
| group f flb =>
250-
if g.flatten then
274+
if g.fld.shouldFlatten then
251275
-- flatten (group f) = flatten f
252276
be w (gs' ({ i with f }::is))
253277
else
@@ -256,7 +280,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
256280
/-- Render the given `f : Format` with a line width of `w`.
257281
`indent` is the starting amount to indent each line by. -/
258282
def prettyM (f : Format) (w : Nat) (indent : Nat := 0) [Monad m] [MonadPrettyFormat m] : m Unit :=
259-
be w [{ flb := FlattenBehavior.allOrNone, flatten := false, items := [{ f := f, indent, activeTags := 0 }]}]
283+
be w [{ flb := FlattenBehavior.allOrNone, fld := .disallow, items := [{ f := f, indent, activeTags := 0 }]}]
260284

261285
/-- Create a format `l ++ f ++ r` with a flatten group.
262286
FlattenBehaviour is `allOrNone`; for `fill` use `bracketFill`. -/

tests/lean/1079.lean.expected.out

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@
1111
?a = ?a
1212
with
1313
Ordering.eq = Ordering.lt
14-
[Meta.Tactic.simp.rewrite] imp_self:10000: False → False ==> True
14+
[Meta.Tactic.simp.rewrite] imp_self:10000:
15+
False → False
16+
==>
17+
True

tests/lean/973b.lean.expected.out

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
973b.lean:5:8-5:10: warning: declaration uses 'sorry'
22
[Meta.Tactic.simp.discharge] ex discharge ❌️
33
?p x
4-
[Meta.Tactic.simp.discharge] ex discharge ❌️ ?p (f x)
4+
[Meta.Tactic.simp.discharge] ex discharge ❌️
5+
?p (f x)
56
973b.lean:9:8-9:11: warning: declaration uses 'sorry'

tests/lean/discrTreeIota.lean.expected.out

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22
default
33
==>
44
PUnit.unit
5-
[Meta.Tactic.simp.rewrite] eq_self:1000: PUnit.unit = x ==> True
5+
[Meta.Tactic.simp.rewrite] eq_self:1000:
6+
PUnit.unit = x
7+
==>
8+
True

tests/lean/exceptionalTrace.lean.expected.out

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ use `set_option diagnostics true` to get diagnostic information
55
rt + 1
66
[Elab.step] expected type: <not-available>, term
77
binop% HAdd.hAdd✝ rt 1
8-
[Elab.step] expected type: <not-available>, term rt
8+
[Elab.step] expected type: <not-available>, term
9+
rt

tests/lean/run/1234.lean

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ trace: [Meta.Tactic.simp.rewrite] h₁:1000:
2828
if True then ⟨v, ⋯⟩ else ⟨v - 1, ⋯⟩
2929
==>
3030
⟨v, ⋯⟩
31-
[Meta.Tactic.simp.rewrite] eq_self:1000: ⟨v, ⋯⟩ = ⟨v, ⋯⟩ ==> True
31+
[Meta.Tactic.simp.rewrite] eq_self:1000:
32+
⟨v, ⋯⟩ = ⟨v, ⋯⟩
33+
==>
34+
True
3235
-/
3336
#guard_msgs in
3437
example (h₁: k ≤ v - 1) (h₂: 0 < v):
@@ -65,7 +68,10 @@ trace: [Meta.Tactic.simp.rewrite] h₁:1000:
6568
if True then ⟨v, ⋯⟩ else ⟨v - 1, ⋯⟩
6669
==>
6770
⟨v, ⋯⟩
68-
[Meta.Tactic.simp.rewrite] eq_self:1000: ⟨v, ⋯⟩ = ⟨v, ⋯⟩ ==> True
71+
[Meta.Tactic.simp.rewrite] eq_self:1000:
72+
⟨v, ⋯⟩ = ⟨v, ⋯⟩
73+
==>
74+
True
6975
-/
7076
#guard_msgs in
7177
example (h₁: k ≤ v - 1) (h₂: 0 < v):
@@ -100,7 +106,10 @@ trace: [Meta.Tactic.simp.rewrite] h₁:1000:
100106
if True then ⟨v, ⋯⟩ else ⟨v - 1, ⋯⟩
101107
==>
102108
⟨v, ⋯⟩
103-
[Meta.Tactic.simp.rewrite] eq_self:1000: ⟨v, ⋯⟩ = ⟨v, ⋯⟩ ==> True
109+
[Meta.Tactic.simp.rewrite] eq_self:1000:
110+
⟨v, ⋯⟩ = ⟨v, ⋯⟩
111+
==>
112+
True
104113
-/
105114
#guard_msgs in
106115
example (h₁: k ≤ v - 1) (h₂: 0 < v):

tests/lean/run/1380.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ trace: [Meta.Tactic.simp.unify] eq_self:1000, failed to unify
2121
v₁ < v₂
2222
==>
2323
True
24-
[Meta.Tactic.simp.rewrite] Nat.ne_of_gt:1000: v₂ = v₁ ==> False
24+
[Meta.Tactic.simp.rewrite] Nat.ne_of_gt:1000:
25+
v₂ = v₁
26+
==>
27+
False
2528
-/
2629
#guard_msgs in
2730
set_option trace.Meta.Tactic.simp true in

tests/lean/run/1815.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ trace: [Meta.Tactic.simp.rewrite] mul_comm:1000:perm, perm rejected Left a ==> d
1313
==>
1414
a * default
1515
[Meta.Tactic.simp.rewrite] mul_comm:1000:perm, perm rejected a * default ==> default * a
16-
[Meta.Tactic.simp.rewrite] eq_self:1000: Left a = a * default ==> True
16+
[Meta.Tactic.simp.rewrite] eq_self:1000:
17+
Left a = a * default
18+
==>
19+
True
1720
-/
1821
#guard_msgs in
1922
example (a : α) : Left a = Right a := by

tests/lean/run/3257.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ trace: [Meta.Tactic.simp.discharge] bar discharge ✅️
2020
T
2121
==>
2222
True
23-
[Meta.Tactic.simp.rewrite] bar:1000: U ==> True
23+
[Meta.Tactic.simp.rewrite] bar:1000:
24+
U
25+
==>
26+
True
2427
-/
2528
#guard_msgs in
2629
example : U := by

tests/lean/run/790.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ trace: [Meta.Tactic.simp.rewrite] differential_of_linear:1000:
2020
differential f x dx
2121
==>
2222
f dx
23-
[Meta.Tactic.simp.rewrite] eq_self:1000: f dx = f dx ==> True
23+
[Meta.Tactic.simp.rewrite] eq_self:1000:
24+
f dx = f dx
25+
==>
26+
True
2427
-/
2528
#guard_msgs in
2629
example {Y : Type} [Vec Y] (f : Nat → Y) (x dx : Nat)

0 commit comments

Comments
 (0)