Zulip Chat Archive

Stream: lean4

Topic: change _ at h fails


Sven Manthe (Jun 18 2024 at 20:39):

This feels like a bug, but I have no understanding of what is going on in the following MWE:

def g (_ : Nat) : Nat := 0
theorem iff (a : Nat) :
  0 = g 0  0 = a := by sorry
theorem test
  (T : Unit)
  (h : 0 = g 0)
  (ih : T = T) --removing this parameter makes change succeed below
  : 0 = g 0 := by
  --change _ at h --adding this line makes change succeed below
  rw [iff] at h
  change _ at h --fails with type mismatch

Floris van Doorn (Jun 18 2024 at 21:26):

Thanks for the minimization! The precise error is

type mismatch
  this
has type
  ?m.158 : Sort ?u.157
but is expected to have type
  0 = ?m.129 : Prop

Sven Manthe (Jun 18 2024 at 22:11):

Even swapping the order of the parameters h and ih makes the error go away (which also explains why the first change helps)

Daniel Weber (Jun 19 2024 at 15:20):

def g (_ : Nat) : Nat := 0
theorem iff (a : Nat) :
  0 = g 0  0 = a := by sorry

theorem test
  (T : Unit)
  (h : 0 = g 0)
  (ih : T = T) --removing this parameter makes change succeed below
  : 0 = g 0 := by
  --change _ at h --adding this line makes change succeed below
  rw [iff ?p] at h
  change 0 = ?p at h --fails with type mismatch

Gives

synthetic hole has already been defined with an incompatible local context

which might be relevant?

Daniel Weber (Jun 19 2024 at 15:26):

theorem test
    (T : Unit) (ih : T = T) (h : 0 = g 0)
    : 0 = g 0 := by
  let n : Nat := ?p
  rw [iff ?p] at h

gives

T: Unit
ih: T = T
h: 0 = g 0
h: 0 = ?p
n: Nat := ?p
 0 = g 0

while

theorem test
    (T : Unit) (h : 0 = g 0) (ih : T = T)
    : 0 = g 0 := by
  let n : Nat := ?p
  rw [iff ?p] at h

gives

T: Unit
h: 0 = g 0
h: 0 = ?p
ih: T = T
n: Nat := ?m.142 ih
 0 = g 0

Jovan Gerbscheid (Jun 20 2024 at 00:46):

The problem is that rewriting a local variable replaces later free variables with different free variables of the same name. So the ih after the rewrite is different from the ih before the rewrite. So metavariables before and after the rewrite depend on different ih, so they are not compatible.

import Lean

open Lean Elab

elab "log_local_contexts" : tactic => do
  let mctx  getMCtx
  let log decls := decls.toArray.filterMap (Option.map (fun decl => (Expr.fvar decl.fvarId, decl.fvarId.name)))
  logInfo m!"local context of ?a: {log (← (mctx.userNames.find! `a).getDecl).lctx.decls}"
  Tactic.withMainContext do
  logInfo m!"local context of ?b: {log (← (mctx.userNames.find! `b).getDecl).lctx.decls}"

theorem test
  (h : True)
  (s : String) -- removing this makes `exact rfl` succeed
  : True := by
  let a : Nat := ?a
  rw [Eq.refl True] at h -- removing this makes `exact rfl` succeed
  let b : Nat := ?b
  /-
  local context of ?a: [(test, _uniq.1176), (h, _uniq.1177), (s, _uniq.1178)]
  -/
  /-
  local context of ?b: [(test, _uniq.1176), (h✝, _uniq.1177), (h, _uniq.1199), (s, _uniq.1202), (a, _uniq.1203)]
  -/
  log_local_contexts
  have : a = b := by
   exact rfl -- error

Jovan Gerbscheid (Jun 23 2024 at 15:57):

Here's another example that fails for the same reason when there is an extra variable in the local context:

example (h : 0 = 2) (s : String) : False := by
  /-
  tactic 'rewrite' failed, did not find instance of the pattern in the target expression
    ?m.84 - ?m.85

  h✝: 0 = 2
  h: ?m.67 - ?m.67 = 2
  s: String
  ⊢ False
  -/
  rw [ Nat.sub_self,  Nat.sub_eq] at h

Sven Manthe (Jul 31 2024 at 17:48):

https://github.com/leanprover/lean4/issues/4885


Last updated: May 02 2025 at 03:31 UTC