Zulip Chat Archive

Stream: mathlib4

Topic: Bug in `simps`


Jakob von Raumer (Nov 20 2025 at 19:55):

We've found this bug which seems to appear if a structure has a structure-typed field the name of which is a prefix of another field.

import Mathlib

structure MyStruct where
  foo : Bool
  bar_b : Bool
  bar : Fin 5

@[simps]  -- Error Failed to find constructor b in structure Fin.
def set_foo (s : MyStruct) (val : Bool) : MyStruct :=
  { s with foo := val }

Has anyone seen this before?

cc @Yury G. Kudryashov

Edward van de Meent (Nov 20 2025 at 20:59):

that's a very weird bug, i haven't seen that before... let me add to it that if you move the field bar_b after bar, the error seems to disappear? (on live lean at least)

Jakob von Raumer (Nov 20 2025 at 21:00):

It also disappears if I name it bar_2 instead, it seems super cursed

Edward van de Meent (Nov 20 2025 at 21:00):

(btw, your error is inconsistent with the name of your field)

Edward van de Meent (Nov 20 2025 at 21:01):

(i.e. it should be bar_baz or Failed to find constructor b in structure Fin.. It seems you (accidentally?) edited it)

Edward van de Meent (Nov 20 2025 at 21:07):

a first guess as to why this happens: @[simps] generates lemmas and names them [def_name]_[projection_name]_[projection_name], and this specific naming causes there to be a clash

Jakob von Raumer (Nov 20 2025 at 21:08):

Edward van de Meent said:

(i.e. it should be bar_baz or Failed to find constructor b in structure Fin.. It seems you (accidentally?) edited it)

Ah, yes sorry, minimized it some more afterwards

Edward van de Meent (Nov 20 2025 at 21:09):

and then this clash :sparkles:somehow:sparkles: causes this weird error rather than failing gracefully

Edward van de Meent (Nov 20 2025 at 21:10):

Jakob von Raumer said:

Edward van de Meent said:

(i.e. it should be bar_baz or Failed to find constructor b in structure Fin.. It seems you (accidentally?) edited it)

Ah, yes sorry, minimized it some more afterwards

tbh i think bar_baz illustrates the correspondence between the error and the code more clearly...

Jovan Gerbscheid (Nov 21 2025 at 00:23):

I guess that simps is doing some really cursed name handling

Yury G. Kudryashov (Nov 21 2025 at 00:53):

Also, if we use a non-structure instead of Fin 5, then it panics.

Floris van Doorn (Nov 21 2025 at 11:37):

This is indeed a bug in simps.

I think the main problems here are that:
(1) the naming scheme is ambiguous in edge cases, e.g.

import Mathlib

structure Foo where
  b : Bool

structure MyStruct where
  foo : Bool
  bar_b : Bool
  bar : Foo

@[simps bar_b] -- which projection do you want here?
def set_foo (s : MyStruct) (val : Bool) : MyStruct :=
  [...]

(2) The internal representation simps used for what projection you want is just a string, and it assumes that this is unambiguous.
(3) There is not enough logic to catch all errors, causing it to fail ungracefully.

The weird behavior with numbers was a workaround added in #15095 when people ran into a similar issue.

(2) + (3) can be fixed, and I can add some logic that simps tries to use the longest matching projection. E.g. when you want projection bar_b_baz, and both bar and bar_b are projections of your current structure, then it will only consider bar_b, not bar. I could even add a rule to the parser that bar__b_baz will consider projection bar only.

Jovan Gerbscheid (Nov 21 2025 at 14:04):

Surely it would be much easier if we used the syntax @[simps bar.b] (where bar.b is parsed as an ident)?

Jakob von Raumer (Nov 22 2025 at 18:15):

In our a case, another workaround would also be a simps simps argument which restricts the "depth" to 1


Last updated: Dec 20 2025 at 21:32 UTC