Zulip Chat Archive
Stream: lean4
Topic: possible linter bugs
Kevin Buzzard (Dec 15 2022 at 15:51):
Do questions about Std4 (or about linters) go in this stream?
I don't know much about linters but both of these surprised me. Are these bugs or is there something wrong with my structure?
import Std.Tactic.Lint
universe u v
structure MulOpposite (α : Type u) : Type u where
op :: unop : α
postfix:max "ᵐᵒᵖ" => MulOpposite
namespace MulOpposite
@[simp]
theorem unop_op (x : α) : unop (op x) = x :=
rfl
@[simp]
theorem unop_inj {x y : αᵐᵒᵖ} : unop x = unop y ↔ x = y := by
cases x; cases y; simp
#lint
/- The `simpComm` linter reports:
COMMUTATIVITY LEMMA IS SIMP.
Some commutativity lemmas are simp lemmas: -/
#check @unop_inj /- should not be marked simp -/
/- The `simpVarHead` linter reports:
LEFT-HAND SIDE HAS VARIABLE AS HEAD SYMBOL.
Some simp lemmas have a variable as head symbol of the left-hand side (after whnfR): -/
#check @unop_op /- Left-hand side has variable as head symbol: x -/
Kevin Buzzard (Dec 15 2022 at 15:53):
wooah
theorem unop_op (x : α) : unop (op x) = x :=
by simp only
What black magic is this? That would never work in Lean 3.
Mario Carneiro (Dec 15 2022 at 16:38):
Kevin Buzzard said:
Do questions about Std4 (or about linters) go in this stream?
There is a #std4 stream
Mario Carneiro (Dec 15 2022 at 16:43):
These could be bugs in the linters. Simp recently changed its discrimination tree index to unfold less stuff like this, although if the simp only
example is any indication then this is still happening in this case
Reid Barton (Dec 15 2022 at 16:44):
Isn't this just iota reduction? I thought simp only
does this by default?
Mario Carneiro (Dec 15 2022 at 16:52):
no, that was what was disabled
Mario Carneiro (Dec 15 2022 at 16:53):
well, simp only
does iota reduction, it just doesn't pattern match modulo iota reduction any more
Mario Carneiro (Dec 15 2022 at 16:54):
so actually yes that explains why simp only
closes the goal, and the linter is still possibly faulty
Eric Wieser (Dec 15 2022 at 23:12):
Kevin Buzzard said:
wooah
theorem unop_op (x : α) : unop (op x) = x := by simp only
What black magic is this? That would never work in Lean 3.
This only happens in Lean3 on days ending in y
-- lean3 code but I'm too lazy to use lean3 names
structure {u} MulOpposite (α : Type u) : Type u :=
op :: (unop : α)
namespace MulOpposite
theorem unop_op {α} (x : α) : unop (op x) = x := by simp only
end MulOpposite
Kevin Buzzard (Dec 16 2022 at 00:04):
So why doesn't the simp linter complain in lean 3 when this gets tagged simp
?
Eric Wieser (Dec 16 2022 at 00:25):
It only does that on days with an a
in:
import tactic.lint
@[nolint doc_blame nolint has_nonempty_instance]
structure {u} MulOpposite (α : Type u) : Type u := op :: (unop : α)
namespace MulOpposite
@[simp] theorem unop_op {α} (x : α) : unop (op x) = x := by simp only
end MulOpposite
#lint -- fails
Eric Wieser (Dec 16 2022 at 00:28):
I think your real question is "why does this not happen on docs#mul_opposite in Lean 3?", to which the answer is "because mul_opposite
is not a structure".
Kevin Buzzard (Dec 16 2022 at 10:18):
Thanks! So the conclusion is simply that unop_op
should not be tagged with simp
in mathlib4 if MulOpposite
is a structure, which resolves the simpVarHead
question (in some sense at least). The unop_inj
/ simpComm
question remains open. Shall I open an issue on Std
for that one?
Eric Wieser (Dec 16 2022 at 10:19):
Yes, the unop_inj
remains mysterious to me; but I'd make sure to really check it is accepted by Lean 3 before reporting it!
Kevin Buzzard (Dec 16 2022 at 10:19):
Do we have that linter in Lean 3?? I'd never heard of it before I saw that error in the file I was porting.
Eric Wieser (Dec 16 2022 at 10:20):
I thought we had something similar in the simp
attribute itself
Kevin Buzzard (Dec 16 2022 at 21:32):
More Lean 4 declarations rejected by simpComm
:
@[simp, to_additive]
theorem semiconj_by_unop [Mul α] {a x y : αᵐᵒᵖ} :
SemiconjBy (unop a) (unop y) (unop x) ↔ SemiconjBy a x y :=
and
theorem commute_unop [Mul α] {x y : αᵐᵒᵖ} : Commute (unop x) (unop y) ↔ Commute x y :=
semiconj_by_unop
Kevin Buzzard (Dec 16 2022 at 21:38):
And indeed in Lean 3 there is no objection to unop_inj
.
import tactic.lint.default
-- lean3 code but I'm too lazy to use lean3 names
structure {u} MulOpposite (α : Type u) : Type u :=
op :: (unop : α)
namespace MulOpposite
variable (α : Type*)
@[simp]
theorem unop_inj {x y : MulOpposite α} : unop x = unop y ↔ x = y := by
cases x; cases y; simp
end MulOpposite
#lint -- no objection
This is holding up mathlib4#1036 which is needed to make some opposite-related files less painful to port. How should I proceed? At the minute we're just working around this, but given that these opposite types should be structures (because we can't use the trick of making them irreducible later on in Lean 4), probably the sooner they're turned into structures the better.
Last updated: Dec 20 2023 at 11:08 UTC