lean4-htt/tests/lean/run/mathlibetaissue.lean
Kyle Miller 3f98f6bc07
feat: structure instance notation elaboration improvements (#7717)
This PR changes how `{...}`/`where` notation ("structure instance
notation") elaborates. The notation now tries to simulate a flat
representation as much as possible, without exposing the details of
subobjects. Features:
- When fields are elaborated, their expected types now have a couple
reductions applied. For all projections and constructors associated to
the structure and its parents, projections of constructors are reduced
and constructors of projections are eta reduced, and also implementation
detail local variables are zeta reduced in propositions (so tactic
proofs should never see them anymore). Furthermore, field values are
beta reduced automatically in successive field types. The example in
[mathlib4#12129](https://github.com/leanprover-community/mathlib4/issues/12129#issuecomment-2056134533)
now shows a goal of `0 = 0` rather than `{ toFun := fun x => x }.toFun 0
= 0`.
- All parents can now be used as field names, not just the subobject
parents. These are like additional sources but with three constraints:
every field of the value must be used, the fields must not overlap with
other provided fields, and every field of the specified parent must be
provided for. Similar to sources, the values are hoisted to `let`s if
they are not already variables, to avoid multiple evaluation. They are
implementation detail local variables, so they get unfolded for
successive fields.
- All class parents are now used to fill in missing fields, not just the
subobject parents. Closes #6046. Rules: (1) only those parents whose
fields are a subset of the remaining fields are considered, (2) parents
are considered only before any fields are elaborated, and (3) only those
parents whose type can be computed are considered (this can happen if a
parent depends on another parent, which is possible since #7302).
- Default values and autoparams now respect the resolution order
completely: each field has at most one default value definition that can
provide for it. The algorithm that tries to unstick default values by
walking up the subobject hierarchy has been removed. If there are
applications of default value priorities, we might consider it in a
future release.
- The resulting constructors are now fully packed. This is implemented
by doing structure eta reduction of the elaborated expressions.
- "Magic field definitions" (as reported [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/Where.20is.20sSup.20defined.20on.20submodules.3F/near/499578795))
have been eliminated. This was where fields were being solved for by
unification, tricking the default value system into thinking they had
actually been provided. Now the default value system keeps track of
which fields it has actually solved for, and which fields the user did
not provide. Explicit structure fields (the default kind) without any
explicit value definition will result in an error. If it was solved for
by unification, the error message will include the inferred value, like
"field 'f' must be explicitly provided, its synthesized value is v"
- When the notation is used in patterns, it now no longer inserts fields
using class parents, and it no longer applies autoparams or default
values. The motivation is that one expects patterns to match only the
given fields. This is still imperfect, since fields might be solved for
indirectly.
- Elaboration now attempts error recovery. Extraneous fields log errors
and are ignored, missing fields are filled with `sorry`.

This is a breaking change, but generally the mitigation is to remove
`dsimp only` from the beginnings of proofs. Sometimes "magic fields"
need to be provided — four possible mitigations are (1) to provide the
field, (2) to provide `_` for the value of the field, (3) to add `..` to
the structure instance notation, (4) or decide to modify the `structure`
command to make the field implicit. Lastly, sometimes parent instances
don't apply when they should. This could be because some of the provided
fields overlap with the class, or it could be that the parent depends on
some of the fields for synthesis — and as parents are only considered
before any fields are elaborated, such parents might not be possible to
use — we will look into refining this further.

There is also a change to elaboration: now the `afterTypeChecking`
attributes are run with all `structure` data set up (e.g. the list of
parents, along with all parent projections in the environment). This is
necessary since attributes like `@[ext]` use structure instance
notation, and the notation needs all this data to be set up now.
2025-03-30 17:40:36 +00:00

167 lines
5.6 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-!
# An etaExperiment timeout
The purpose of this file is to demonstrate a typeclass search that
* times out with `etaExperiment`
* is fast on `lean-toolchain` `gebner/lean4:reenableeta230506`
* is realistic, i.e. is a minimisation of something appearing in mathlib.
I've taken the example Matthew Ballard showed me:
```
import Mathlib
#synth Zero
```
and minimised it.
I've used `sorry` liberally,
but not changed the typeclass inheritance structure at all relative to mathlib4.
(It could probably be minimized further, but I think this is not the point?)
This file is minimised in the sense that:
* removing any command should either cause a new error, or remove the timeout.
* removing any field of a structure, and sorrying a field of an instance, should do the same.
Section titles correspond to the files the material came from the mathlib4/std4.
-/
section Std.Classes.Cast
class NatCast2 (R : Type u) where
class IntCast2 (R : Type u) where
end Std.Classes.Cast
section Std.Data.Int.Lemmas
end Std.Data.Int.Lemmas
section Std.Classes.RatCast
class RatCast (K : Type u) where
end Std.Classes.RatCast
section Mathlib.Init.ZeroOne
class One (α : Type u) where
one : α
instance One.toOfNat1 {α} [One α] : OfNat α (nat_lit 1) where
ofNat := One α.1
end Mathlib.Init.ZeroOne
section Mathlib.Algebra.Group.Defs
class Inv (α : Type u) where
class Semigroup (G : Type u) extends Mul G where
class AddSemigroup (G : Type u) extends Add G where
class CommSemigroup (G : Type u) extends Semigroup G where
mul_comm : ∀ a b : G, a * b = b * a
class AddCommSemigroup (G : Type u) extends AddSemigroup G where
class MulOneClass (M : Type u) extends One M, Mul M where
mul_one : ∀ a : M, a * 1 = a
class AddZeroClass (M : Type u) extends Zero M, Add M where
add_zero : ∀ a : M, a + 0 = a
class AddMonoid (M : Type u) extends AddSemigroup M, AddZeroClass M where
class Monoid (M : Type u) extends Semigroup M, MulOneClass M where
class AddCommMonoid (M : Type u) extends AddMonoid M, AddCommSemigroup M
class CommMonoid (M : Type u) extends Monoid M, CommSemigroup M
class DivInvMonoid (G : Type u) extends Monoid G, Inv G, Div G where
class SubNegMonoid (G : Type u) extends AddMonoid G, Neg G, Sub G where
class Group (G : Type u) extends DivInvMonoid G where
class AddGroup (A : Type u) extends SubNegMonoid A where
class AddCommGroup (G : Type u) extends AddGroup G, AddCommMonoid G
end Mathlib.Algebra.Group.Defs
section Mathlib.Logic.Nontrivial
class Nontrivial (α : Type _) : Prop where
end Mathlib.Logic.Nontrivial
section Mathlib.Algebra.GroupWithZero.Defs
class MulZeroClass (M₀ : Type u) extends Mul M₀, Zero M₀ where
class IsLeftCancelMulZero (M₀ : Type u) [Mul M₀] [Zero M₀] : Prop where
class IsRightCancelMulZero (M₀ : Type u) [Mul M₀] [Zero M₀] : Prop where
class IsCancelMulZero (M₀ : Type u) [Mul M₀] [Zero M₀] : Prop
extends IsLeftCancelMulZero M₀, IsRightCancelMulZero M₀
class NoZeroDivisors (M₀ : Type _) [Mul M₀] [Zero M₀] : Prop where
class SemigroupWithZero (S₀ : Type u) extends Semigroup S₀, MulZeroClass S₀
class MulZeroOneClass (M₀ : Type u) extends MulOneClass M₀, MulZeroClass M₀
class MonoidWithZero (M₀ : Type u) extends Monoid M₀, MulZeroOneClass M₀, SemigroupWithZero M₀
class CommMonoidWithZero (M₀ : Type _) extends CommMonoid M₀, MonoidWithZero M₀
class CancelCommMonoidWithZero (M₀ : Type _) extends CommMonoidWithZero M₀, IsLeftCancelMulZero M₀
end Mathlib.Algebra.GroupWithZero.Defs
section Mathlib.Data.Nat.Cast.Defs
class AddMonoidWithOne (R : Type u) extends NatCast2 R, AddMonoid R, One R where
class AddCommMonoidWithOne (R : Type _) extends AddMonoidWithOne R, AddCommMonoid R
end Mathlib.Data.Nat.Cast.Defs
section Mathlib.Data.Int.Cast.Defs
class AddGroupWithOne (R : Type u) extends IntCast2 R, AddMonoidWithOne R, AddGroup R where
end Mathlib.Data.Int.Cast.Defs
section Mathlib.Algebra.Ring.Defs
class NonUnitalNonAssocSemiring (α : Type u) extends AddCommMonoid α, MulZeroClass α
class NonUnitalSemiring (α : Type u) extends NonUnitalNonAssocSemiring α, SemigroupWithZero α
class NonAssocSemiring (α : Type u) extends NonUnitalNonAssocSemiring α, MulZeroOneClass α,
AddCommMonoidWithOne α
class Semiring (α : Type u) extends NonUnitalSemiring α, NonAssocSemiring α, MonoidWithZero α
class Ring (R : Type u) extends Semiring R, AddCommGroup R, AddGroupWithOne R
class CommSemiring (R : Type u) extends Semiring R, CommMonoid R
class CommRing (α : Type u) extends Ring α, CommMonoid α
instance CommRing.toCommSemiring [s : CommRing α] : CommSemiring α :=
{ s with }
class IsDomain (α : Type u) [Semiring α] : Prop extends IsCancelMulZero α, Nontrivial α
end Mathlib.Algebra.Ring.Defs
section Mathlib.Data.Int.Basic
instance : CommRing Int where
one := 1
mul_comm := sorry
mul_one := Int.mul_one -- Replacing this with `sorry` makes the timeout go away!
add_zero := Int.add_zero -- Similarly here.
end Mathlib.Data.Int.Basic
section Mathlib.Algebra.Ring.Regular
section IsDomain
instance IsDomain.toCancelCommMonoidWithZero [CommSemiring α] [IsDomain α] :
CancelCommMonoidWithZero α := { }
end IsDomain
end Mathlib.Algebra.Ring.Regular
section Mathlib.Algebra.Field.Defs
class DivisionRing (K : Type u) extends Ring K, DivInvMonoid K, Nontrivial K, RatCast K where
class Field (K : Type u) extends CommRing K, DivisionRing K
end Mathlib.Algebra.Field.Defs
section Mathlib.Algebra.Field.Basic
instance Field.isDomain [Field K] : IsDomain K :=
sorry
end Mathlib.Algebra.Field.Basic
set_option synthInstance.maxHeartbeats 200 in
/-- info: MulZeroClass.toZero -/
#guard_msgs in
#synth Zero Int