Zulip Chat Archive

Stream: mathlib4

Topic: congr unexpectedly fails with Set.image


Terence Tao (Jul 07 2025 at 00:09):

For some reason congr cannot seem to reduce with Set.image:

import Mathlib

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  congr -- does nothing!
  exact h -- fails due to inability of congr to reduce

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : @Set.image X Y f E = @Set.image X Y f F := by
  congr -- does nothing!
  exact h -- fails due to inability of congr to reduce

Is this a bug? convert rfl works, though it manages to somehow reverse the equality:

import Mathlib

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  convert rfl  -- works, though with equality reversed
  exact h.symm

Also, congr! closes the goal completely.

Kyle Miller (Jul 07 2025 at 00:24):

It's likely a bug — I wrote congr! to be a replacement of congr, and the eventual plan is to improve the core congr.

Kyle Miller (Jul 07 2025 at 00:25):

Here are a few more approaches to congruence here (these all use the same underlying system):

import Mathlib

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F :=
  congr(f '' $h)

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  refine congr(f '' $(?_))
  exact h

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  congrm f '' ?_
  exact h

Terence Tao (Jul 07 2025 at 00:26):

Yeah, everything other than vanilla congr seems to work just fine here

Kyle Miller (Jul 07 2025 at 00:28):

Terence Tao said:

convert rfl works

That's amusing that it reverses the equality... I'm not sure exactly why that is, but I imagine it has something to do with unification order (you can see hints of it with convert rfl using 0).

The convert tactic is a frontend for congr!, so it makes sense that it works here.

Kyle Miller (Jul 07 2025 at 00:29):

I believe the underlying bug is that congr miscalculates the arity of Set.image. The arity is 4, and it's given four arguments, but it's unfolding Set and seeing it as having arity 5.

(This affects simp too, but there are some other features that paper over the issue, so long as functions involved don't have some complicated dependent types.)

Terence Tao (Jul 07 2025 at 00:31):

congr also fails to work with the other argument of Set.image, which seems consistent with your diagnosis:

example {X Y:Type} (f g: X  Y) (E: Set X) (h: f = g) : f '' E = g '' E := by
  congr -- does nothing!
  exact h -- fails due to inability of congr to reduce

Kyle Miller (Jul 07 2025 at 00:34):

At some point I fixed the corresponding bug in conv mode's arg/enter/congr tactics

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  conv =>
    enter [1,2]
    rw [h]

example {X Y:Type} (f: X  Y) (E F: Set X) (h: E = F) : f '' E = f '' F := by
  conv =>
    congr
    congr
    rfl
    rw [h]

It's not the same congr, so it didn't fix the main tactic mode congr

Terence Tao (Jul 07 2025 at 00:35):

ok so hopefully it is just a matter of porting some previous bugfix to the congr code?

Kyle Miller (Jul 07 2025 at 00:35):

(Or it was another bug I fixed, but in any case conv mode works!)

Kyle Miller (Jul 07 2025 at 00:37):

They work pretty differently, so it's not going to be a bugfix port, but the principle is similar. I'd suggest using congr! for now, unless you have a reason not to.

Kyle Miller (Jul 07 2025 at 00:40):

I think there's a good chance that there will be some attention on improving congr this summer.

Kyle Miller (Jul 07 2025 at 01:13):

lean4#9225 has a fix, though it likely will need a number of mathlib adaptations

Kevin Buzzard (Jul 07 2025 at 09:08):

Note also #25889 which fixes issues with conv? miscounting.

Kyle Miller (Jul 23 2025 at 18:40):

(Looking through some old issues, I was just reminded of the fact that I reported this issue with congr and Set.image back in #lean4 > mkCongrSimp? error for Set @ 💬! Happy to see it's resolved.)


Last updated: Dec 20 2025 at 21:32 UTC