Zulip Chat Archive

Stream: mathlib4

Topic: OfNat.ofNat visible


Yury G. Kudryashov (Jul 15 2023 at 15:54):

Sometimes I get OfNat.ofNat 2 instead of 2 in the info view (failed to minimize so far). Does it mean that this 2 is different from a "normal" 2?

Eric Wieser (Jul 15 2023 at 16:15):

I think this is actually OfNat.ofNat (OfNat.ofNat <a raw 2 literal>)

Eric Wieser (Jul 15 2023 at 16:16):

Whereas a normal 2 is OfNat.ofNat <a raw 2 literal>

Yury G. Kudryashov (Jul 15 2023 at 16:48):

How can I test this?

James Gallicchio (Jul 15 2023 at 16:49):

#check OfNat.ofNat (nat_lit 1)                -- 1 : ℕ
#check OfNat.ofNat (OfNat.ofNat (nat_lit 1))  -- OfNat.ofNat 1 : ℕ

Yury G. Kudryashov (Jul 15 2023 at 16:51):

I mean test in the actual non-minimal example.

Yury G. Kudryashov (Jul 15 2023 at 16:51):

set_option ? ?

Eric Wieser (Jul 15 2023 at 16:51):

What's the tactic that makes it appear?

Yury G. Kudryashov (Jul 15 2023 at 16:57):

simp

Yury G. Kudryashov (Jul 15 2023 at 16:57):

But AFAIR (can test in an hour), set_option pp.all true doesn't show nested OfNat.ofNat.

Kyle Miller (Jul 15 2023 at 17:08):

Apparently set_option pp.coercions false should turn off hiding OfNat.ofNat

Eric Wieser (Jul 15 2023 at 17:08):

Can you squeeze the simp to find the bad lemma?

Kyle Miller (Jul 15 2023 at 17:09):

The source code is consistent with only the innermost OfNat.ofNat being hidden if they're nested.

Eric Wieser (Jul 15 2023 at 17:11):

Does the pretty-printer distinguish raw literals (which should never appear) from "regular" literals?

Kyle Miller (Jul 15 2023 at 17:16):

No, raw literals get printed in the same way: https://github.com/leanprover/lean4/blob/d37bbf4292c72798afdff8bf5488df09193fde58/src/Lean/PrettyPrinter/Delaborator/Builtins.lean#L592

Kyle Miller (Jul 15 2023 at 17:16):

The only difference would be what you see when you hover over it in the infoview (is it just a nat? or does it have an OfNat.ofNat?)

Yury G. Kudryashov (Jul 15 2023 at 18:19):

With pp.coercions false, it's just a usual OfNat.ofNat 2, not OfNat.ofNat (OfNat.ofNat 2).

Yury G. Kudryashov (Jul 15 2023 at 18:21):

The (very non-minimal) example is at the end of Mathlib/Geometry/Euclidean/Inversion/Calculus.lean in branch#YK-inversion-fderiv

Kyle Miller (Jul 15 2023 at 18:56):

Here's a little delaborator to help debug this:

section
open Lean PrettyPrinter Delaborator SubExpr

@[delab lit]
def delabLit : Delab := do
  let .lit (.natVal n)  getExpr | failure
  `(nat_lit $(quote n))

end

It prints natural number literals as nat_lit 37 for example

Kyle Miller (Jul 15 2023 at 18:57):

I see what the issue is though: the OfNat.ofNat delaborator doesn't expect numbers to be functions, and in your example the number is a function that's being applied to an argument

Kyle Miller (Jul 15 2023 at 18:57):

So there's not really anything wrong with the expression, it's just not pretty printing right

Kyle Miller (Jul 15 2023 at 18:58):

Here's the offending expression: OfNat.ofNat 2 y

Mario Carneiro (Jul 15 2023 at 20:17):

The easiest way to determine whether you are looking at a double ofNat vs a single ofNat or a raw numeral is to hover over the expression in the infoview. Hovering over raw numeral 2 shows 2 in the hover, and hovering over a 2 ofNat expression shows ofNat 2 ... in the hover

Mario Carneiro (Jul 15 2023 at 20:18):

it would be nice if raw numerals were printed as nat_lit 2

Kyle Miller (Jul 15 2023 at 20:24):

Kyle Miller said:

The only difference would be what you see when you hover over it in the infoview (is it just a nat? or does it have an OfNat.ofNat?)

Yeah, I was doing that but wanted to be sure nothing weird was going on (and I got tired of hovering over all the numbers in the goal state), before I noticed the y argument

Kyle Miller (Jul 15 2023 at 20:26):

Mario Carneiro said:

it would be nice if raw numerals were printed as nat_lit 2

This line would just need to be | Literal.natVal n => `(nat_lit $(quote n)). Should that be behind a pp.nat_lit option?

Eric Wieser (Jul 15 2023 at 20:35):

Wouldn't that break the delaboration of ofNat (nat_lit 2) to print as nat_lit 2?

Kyle Miller (Jul 15 2023 at 20:39):

No, OfNat.ofNat isn't implemented as an app_unexpander, but as a delaborator

Kyle Miller (Jul 15 2023 at 20:42):

I linked the source code, but I'll paste it here. It does a pattern match on the Expr. Delaborators go outside-in and, for applications, app unexpanders go inside-out. This runs before the lit delaborator or the app delaborator.

@[builtin_delab app.OfNat.ofNat]
def delabOfNat : Delab := whenPPOption getPPCoercions do
  let .app (.app _ (.lit (.natVal n))) _  getExpr | failure
  return quote n

Last updated: Dec 20 2023 at 11:08 UTC