Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

invalid match-expression, type of pattern variable 'match_eq✝' contains metavariables #30

Open
eric-wieser opened this issue Dec 15, 2023 · 7 comments

Comments

@eric-wieser
Copy link
Member

The following example:

import Qq

open Qq Lean.Meta

example (qo : Q(Option Nat)) (o : Option Nat) : MetaM Unit := do
  match qo with
  | ~q(some $qx) => match o with
    | some x => pure ()
    | _ => pure ()

gives the error:

invalid match-expression, type of pattern variable 'match_eq✝' contains metavariables
  «$qo» =Q some «$qx»

Indeed, the type of match_eq✝ in the goal in

example (qo : Q(Option Nat)) : MetaM Unit := do
  match qo with
  | ~q(some $qx) => sorry

has a metavariable for the Level argument.

@eric-wieser
Copy link
Member Author

Replacing the inner match with match (generalizing := false) o with or match id o with is sufficient as a workaround, though of course this disables generalization.

@eric-wieser
Copy link
Member Author

(And with leanprover/lean4#3060, this obviously also affects let some x := o which must be written as let some x := id o)

@eric-wieser
Copy link
Member Author

My initial thought was that these lines are missing a let argLvlExpr ← instantiateMVarsQ argLvlExpr:

quote4/Qq/Match.lean

Lines 208 to 212 in ccba5d3

let argLvlExpr ← mkFreshExprMVarQ q(Level)
let argTyExpr ← mkFreshExprMVarQ q(Quoted (.sort $argLvlExpr))
let e' ← elabTermEnsuringTypeQ e q(Quoted $argTyExpr)
let argTyExpr ← instantiateMVarsQ argTyExpr

but this doesn't seem to make any difference.

github-merge-queue bot pushed a commit to leanprover/lean4 that referenced this issue Jan 23, 2024
As suggested by @kmill, removing an unnecessary `let` (possibly only
there in the first place for copy/paste reasons) seems to fix the
included test.

This makes `~q()` matching in quote4 noticeably more useful in things
like `norm_num` (as it fixes
leanprover-community/quote4#29)

It also makes a quote4 bug slightly more visible
(leanprover-community/quote4#30), but the bug
there already existed anyway, and isn't caused by this patch.

Fixes #3065
mathlib-bors bot pushed a commit to leanprover-community/mathlib4 that referenced this issue Jan 25, 2024
leanprover/lean4#3060 exposed the latent leanprover-community/quote4#30 (by propagating it from `if let` and `match` to `let`). The workaround is thankfully trivial.
@0art0
Copy link

0art0 commented Jan 1, 2025

I'm facing this issue too; in my case, the match was sensitive to the order of the arguments, and swapping them allowed me to work around this bug.

import Lean
import Qq

open Lean Meta Qq

def test : (P : Q(Prop)) → (args : List Nat) → MetaM String
  | ~q($A ∧ $B), [] => return "and"
  | _, _ => return "other"

def test' : (args : List Nat) → (P : Q(Prop)) → MetaM String
  | [], ~q($A ∧ $B) => return "and"
  | _, _ => return "other"

When I edit this line:

let argLvlExpr ← mkFreshExprMVarQ q(Level)

to hard-code the universe level, everything seems to work. I suspect that argLvlExpr actually needs to be a Level metavariable created by mkFreshLevelMVar, but I haven't been able to figure out how to quote such a thing into the type of argTyExpr.

@eric-wieser
Copy link
Member Author

mkFreshLevelMVar is not correct here; we're building a metavariable to hold an Expr corresponding to a Level, not a metavariable for a level itself.

@0art0
Copy link

0art0 commented Jan 2, 2025

A metavariable for a Level created that way doesn't seem to play well with unification, so I was hoping that argTyExpr could somehow be defined as

let argTyExpr ← mkFreshExprMVarQ q(Quoted (.sort (← mkFreshLevelMVar))

instead of

let argTyExpr ← mkFreshExprMVarQ q(Quoted (.sort $argLvlExpr))

(the code I've written doesn't work with the quote interpolation.)

@eric-wieser
Copy link
Member Author

I think the confusion here is between metavariables which are created at match time (resolved with defeq), and metavariables which are created and resolved while elaborating the ~q syntax itself. I'm pretty sure this is the former, though most likely one type of metavariable ends up instantiated with the other which makes the whole thing rather confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants