Zulip Chat Archive

Stream: lean4

Topic: tactic to fail with error message


Heather Macbeth (Jun 25 2023 at 21:05):

I'd like to change the error message of a finishing tactic (for use in a macro which wraps that tactic). Is there a more idiomatic way to do it than (try ...) <;> fail "my error message"?

syntax "foo" : tactic

macro_rules | `(tactic| foo) => `(tactic| (try exact rfl) <;> fail "zz")

Kyle Miller (Jun 25 2023 at 21:34):

You can also do

syntax "foo" : tactic

macro_rules | `(tactic| foo) => `(tactic| fail "zz")
macro_rules | `(tactic| foo) => `(tactic| exact rfl)

Tactic macros do backtracking, and they are tried in reverse-definition order

Kyle Miller (Jun 25 2023 at 21:35):

If you want it as a single rule, then better than (try ...) <;> ... is first | exact rfl | fail "zz" (like this example)

Heather Macbeth (Jun 25 2023 at 21:50):

Those are two very nice solutions. Thanks!

Damiano Testa (Jun 25 2023 at 22:10):

Kyle, maybe I am misunderstanding your suggestion, but with macro_rules it seems that if all available choices fail, then the last-defined one is used:

syntax "foo" : tactic

macro_rules | `(tactic| foo) => `(tactic| fail "zz")
macro_rules | `(tactic| foo) => `(tactic| exact rfl)

example : False := by
  foo
/-
type mismatch
  rfl
has type
  ?m.3525 = ?m.3525 : Prop
but is expected to have type
  False : Prop
-/

You get zz if instead you do

syntax "foo" : tactic

macro_rules | `(tactic| foo) => `(tactic| exact rfl)
macro_rules | `(tactic| foo) => `(tactic| fail "zz")

example : False := by
  foo  -- zz

Kyle Miller (Jun 25 2023 at 22:17):

@Damiano Testa I'll admit I might have it backwards!

Damiano Testa (Jun 25 2023 at 22:19):

No, I think that what you said was correct, when one of the tactics succeeds: in this case, Lean chooses the top-mostlast successful tactic. If they all fail, then again Lean applies the top-mostlast tactic, and that is the error that you see.

Damiano Testa (Jun 25 2023 at 22:21):

So, if you want to replace the error message, you should make the error message that you want to display be the last-defined behaviour of the tactic.

Kyle Miller (Jun 25 2023 at 22:25):

If you want it to also be extensible, then something I've seen (like for the GetElem index bounds tactic) is a two-level system, where macro 1 has two expansions, macro 2 and an error message, and then macro 2 is the main implementation. That way you can create rules for macro 2 without changing that the error message is last for macro 1

Damiano Testa (Jun 25 2023 at 22:31):

Ah, nice!

Until now, I hadn't realized that if one of the steps of your macro is an error message, then all previously defined error messages will never display.


Last updated: Dec 20 2023 at 11:08 UTC