Zulip Chat Archive

Stream: lean4

Topic: user-facing metavariable names shared between goals


Floris van Doorn (Nov 16 2023 at 14:47):

Is this error expected? I was surprised that the metavariable name ?h refers to the same metavariable in different subgoals.

example {p q r s : Prop} (h1 : p  q) (h2 : r  s)
    (hp : p) (hr : r) : q  s := by
  constructor
  · refine h1 ?h
    exact hp
  · refine h2 ?h -- error, since `?h` has type `p`.
    exact hr

(note: I generally don't type ?h myself, but ?_. In this case I used apply? in two separate subgoals, and the suggestions of apply? are of the form refine ... ?h)

Mario Carneiro (Nov 16 2023 at 16:52):

Oh, I was just thinking about opening an RFC about this. Yes, this is a known issue and it is surprising to me that it isn't a higher concern given that we use short goal names all the time

Mario Carneiro (Nov 16 2023 at 16:53):

The thing is, the tactic state doesn't really have "scoping" in the sense that you are thinking about

Mario Carneiro (Nov 16 2023 at 16:54):

It's even worse than this: apply and other tactics automatically name their goals, and if you use that name in your ?foo metavariables then you will pick up old assignments

Mario Carneiro (Nov 16 2023 at 16:58):

example (f : (x y : Nat)  True) : True  True := by
  constructor
  next =>
    apply f
    · exact 0
    · exact 1
  next =>
    let z := ?x + ?y
    -- z := 0 + 1
    exact f 0 z

Floris van Doorn (Nov 16 2023 at 17:06):

I think this is not a higher concern because we rarely name goals ourselves, and all automatically-named goals generate a fresh name (I think?)

Mario Carneiro (Nov 16 2023 at 17:09):

No, they are not fresh names, that's the issue

Mario Carneiro (Nov 16 2023 at 17:09):

they are completely outside the hygiene system

Mario Carneiro (Nov 16 2023 at 17:09):

unless you write ?a or case a => inside a macro but that's not a very common situation

Floris van Doorn (Nov 16 2023 at 17:12):

I see. What I meant is that apply will at least not re-use existing metavariables with the same user-facing name.

Mario Carneiro (Nov 16 2023 at 17:12):

But when you use the metaprogramming API to create a new named mvar, it will not be unified with other mvars with the same user name, it will just "shadow" the original

Mario Carneiro (Nov 16 2023 at 17:12):

No, it will

Mario Carneiro (Nov 16 2023 at 17:12):

Er, it can make multiple goals with the same name but the metaprogramming API doesn't try to be smart about this and unify them, unlike the ?a syntax

Floris van Doorn (Nov 16 2023 at 17:13):

I mean, in this example, the second apply f will generate 2 new subgoals, not reuse the existing ?x and ?y.

example (f : (x y : Nat)  True) : True  True := by
  constructor
  next =>
    apply f
    · exact 0
    · exact 1
  next =>
    apply f
    · exact 2
    · exact 3

Floris van Doorn (Nov 16 2023 at 17:13):

Oh juicy, I just got a stack overflow

example (f : (x y : Nat)  True) : True  True := by
  constructor
  next =>
    apply f
    · exact ?x

Mario Carneiro (Nov 16 2023 at 17:13):

yep, that one is fun

Thomas Murrills (Nov 16 2023 at 17:13):

The exposed mvar names issue was brought up in this thread, which suggests a combinator for hiding goals created during execution of some monad computation

Mario Carneiro (Nov 16 2023 at 17:14):

this has to do with the fact that lean doesn't really do the occurs check as often as it should

Mario Carneiro (Nov 16 2023 at 17:17):

Maybe we should just have another syntax like ?=a for reusing an existing metavariable, this is almost impossible to use correctly from a user perspective as currently designed

Mario Carneiro (Nov 16 2023 at 17:18):

(and I can count on one hand the number of times I actually wanted to reuse a metavariable with named mvar syntax)

Floris van Doorn (Nov 16 2023 at 17:19):

Fair, although I can personally also count on one hand the number of times I actually gave a metavariable a name manually.

Mario Carneiro (Nov 16 2023 at 17:20):

True. But that road leads to "?a considered harmful"

Mario Carneiro (Nov 16 2023 at 17:20):

We could certainly have apply? et al explicitly use ?_ instead of named mvars

Kyle Miller (Nov 16 2023 at 17:25):

@Floris van Doorn Here's the issue for your last example: bug: exact tactic is missing an occurs check

Mario Carneiro (Nov 16 2023 at 17:29):

I think you could trace that apply? behavior back to the show_term tactic, which tries to replicate the behavior of the tactic it replaces, including the names of generated goals

Mario Carneiro (Nov 16 2023 at 17:29):

Although I suppose it won't get the order right regardless

Floris van Doorn (Nov 16 2023 at 19:02):

Oh, we also have a new version of the "a"-bug :grinning: (although in this case a actually occurs in the definition of And)

example : True  True  := by
  constructor
  · refine ?a -- error

Last updated: Dec 20 2023 at 11:08 UTC