leanprover / leanprover/lean4

`liftTermElabM` uses a non-default meta context

Open
#3,499 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug P-low
Dominant language
Lean
Stars
9.2k
Forks
990
Avg merge
1d 17h
Merged PRs (30d)
175

Description

In leanprover/std4#671, there was an issue in the simpNF linter which was reduced to the setting of foApprox from the MetaM state. The problem is that not all methods for lifting a MetaM into IO to run it set the config in the same way:

import Lean.Meta.Tactic.Simp.Main
import Std.Tactic.OpenPrivate
import Std.Tactic.RunCmd

def MyPred (_ : Nat → Nat) : Prop := True
@[simp] theorem bad1 (f : Unit → Nat → Nat) : MyPred (f ()) = True := sorry

open Lean Elab Meta Tactic Term 

def test : MetaM Unit := withReducible do
  let (t, _) ← Elab.Term.TermElabM.run do
    Elab.Term.elabTerm (← `(fun f : Unit → Nat → Nat => MyPred (f ()))) none
  let ctx := { ← Simp.Context.mkDefault with config.decide := false }
  lambdaLetTelescope t fun _ lhs => do
    let ({ expr := lhs', .. }, _) ← simp lhs ctx
    if lhs == lhs' then throwError "did not simplify"

run_cmd Command.runTermElabM fun _ => test                             -- ok
run_cmd Command.liftTermElabM test                                     -- ok
run_elab test                                                          -- ok
run_meta test                                                          -- ok
#eval show TermElabM _ from test                                       -- ok
#eval show MetaM _ from test                                           -- fail
#eval show CoreM _ from MetaM.run' test {} {}                          -- fail
#eval show CoreM _ from MetaM.run' test { config.foApprox := true } {} -- ok
open private mkMetaContext from Lean.Elab.Command in
#eval show CoreM _ from MetaM.run' test mkMetaContext {}               -- ok

The fact that the default MetaM context constructed by {} is not the same as the MetaM context used by liftTermElabM (and transitively, most regular metaprogramming code) is error-prone since it means that you get different results depending on whether you use MetaM.run' or liftTermElabM, resulting in the above-demonstrated inconsistency. My recommendation is to have the current mkMetaContext be the default (i.e. make {} do the same thing as mkMetaContext).

cc: @leodemoura

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the supplied reproducer and compare MetaM.run' with liftTermElabM, Command.runTermElabM, and the mkMetaContext path. Read the construction and defaulting behavior of mkMetaContext and MetaM.run'; done means the default {} context produces the same behavior as the context used by liftTermElabM without breaking the demonstrated metaprogramming cases.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.