-
Notifications
You must be signed in to change notification settings - Fork 446
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
RFC: A single rfl tactic implementation #3302
Comments
Having a closer look. One issue is that the order of parameters in
(it would have to be If one still wants to persue the goal of a
|
There is: In |
There is another option you did not list:
This would be desirable for other reasons as well; I recall something similar coming up with being able to use In short, the issue here is not unique to |
Ah, yes, parameter vs. index makes sense, thanks. True, extending |
I think keeping Another reason you probably want |
(Just for my own record: I attempted this refactoring, but got stuck in what’s either a boostrapping maze or a misunderstanding of how things works, and ran out of time today. Putting this back on the stack of things to look at when I have some extra time to spare. If someone else does tackles before I do then of course I don’t mind.) (Update: #3714 has the tactic as I think it could be, it doesn’t swap it out for |
this implements the first half of #3302: It improves the extensible `rfl` tactic (the one that looks at `refl` attributes) to * Check itself that the lhs and rhs are defEq, and give a nice consistent error message when they don't (instead of just passing on the less helpful error message from `apply Foo.refl`) * Also handle `Eq` and `HEq` (built in) and `Iff` (using the attribute) Care ist taken that, as before, the transparency setting affects comparing the lhs and rhs, but not the reduction of the relation A test file checks the various failure modes and error messages. I believe this `apply_rfl` can serve as the only implementation of `rfl`, which would then complete #3302, but that seems to require a non-trivial bootstrapping dance, so maybe better done separately.
The new message is
Marking it as closing soon |
#3714 and #3718 contain further improvements, including even better error messages, by having a single implementation, but I got stalled there because of the different transparency levels the current tactics work at. Might revisit that later, but I have the draft PRs to recall, so happy to close this issue. |
This implements the first half of #3302: It improves the extensible `apply_rfl` tactic (the one that looks at `refl` attributes, part of the `rfl` macro) to * Check itself and ahead of time that the lhs and rhs are defEq, and give a nice consistent error message when they don't (instead of just passing on the less helpful error message from `apply Foo.refl`), and using the machinery that `apply` uses to elaborate expressions to highlight diffs in implicit arguments. * Also handle `Eq` and `HEq` (built in) and `Iff` (using the attribute) Care is taken that, as before, the current transparency setting affects comparing the lhs and rhs, but not the reduction of the relation So before we had ```lean opaque P : Nat → Nat → Prop @[refl] axiom P.refl (n : Nat) : P n n /-- error: tactic 'apply' failed, failed to unify P ?n ?n with P 42 23 ⊢ P 42 23 -/ #guard_msgs in example : P 42 23 := by apply_rfl opaque withImplicitNat {n : Nat} : Nat /-- error: tactic 'apply' failed, failed to unify P ?n ?n with P withImplicitNat withImplicitNat ⊢ P withImplicitNat withImplicitNat -/ #guard_msgs in example : P (@withImplicitNat 42) (@withImplicitNat 23) := by apply_rfl ``` and with this PR the messages we get are ``` error: tactic 'apply_rfl' failed, The lhs 42 is not definitionally equal to rhs 23 ⊢ P 42 23 ``` resp. ``` error: tactic 'apply_rfl' failed, The lhs @withImplicitNat 42 is not definitionally equal to rhs @withImplicitNat 23 ⊢ P withImplicitNat withImplicitNat ``` A test file checks the various failure modes and error messages. I believe this `apply_rfl` can serve as the only implementation of `rfl`, which would then complete #3302, and actually expose these improved error messages to the user. But as that seems to require a non-trivial bootstrapping dance, it’ll be separate.
I actually picked up the work on these PRs. So reopening this, so that merging them can close it properly :-D |
building upon #3714, this (almost) implements the second half of #3302. The main effect is that we now get a better error message when `rfl` fails. For ```lean example : n+1+m = n + (1+m) := by rfl ``` instead of the wall of text ``` The rfl tactic failed. Possible reasons: - The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). - The arguments of the relation are not equal. Try using the reflexivity lemma for your relation explicitly, e.g. `exact Eq.refl _` or `exact HEq.rfl` etc. n m : Nat ⊢ n + 1 + m = n + (1 + m) ``` we now get ``` error: tactic 'rfl' failed, the left-hand side n + 1 + m is not definitionally equal to the right-hand side n + (1 + m) n m : Nat ⊢ n + 1 + m = n + (1 + m) ``` Unfortunately, because of very subtle differences in semantics (which transparency setting is used when reducing the goal and whether the “implicit lambda” feature applies) I could not make this simply the only `rfl` implementation. So `rfl` remains a macro and is still expanded to `eq_refl` (difference transparency setting) and `exact Iff.rfl` and `exact HEq.rfl` (implicit lambda) to not break existing code. This can be revised later, so this still closes: #3302. A user might still be puzzled *why* to terms are not defeq. Explaining that better (“reduced to… and reduces to… etc.”) would also be great, but that’s not specific to `rfl`, so better left for some other time.
I noticed (while #3299 passed by) that
rfl
produces a rather unhelpful error message:gives
This is not a good UX for a tactic that early users will be exposed to early (and also not great later on).
Looking at what happens I found that there are four different implementations registered (using
macro
/macro_rules
) forrfl
:Lean.MVarId.refl
, forEq
.HEq.rfl
Iff.rfl
@[refl]
lemma.Unfortunately, it seems that using
macro_rules
to extend tactics doesn’t give great control over which error message is shown if all fail.Assuming we want
@[refl]
in core, I propose that, after upstreamingStd.Tactic.Relation.Rfl
, we back therlf
tactic by a single function that combinesLean.MVarId.refl
andLean.MVarId.applyRfl
, possibly still with a special path forEq
(should that be needed, TBD), and with good error messages for the various failure modes.With a suitable
@[refl]
attribute, this should allow us to remove the extraexact ….rfl
macro rules.Community Feedback
This was escalated from a discussion on zulip.
Impact
Add 👍 to issues you consider important. If others benefit from the changes in this proposal being added, please ask them to add 👍 to it.
The text was updated successfully, but these errors were encountered: