Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: Incorrect macro expansion(?) in doElem macro
Jannis Limperg (Nov 07 2024 at 14:35):
A student of mine is trying to write a macro that transforms a match
in a monadic context (i.e., the match
is a doElem
) into a different match
. However, something seems to be going wrong when the macro is run: the new match
gets a different right-hand side than the old match
, even though we're not modifying the matchAlt
s at all. MWE:
import Lean
open Lean Lean.Parser Lean.Parser.Term
attribute [run_parser_attribute_hooks] matchAltExpr
macro "match_expri " t:term " with " alts:matchAltExpr* : doElem => do
`(doElem| match $t:term with $alts:matchAlt*)
run_meta
show MetaM Expr from do
match_expri (Expr.const `True []) with
| e => return e
/-
application type mismatch
pure PUnit.unit
argument
PUnit.unit
has type
PUnit : Sort ?u.807
but is expected to have type
Expr : Type
-/
Tracing shows that at some point during elaboration, the return e
becomes return PUnit.unit
. But I have no idea why this happens. @Sebastian Ullrich can you maybe help?
Daniel Weber (Nov 07 2024 at 18:58):
This causes a crash :thinking:
import Lean
open Lean Lean.Parser Lean.Parser.Term
attribute [run_parser_attribute_hooks] matchAltExpr
macro "match_expri " t:term " with " alts:matchAltExpr* : doElem => do
`(doElem| match $t:term with $alts:matchAlt*)
set_option trace.Elab.match_syntax true
axiom test : False
run_meta
show MetaM Expr from do
match_expri test with
Jannis Limperg (Nov 07 2024 at 19:41):
The match
elaborator might (reasonably) rely on the fact that there's no closed term of type False
. So this might be unrelated.
Daniel Weber (Nov 07 2024 at 19:42):
I thought using match
there works, but now it doesn't seem to
Thomas Murrills (Nov 07 2024 at 21:03):
I think this has to do with the fact that matchAltExpr
parses a term
on the rhs of the match alt, when you want to parse a doSeq
. matchAlt
(s
) takes a default argument (rhsParser := termParser)
, and matchAltExpr
is a thin wrapper around that; likewise, doMatchAlts
is a thin wrapper around matchAlts (rhsParser := doSeq)
.
(Lean doesn't like the direct macro
version of this, though—I'm guessing because doMatchAlts
haven't been prepped for use in quotations.) (lead
precedence is cargo-culted from other match
es.)
import Lean
open Lean Lean.Parser Lean.Parser.Term
syntax:lead (name := matchExpri) "match_expri " term " with " doMatchAlts : doElem
macro_rules
| `(doElem|match_expri $t:term with $alts) => `(doElem|match $t:term with $alts)
#eval -- Lean.Expr.const `True []
show MetaM Expr from do
match_expri (Expr.const `True []) with
| e => return e
Last updated: May 02 2025 at 03:31 UTC