This PR changes how fields are elaborated in the `structure`/`class` commands and also makes default values respect the structure resolution order when there is diamond inheritance. Before, the details of subobjects were exposed during elaboration, and in the local context any fields that came from a subobject were defined to be projections of the subobject field. Now, every field is represented as a local variable. All parents (not just subobject parents) are now represented in the local context, and they are now local variables defined to be parent constructors applied to field variables (inverting the previous relationship). Other notes: - The entire collection of parents is processed, and all parent projection names are checked for consistency. Every parent appears in the local context now. - For classes, every parent now contributes an instance, not just the parents represented as subobjects. - Default values are now processed according to the parent resolution order. Default value definition/override auxiliary definitions are stored at `StructName.fieldName._default`, and inherited values are stored at `StructName.fieldName._inherited_default`. Metaprograms no longer need to look at parents when doing calculations on default values. - Default value omission for structure instance notation pretty printing has been updated in consideration of this. - Now the elaborator generates a `_flat_ctor` constructor that will be used for structure instance elaboration. All types in this constructor are put in "field normal form" (projections of parent constructors are reduced, and parent constructors are eta reduced), and all fields with autoParams are annotated as such. This is not meant for users, but it may be useful for metaprogramming. - While elaborating fields, any metavariables whose type is one of the parents is assigned to that parent. The hypothesis is that, for the purpose of elaborating structure fields, parents are fixed: there is only *one* instance of any given parent under consideration. See the `Magma` test for an example of this being necessary. The hypothesis may not be true when there are recursive structures, since different values of the structure might not agree on parent fields. Other notes: - The elaborator has been refactored, and it now uses a monad to keep track of the elaboration state. - This PR was motivation for #7100, since we need to be able to make all parents have consistent projection names when there is diamond inheritance. Still to do: - Handle autoParams like we do default values. Inheritance for these is not correct when there is diamond inheritance. - Avoid splitting apart parents if the overlap is only on proof fields. - Non-subobject parent projections do not have parameter binder kinds that are consistent with other projections (i.e., all implicit by default, no inst implicits). This needs to wait on adjustments to the synthOrder algorithm. - We could elide parents with no fields, letting their projections be constant functions. This causes some trouble for defeq checking however (maybe #2258 would address this).
215 lines
4.3 KiB
Text
215 lines
4.3 KiB
Text
/-!
|
||
# Delaborating structure instances
|
||
-/
|
||
|
||
structure A where
|
||
x : Nat
|
||
|
||
/-!
|
||
Basic example
|
||
-/
|
||
/-- info: { x := 1 } : A -/
|
||
#guard_msgs in #check { x := 1 : A }
|
||
|
||
/-!
|
||
pp.all
|
||
-/
|
||
set_option pp.all true in
|
||
/-- info: A.mk (@OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)) : A -/
|
||
#guard_msgs in #check { x := 1 : A }
|
||
|
||
structure B extends A where
|
||
y : Nat
|
||
|
||
/-!
|
||
Check flattening of parent structures.
|
||
-/
|
||
|
||
/-- info: { x := 1 } : A -/
|
||
#guard_msgs in #check {x := 1 : A}
|
||
|
||
/-- info: { x := 1, y := 2 } : B -/
|
||
#guard_msgs in #check {x := 1, y := 2 : B}
|
||
|
||
/-!
|
||
No flattening of parent structures
|
||
-/
|
||
section
|
||
set_option pp.structureInstances.flatten false
|
||
|
||
/-- info: { x := 1 } : A -/
|
||
#guard_msgs in #check {x := 1 : A}
|
||
|
||
/-- info: { toA := { x := 1 }, y := 2 } : B -/
|
||
#guard_msgs in #check {x := 1, y := 2 : B}
|
||
end
|
||
|
||
/-!
|
||
Not a true parent structure, so no flattening.
|
||
-/
|
||
|
||
structure B' where
|
||
toA : A
|
||
y : Nat
|
||
|
||
/-- info: { toA := { x := 1 }, y := 2 } : B' -/
|
||
#guard_msgs in #check {toA := {x := 1}, y := 2 : B'}
|
||
|
||
/-!
|
||
Check that this handles parameters.
|
||
-/
|
||
structure C (n : Nat) where
|
||
x : Fin n
|
||
|
||
structure D (n : Nat) extends C n where
|
||
y : Nat
|
||
|
||
/-- info: { x := 1, y := 2 } : D 3 -/
|
||
#guard_msgs in #check {x := 1, y := 2 : D 3}
|
||
|
||
/-!
|
||
Show type
|
||
-/
|
||
set_option pp.structureInstanceTypes true in
|
||
/-- info: { x := 0 : A } : A -/
|
||
#guard_msgs in #check { x := 0 : A }
|
||
|
||
/-!
|
||
Omit default values
|
||
-/
|
||
|
||
/-- info: { } : Lean.Meta.Simp.Config -/
|
||
#guard_msgs in #check { : Lean.Meta.Simp.Config }
|
||
|
||
structure E where
|
||
n : Nat := 0
|
||
|
||
/-- info: { } : E -/
|
||
#guard_msgs in #check { : E }
|
||
|
||
/-- info: { n := 1 } : E -/
|
||
#guard_msgs in #check { n := 1 : E }
|
||
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { n := 0 } : E -/
|
||
#guard_msgs in #check { : E }
|
||
|
||
structure F extends E where
|
||
m : Nat := 1
|
||
|
||
/-- info: { } : F -/
|
||
#guard_msgs in #check { : F }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { n := 0, m := 1 } : F -/
|
||
#guard_msgs in #check { : F }
|
||
/-- info: { n := 1 } : F -/
|
||
#guard_msgs in #check { n := 1 : F }
|
||
/-- info: { m := 2 } : F -/
|
||
#guard_msgs in #check { m := 2 : F }
|
||
|
||
/-!
|
||
Omit default values, with parameter handling
|
||
-/
|
||
|
||
structure G (n : Nat) where
|
||
m := n
|
||
|
||
/-- info: { } : G 3 -/
|
||
#guard_msgs in #check { : G 3 }
|
||
/-- info: { m := 2 } : G 3 -/
|
||
#guard_msgs in #check { m := 2 : G 3 }
|
||
|
||
|
||
/-!
|
||
Explicit mode turns off structure instance notation iff there are parameters
|
||
-/
|
||
|
||
set_option pp.explicit true in
|
||
/-- info: { } : E -/
|
||
#guard_msgs in #check { : E }
|
||
|
||
set_option pp.explicit true in
|
||
/--
|
||
info: @G.mk (@OfNat.ofNat Nat 3 (instOfNatNat 3))
|
||
(@OfNat.ofNat Nat 3 (instOfNatNat 3)) : G (@OfNat.ofNat Nat 3 (instOfNatNat 3))
|
||
-/
|
||
#guard_msgs in #check { : G 3 }
|
||
|
||
/-!
|
||
If universe levels need to be shown, structure instance notation is turned off
|
||
-/
|
||
|
||
structure U (α : Type _) where
|
||
x : α
|
||
|
||
/-- info: { x := 1 } : U Nat -/
|
||
#guard_msgs in #check { x := 1 : U Nat }
|
||
|
||
set_option pp.universes true in
|
||
/-- info: U.mk.{0} 1 : U.{0} Nat -/
|
||
#guard_msgs in #check { x := 1 : U Nat }
|
||
|
||
/-!
|
||
Dependence of default value
|
||
-/
|
||
structure H where
|
||
x : Nat
|
||
y : Nat := x
|
||
|
||
/-- info: { x := 1 } : H -/
|
||
#guard_msgs in #check { x := 1 : H }
|
||
|
||
/-!
|
||
Diamond inheritance
|
||
-/
|
||
structure D1 where
|
||
x := 1
|
||
structure D2 extends D1 where
|
||
structure D3 extends D1 where
|
||
x := 3
|
||
structure D4 extends D2, D3
|
||
|
||
/-- info: { } : D1 -/
|
||
#guard_msgs in #check { : D1 }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { x := 1 } : D1 -/
|
||
#guard_msgs in #check { : D1 }
|
||
|
||
/-- info: { } : D2 -/
|
||
#guard_msgs in #check { : D2 }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { x := 1 } : D2 -/
|
||
#guard_msgs in #check { : D2 }
|
||
|
||
/-- info: { } : D3 -/
|
||
#guard_msgs in #check { : D3 }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { x := 3 } : D3 -/
|
||
#guard_msgs in #check { : D3 }
|
||
|
||
/-- info: { } : D4 -/
|
||
#guard_msgs in #check { : D4 }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { x := 3 } : D4 -/
|
||
#guard_msgs in #check { : D4 }
|
||
|
||
/-!
|
||
Inheritance with parameters
|
||
-/
|
||
namespace Test1
|
||
|
||
structure A (α : Type) [Inhabited α] where
|
||
x : α := default
|
||
structure B (β : Type) [Inhabited β] extends A β where
|
||
|
||
/-- info: { } : B Nat -/
|
||
#guard_msgs in #check { : B Nat }
|
||
set_option pp.structureInstances.defaults true in
|
||
/-- info: { x := default } : B Nat -/
|
||
#guard_msgs in #check { : B Nat }
|
||
|
||
-- Only reducible defeq, so the `x` fields is still included:
|
||
/-- info: { x := 0 } : B Nat -/
|
||
#guard_msgs in #check { x := 0 : B Nat }
|
||
|
||
end Test1
|