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

[Merged by Bors] - fix(library/tactic): improve out_param support in simp #659

Closed
wants to merge 7 commits into from

Conversation

Vierkantor
Copy link
Collaborator

When a simp lemma matches with the goal, all remaining arguments, occurring as temporary metavariables, were inferred left-to-right by instantiate_emetas, stopping at the first metavariable that can't be inferred through matching with the goal, instance synthesis, or using the prover argument to simp. This meant a simp lemma with a parameter corresponding to the out_param of a typeclass will be rejected, unless that class occurs in the goal.

I modified instantiate_emetas to instead repeat until either all metavariables are inferred, or no progress is made on instantiating. I had to use a temporary type context to infer instances, in order to correctly unify the out_params with the temporary metavariables occurring earlier in the simp lemma. If I understand the comments about temporary type contexts correctly, this is the same as rw does, so this should not cause any regressions.

@gebner
Copy link
Member

gebner commented Jan 4, 2022

This certainly needs a ready-to-synthesize check, otherwise everything is treated as an out_param†:

class A (α β : Type) -- no out_param!
instance : A ℕ ℤ := ⟨⟩
def p (_ : Type) : Prop := false
@[simp] lemma l {α β} [A α β] : p α ↔ p β := iff.rfl
example : p ℕ := by simp --> p ℤ

† albeit with reducible transparency instead of semireducible, of course

Can you also mention where this turned up in mathlib? This will make it easier to sell as a Lean 4 change.

@ericrbg
Copy link
Contributor

ericrbg commented Jan 5, 2022

as far as I know, this patch was because lemmas like map_zero for fun_like+children don't fire as simp lemmas sometimes.

This ensures non-`out_param`s are not accidentally filled through unification
with the temporary metavariables. `out_param`s are still allowed to contain
metavariables that will be unified (see also #657).

I moved the `ready_to_synthesize` check from the elaborator to the type context
in order to access it from the simplifier.

Co-Authored-By: Gabriel Ebner <gebner@gebner.org>
tout() << "unable to assign instance for: " << mvar_type << "\n";);
failed = true;
tout() << "unable to synthesize instance for: " << mvar_type << "\n";);
done = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can do an early return here now. If it fails once, then it's not going to succeed in a future iteration (because of the ready-to-synthesize check). The same goes for the auto-param/discharging code below, if it fails we shouldn't try to fill in the other parameters. (I'm a bit concerned about performance here. Ideally we'd only try to synthesize each argument once, and fail immediately without futilely solving the rest if it doesn't succeed.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to retry the instances to avoid having cases like {α : Type*} [some_class_with_out_param α] [some_class_with_in_param α] work and {α : Type*} [some_class_with_in_param α] [some_class_with_out_param α] fail. As long as it's guarded by the metavariable check, I agree that this should work.

@Vierkantor
Copy link
Collaborator Author

Can you also mention where this turned up in mathlib? This will make it easier to sell as a Lean 4 change.

as far as I know, this patch was because lemmas like map_zero for fun_like+children don't fire as simp lemmas sometimes.

Indeed this was one of the cases, although this was mostly worked around as a side effect of adding the out_param to has_coe_to_fun: this made the goal contain enough of the instances that filling in the metavariables typically succeeds. This worked, as long as classes remained bundled.

For the linear_map_class I was working on, bundling is not possible (it would produce a dangerous instance) and the issue returned. I'm currently recompiling/fixing a branch of mathlib that should demonstrate a simp lemma newly picked up by this change.

@gebner
Copy link
Member

gebner commented Jan 5, 2022

LGTM. Thanks!

bors r+

bors bot pushed a commit that referenced this pull request Jan 5, 2022
When a `simp` lemma matches with the goal, all remaining arguments, occurring as temporary metavariables, were inferred left-to-right by `instantiate_emetas`, stopping at the first metavariable that can't be inferred through matching with the goal, instance synthesis, or using the prover argument to `simp`. This meant a `simp` lemma with a parameter corresponding to the `out_param` of a typeclass will be rejected, unless that class occurs in the goal.

I modified `instantiate_emetas` to instead repeat until either all metavariables are inferred, or no progress is made on instantiating. I had to use a temporary type context to infer instances, in order to correctly unify the `out_param`s with the temporary metavariables occurring earlier in the `simp` lemma. If I understand the comments about temporary type contexts correctly, this is the same as `rw` does, so this should not cause any regressions.
@bors
Copy link

bors bot commented Jan 5, 2022

@bors bors bot changed the title fix(library/tactic): improve out_param support in simp [Merged by Bors] - fix(library/tactic): improve out_param support in simp Jan 5, 2022
@bors bors bot closed this Jan 5, 2022
@bors bors bot deleted the simp_out_param branch January 5, 2022 13:40
bors bot pushed a commit to leanprover-community/mathlib that referenced this pull request May 16, 2022
This PR introduces morphism classes corresponding to `mul_action_hom`, `distrib_mul_action_hom`, `mul_semiring_action_hom` and `linear_map`.

Most of the new generic results work smoothly, only `simp` seems to have trouble applying `map_smulₛₗ`. I expect this requires another fix in the elaborator along the lines of [lean#659](leanprover-community/lean#659). For now we can just keep around the specialized `simp` lemmas `linear_map.map_smulₛₗ` and `linear_equiv.map_smulₛₗ`.

The other changes are either making `map_smul` protected where it conflicts, or helping the elaborator unfold some definitions that previously were helped by the specific `map_smul` lemma suggesting the type.

Thanks to @dupuisf for updating and making this branch compile!

Co-Authored-By: Frédéric Dupuis <dupuisf@iro.umontreal.ca>



Co-authored-by: Frédéric Dupuis <dupuisf@iro.umontreal.ca>
Co-authored-by: Anne Baanen <t.baanen@vu.nl>
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

Successfully merging this pull request may close these issues.

None yet

3 participants