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.
This commit is contained in:
parent
176e8bc077
commit
3f98f6bc07
39 changed files with 1595 additions and 1114 deletions
|
|
@ -488,7 +488,7 @@ instance instCCPOPProd [CCPO α] [CCPO β] : CCPO (α ×' β) where
|
|||
csup c := ⟨CCPO.csup (PProd.chain.fst c), CCPO.csup (PProd.chain.snd c)⟩
|
||||
csup_spec := by
|
||||
intro ⟨a, b⟩ c hchain
|
||||
dsimp
|
||||
try dsimp -- TODO(kmill) remove
|
||||
constructor
|
||||
next =>
|
||||
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
|
||||
|
|
|
|||
|
|
@ -121,6 +121,12 @@ structure ElabHeaderResult extends PreElabHeaderResult where
|
|||
indFVar : Expr
|
||||
deriving Inhabited
|
||||
|
||||
/-- An intermediate step for mutual inductive elaboration. See `InductiveElabDescr` -/
|
||||
structure InductiveElabStep3 where
|
||||
/-- Finalize the inductive type, after they are all added to the environment, after auxiliary definitions are added, and after computed fields are registered.
|
||||
The `levelParams`, `params`, and `replaceIndFVars` arguments of `prefinalize` are still valid here. -/
|
||||
finalize : TermElabM Unit := pure ()
|
||||
|
||||
/-- An intermediate step for mutual inductive elaboration. See `InductiveElabDescr`. -/
|
||||
structure InductiveElabStep2 where
|
||||
/-- The constructors produced by `InductiveElabStep1`. -/
|
||||
|
|
@ -133,9 +139,7 @@ structure InductiveElabStep2 where
|
|||
/-- Step to finalize term elaboration, done immediately after universe level processing is complete. -/
|
||||
finalizeTermElab : TermElabM Unit := pure ()
|
||||
/-- Like `finalize`, but occurs before `afterTypeChecking` attributes. -/
|
||||
prefinalize (levelParams : List Name) (params : Array Expr) (replaceIndFVars : Expr → MetaM Expr) : TermElabM Unit := fun _ _ _ => pure ()
|
||||
/-- Finalize the inductive type, after they are all added to the environment, after auxiliary definitions are added, and after computed fields are registered. -/
|
||||
finalize (levelParams : List Name) (params : Array Expr) (replaceIndFVars : Expr → MetaM Expr) : TermElabM Unit := fun _ _ _ => pure ()
|
||||
prefinalize (levelParams : List Name) (params : Array Expr) (replaceIndFVars : Expr → MetaM Expr) : TermElabM InductiveElabStep3 := fun _ _ _ => pure {}
|
||||
deriving Inhabited
|
||||
|
||||
/-- An intermediate step for mutual inductive elaboration. See `InductiveElabDescr`. -/
|
||||
|
|
@ -160,7 +164,7 @@ Elaboration occurs in the following steps:
|
|||
- Elaboration of constructors is finalized, with additional tasks done by each `InductiveStep2.collectUniverses`.
|
||||
- The inductive family is added to the environment and is checked by the kernel.
|
||||
- Attributes and other finalization activities are performed, including those defined
|
||||
by `InductiveStep2.prefinalize` and `InductiveStep2.finalize`.
|
||||
by `InductiveStep2.prefinalize` and `InductiveStep3.finalize`.
|
||||
-/
|
||||
structure InductiveElabDescr where
|
||||
mkInductiveView : Modifiers → Syntax → TermElabM InductiveElabStep1
|
||||
|
|
@ -1048,9 +1052,9 @@ private def elabInductiveViewsPostprocessing (views : Array InductiveView) (res
|
|||
let ref := view0.ref
|
||||
applyComputedFields views -- NOTE: any generated code before this line is invalid
|
||||
liftTermElabM <| withMCtx res.mctx <| withLCtx res.lctx res.localInsts do
|
||||
for elab' in res.elabs do elab'.prefinalize res.levelParams res.params res.replaceIndFVars
|
||||
let finalizers ← res.elabs.mapM fun elab' => elab'.prefinalize res.levelParams res.params res.replaceIndFVars
|
||||
for view in views do withRef view.declId <| Term.applyAttributesAt view.declName view.modifiers.attrs .afterTypeChecking
|
||||
for elab' in res.elabs do elab'.finalize res.levelParams res.params res.replaceIndFVars
|
||||
for elab' in finalizers do elab'.finalize
|
||||
applyDerivingHandlers views
|
||||
runTermElabM fun _ => Term.withDeclName view0.declName do withRef ref do
|
||||
for view in views do withRef view.declId <| Term.applyAttributesAt view.declName view.modifiers.attrs .afterCompilation
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ private partial def getFieldOrigin (structName field : Name) : MetaM StructureFi
|
|||
return fi
|
||||
|
||||
open Meta in
|
||||
private partial def printStructure (id : Name) (levelParams : List Name) (numParams : Nat) (type : Expr)
|
||||
private partial def printStructure (id : Name) (levelParams : List Name) (numParams : Nat) (type : Expr) (ctor : Name)
|
||||
(isUnsafe : Bool) : CommandElabM Unit := do
|
||||
let env ← getEnv
|
||||
let kind := if isClass env id then "class" else "structure"
|
||||
|
|
@ -107,8 +107,9 @@ private partial def printStructure (id : Name) (levelParams : List Name) (numPar
|
|||
let paramMap : NameMap Expr ← params.foldlM (init := {}) fun paramMap param => do
|
||||
pure <| paramMap.insert (← param.fvarId!.getUserName) param
|
||||
-- Collect autoParam tactics, which are all on the flat constructor:
|
||||
let flatCtorName := mkFlatCtorOfStructName id
|
||||
let autoParams : NameMap Syntax ← forallTelescope (← getConstInfo flatCtorName).type fun args _ =>
|
||||
let flatCtorName := mkFlatCtorOfStructCtorName ctor
|
||||
let flatCtorInfo ← try getConstInfo flatCtorName catch _ => getConstInfo (id ++ `_flat_ctor) -- TODO(kmill): remove catch
|
||||
let autoParams : NameMap Syntax ← forallTelescope flatCtorInfo.type fun args _ =>
|
||||
args[numParams:].foldlM (init := {}) fun set arg => do
|
||||
let decl ← arg.fvarId!.getDecl
|
||||
if let some (.const tacticDecl _) := decl.type.getAutoParamTactic? then
|
||||
|
|
@ -187,7 +188,7 @@ private def printIdCore (id : Name) : CommandElabM Unit := do
|
|||
| ConstantInfo.recInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "recursor" id us t u
|
||||
| ConstantInfo.inductInfo { levelParams := us, numParams, type := t, ctors, isUnsafe := u, .. } =>
|
||||
if isStructure env id then
|
||||
printStructure id us numParams t u
|
||||
printStructure id us numParams t ctors[0]! u
|
||||
else
|
||||
printInduct id us numParams t ctors u
|
||||
| none => throwUnknownId id
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -510,46 +510,6 @@ private def reduceFieldProjs (e : Expr) (zetaDelta := true) : StructElabM Expr :
|
|||
return TransformStep.continue
|
||||
Meta.transform e (post := postVisit)
|
||||
|
||||
/-- Checks if the expression is of the form `S.mk x.1 ... x.n` with `n` nonzero
|
||||
and `S.mk` a structure constructor with `S` one of the recorded structure parents.
|
||||
Returns `x`.
|
||||
Each projection `x.i` can be either a native projection or from a projection function. -/
|
||||
private def etaStruct? (e : Expr) : StructElabM (Option Expr) := do
|
||||
let .const f _ := e.getAppFn | return none
|
||||
let some (ConstantInfo.ctorInfo fVal) := (← getEnv).find? f | return none
|
||||
unless (← findParentFieldInfo? fVal.induct).isSome do return none
|
||||
unless 0 < fVal.numFields && e.getAppNumArgs == fVal.numParams + fVal.numFields do return none
|
||||
let args := e.getAppArgs
|
||||
let some (S0, i0, x) ← getProjectedExpr args[fVal.numParams]! | return none
|
||||
unless S0 == fVal.induct && i0 == 0 do return none
|
||||
for i in [1 : fVal.numFields] do
|
||||
let arg := args[fVal.numParams + i]!
|
||||
let some (S', i', x') ← getProjectedExpr arg | return none
|
||||
unless S' == fVal.induct && i' == i && x' == x do return none
|
||||
return x
|
||||
where
|
||||
/-- Given an expression that's either a native projection or a registered projection
|
||||
function, gives (1) the name of the structure type, (2) the index of the projection, and
|
||||
(3) the object being projected. -/
|
||||
getProjectedExpr (e : Expr) : MetaM (Option (Name × Nat × Expr)) := do
|
||||
if let .proj S i x := e then
|
||||
return (S, i, x)
|
||||
if let .const fn _ := e.getAppFn then
|
||||
if let some info ← getProjectionFnInfo? fn then
|
||||
if e.getAppNumArgs == info.numParams + 1 then
|
||||
if let some (ConstantInfo.ctorInfo fVal) := (← getEnv).find? info.ctorName then
|
||||
return (fVal.induct, info.i, e.appArg!)
|
||||
return none
|
||||
|
||||
/-- Runs `etaStruct?` over the whole expression. -/
|
||||
private def etaStructReduce (e : Expr) : StructElabM Expr := do
|
||||
let e ← instantiateMVars e
|
||||
Meta.transform e (post := fun e => do
|
||||
if let some e ← etaStruct? e then
|
||||
return .done e
|
||||
else
|
||||
return .continue)
|
||||
|
||||
/--
|
||||
Puts an expression into "field normal form".
|
||||
- All projections of constructors for parent structures are reduced.
|
||||
|
|
@ -557,7 +517,8 @@ Puts an expression into "field normal form".
|
|||
- Constructors of parent structures are eta reduced.
|
||||
-/
|
||||
private def fieldNormalizeExpr (e : Expr) (zetaDelta : Bool := true) : StructElabM Expr := do
|
||||
etaStructReduce <| ← reduceFieldProjs e (zetaDelta := zetaDelta)
|
||||
let ancestors := (← get).ancestorFieldIdx
|
||||
etaStructReduce (p := ancestors.contains) <| ← reduceFieldProjs e (zetaDelta := zetaDelta)
|
||||
|
||||
private def fieldFromMsg (info : StructFieldInfo) : MessageData :=
|
||||
if let some sourceStructName := info.sourceStructNames.head? then
|
||||
|
|
@ -1150,11 +1111,9 @@ Assumes the inductive type has already been added to the environment.
|
|||
Note: we can't generally use optParams here since the default values might depend on previous ones.
|
||||
We include autoParams however.
|
||||
-/
|
||||
private def mkFlatCtorExpr (levelParams : List Name) (params : Array Expr) (structName : Name) (replaceIndFVars : Expr → MetaM Expr) :
|
||||
private def mkFlatCtorExpr (levelParams : List Name) (params : Array Expr) (ctor : ConstructorVal) (replaceIndFVars : Expr → MetaM Expr) :
|
||||
StructElabM Expr := do
|
||||
let env ← getEnv
|
||||
-- build the constructor application using the fields in the local context
|
||||
let ctor := getStructureCtor env structName
|
||||
let mut val := mkAppN (mkConst ctor.name (levelParams.map mkLevelParam)) params
|
||||
let fieldInfos := (← get).fields
|
||||
for fieldInfo in fieldInfos do
|
||||
|
|
@ -1173,17 +1132,20 @@ private def mkFlatCtorExpr (levelParams : List Name) (params : Array Expr) (stru
|
|||
| _ => pure decl.type
|
||||
let type ← zetaDeltaFVars (← instantiateMVars type) parentFVars
|
||||
let type ← replaceIndFVars type
|
||||
return .lam decl.userName type (val.abstract #[fieldInfo.fvar]) decl.binderInfo
|
||||
return .lam decl.userName.eraseMacroScopes type (val.abstract #[fieldInfo.fvar]) decl.binderInfo
|
||||
val ← mkLambdaFVars params val
|
||||
val ← replaceIndFVars val
|
||||
fieldNormalizeExpr val
|
||||
|
||||
private partial def mkFlatCtor (levelParams : List Name) (params : Array Expr) (structName : Name) (replaceIndFVars : Expr → MetaM Expr) :
|
||||
StructElabM Unit := do
|
||||
let val ← mkFlatCtorExpr levelParams params structName replaceIndFVars
|
||||
let env ← getEnv
|
||||
let ctor := getStructureCtor env structName
|
||||
let val ← mkFlatCtorExpr levelParams params ctor replaceIndFVars
|
||||
withLCtx {} {} do trace[Elab.structure] "created flat constructor:{indentExpr val}"
|
||||
unless val.hasSyntheticSorry do
|
||||
let flatCtorName := mkFlatCtorOfStructName structName
|
||||
-- Note: flatCtorName will be private if the constructor is private
|
||||
let flatCtorName := mkFlatCtorOfStructCtorName ctor.name
|
||||
let valType ← replaceIndFVars (← instantiateMVars (← inferType val))
|
||||
let valType := valType.inferImplicit params.size true
|
||||
addDecl <| Declaration.defnDecl (← mkDefinitionValInferrringUnsafe flatCtorName levelParams valType val .abbrev)
|
||||
|
|
@ -1393,8 +1355,8 @@ private def mkRemainingProjections (levelParams : List Name) (params : Array Exp
|
|||
-- No need to zeta delta reduce; `fvarToConst` has replaced such fvars.
|
||||
let val ← fieldNormalizeExpr val (zetaDelta := false)
|
||||
fvarToConst := fvarToConst.insert field.fvar val
|
||||
-- TODO(kmill): if it is a direct parent, add the coercion function the environment and use that instead of `val`,
|
||||
-- and evaluate the difference.
|
||||
-- TODO(kmill): if it is a direct parent, try adding the coercion function from the environment and use that instead of `val`.
|
||||
-- (This should be evaluated to see if it is a good idea.)
|
||||
else
|
||||
throwError m!"(mkRemainingProjections internal error) {field.name} has no value"
|
||||
|
||||
|
|
@ -1465,30 +1427,31 @@ def elabStructureCommand : InductiveElabDescr where
|
|||
collectUsedFVars := collectUsedFVars lctx localInsts fieldInfos
|
||||
checkUniverses := fun _ u => withLCtx lctx localInsts do checkResultingUniversesForFields fieldInfos u
|
||||
finalizeTermElab := withLCtx lctx localInsts do checkDefaults fieldInfos
|
||||
prefinalize := fun _ _ _ => do
|
||||
prefinalize := fun levelParams params replaceIndFVars => do
|
||||
withLCtx lctx localInsts do
|
||||
addProjections r fieldInfos
|
||||
registerStructure view.declName fieldInfos
|
||||
runStructElabM (init := state) do
|
||||
mkFlatCtor levelParams params view.declName replaceIndFVars
|
||||
addDefaults levelParams params replaceIndFVars
|
||||
let parentInfos ← withLCtx lctx localInsts <| runStructElabM (init := state) do
|
||||
mkRemainingProjections levelParams params view
|
||||
setStructureParents view.declName parentInfos
|
||||
withSaveInfoContext do -- save new env
|
||||
for field in view.fields do
|
||||
-- may not exist if overriding inherited field
|
||||
if (← getEnv).contains field.declName then
|
||||
Term.addTermInfo' field.ref (← mkConstWithLevelParams field.declName) (isBinder := true)
|
||||
finalize := fun levelParams params replaceIndFVars => do
|
||||
let parentInfos ← runStructElabM (init := state) <| withLCtx lctx localInsts <| mkRemainingProjections levelParams params view
|
||||
withSaveInfoContext do
|
||||
-- Add terminfo for parents now that all parent projections exist.
|
||||
for parent in parents do
|
||||
if parent.addTermInfo then
|
||||
Term.addTermInfo' parent.ref (← mkConstWithLevelParams parent.declName) (isBinder := true)
|
||||
setStructureParents view.declName parentInfos
|
||||
checkResolutionOrder view.declName
|
||||
if view.isClass then
|
||||
addParentInstances parentInfos
|
||||
|
||||
runStructElabM (init := state) <| withLCtx lctx localInsts do
|
||||
mkFlatCtor levelParams params view.declName replaceIndFVars
|
||||
addDefaults levelParams params replaceIndFVars
|
||||
return {
|
||||
finalize := do
|
||||
if view.isClass then
|
||||
addParentInstances parentInfos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,12 +139,14 @@ instance : ToString Fact where
|
|||
/-- `tidy`, implemented on `Fact`. -/
|
||||
def tidy (f : Fact) : Fact :=
|
||||
match f.justification.tidy? with
|
||||
| some ⟨_, _, justification⟩ => { justification }
|
||||
| some ⟨constraint, coeffs, justification⟩ => { coeffs, constraint, justification }
|
||||
| none => f
|
||||
|
||||
/-- `combo`, implemented on `Fact`. -/
|
||||
def combo (a : Int) (f : Fact) (b : Int) (g : Fact) : Fact :=
|
||||
{ justification := .combo a f.justification b g.justification }
|
||||
{ coeffs := .combo a f.coeffs b g.coeffs
|
||||
constraint := .combo a f.constraint b g.constraint
|
||||
justification := .combo a f.justification b g.justification }
|
||||
|
||||
end Fact
|
||||
|
||||
|
|
|
|||
|
|
@ -109,4 +109,69 @@ def mkProjections (n : Name) (projDecls : Array StructProjDecl) (instImplicit :
|
|||
let proj := mkApp (mkAppN (.const projName lvls) params) self
|
||||
ctorType := ctorType.bindingBody!.instantiate1 proj
|
||||
|
||||
/--
|
||||
Checks if the expression is of the form `S.mk x.1 ... x.n` with `n` nonzero
|
||||
and `S.mk` a structure constructor with `S` one of the recorded structure parents.
|
||||
Returns `x`.
|
||||
Each projection `x.i` can be either a native projection or from a projection function.
|
||||
-/
|
||||
def etaStruct? (e : Expr) (p : Name → Bool) : MetaM (Option Expr) := do
|
||||
let .const ctor _ := e.getAppFn | return none
|
||||
let some (ConstantInfo.ctorInfo fVal) := (← getEnv).find? ctor | return none
|
||||
unless p fVal.induct do return none
|
||||
unless 0 < fVal.numFields && e.getAppNumArgs == fVal.numParams + fVal.numFields do return none
|
||||
let args := e.getAppArgs
|
||||
let params := args.extract 0 fVal.numParams
|
||||
let some x ← getProjectedExpr ctor fVal.induct params 0 args[fVal.numParams]! none | return none
|
||||
for i in [1 : fVal.numFields] do
|
||||
let arg := args[fVal.numParams + i]!
|
||||
let some x' ← getProjectedExpr ctor fVal.induct params i arg x | return none
|
||||
unless x' == x do return none
|
||||
return x
|
||||
where
|
||||
sameParams (params1 params2 : Array Expr) : MetaM Bool := withNewMCtxDepth do
|
||||
if params1.size == params2.size then
|
||||
for p1 in params1, p2 in params2 do
|
||||
unless ← isDefEqGuarded p1 p2 do
|
||||
return false
|
||||
return true
|
||||
else
|
||||
return false
|
||||
/--
|
||||
Given an expression `e` that's either a native projection or a registered projection
|
||||
function, gives the object being projected.
|
||||
Checks that the parameters are defeq to `params`, that the projection index is equal to `idx`,
|
||||
and, if `x?` is provided, that the object being projected is equal to it.
|
||||
-/
|
||||
getProjectedExpr (ctor induct : Name) (params : Array Expr) (idx : Nat) (e : Expr) (x? : Option Expr) : MetaM (Option Expr) := do
|
||||
if let .proj S i x := e then
|
||||
if i == idx && induct == S && (x? |>.map (· == x) |>.getD true) then
|
||||
let ety ← whnf (← inferType e)
|
||||
let params' := ety.getAppArgs
|
||||
if ← sameParams params params' then
|
||||
return x
|
||||
return none
|
||||
if let .const fn _ := e.getAppFn then
|
||||
if let some info ← getProjectionFnInfo? fn then
|
||||
if info.ctorName == ctor && info.i == idx && e.getAppNumArgs == info.numParams + 1 then
|
||||
let x := e.appArg!
|
||||
if (x? |>.map (· == x) |>.getD true) then
|
||||
let params' := e.appFn!.getAppArgs
|
||||
if ← sameParams params params' then
|
||||
return e.appArg!
|
||||
return none
|
||||
|
||||
/--
|
||||
Eta reduces all structures satisfying `p` in the whole expression.
|
||||
|
||||
See `etaStruct?` for reducing single expressions.
|
||||
-/
|
||||
def etaStructReduce (e : Expr) (p : Name → Bool) : MetaM Expr := do
|
||||
let e ← instantiateMVars e
|
||||
Meta.transform e (post := fun e => do
|
||||
if let some e ← etaStruct? e p then
|
||||
return .done e
|
||||
else
|
||||
return .continue)
|
||||
|
||||
end Lean.Meta
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Authors: Leonardo de Moura
|
|||
Helper functions for retrieving structure information.
|
||||
-/
|
||||
prelude
|
||||
import Init.Control.Option
|
||||
import Lean.Environment
|
||||
import Lean.ProjFns
|
||||
import Lean.Exception
|
||||
|
|
@ -98,7 +99,7 @@ structure StructureDescr where
|
|||
deriving Inhabited
|
||||
|
||||
/--
|
||||
Declare a new structure to the elaborator.
|
||||
Declares a new structure to the elaborator.
|
||||
Every structure created by `structure` or `class` has such an entry.
|
||||
This should be followed up with `setStructureParents` and `setStructureResolutionOrder`.
|
||||
-/
|
||||
|
|
@ -110,7 +111,7 @@ def registerStructure (env : Environment) (e : StructureDescr) : Environment :=
|
|||
}
|
||||
|
||||
/--
|
||||
Set parent projection info for a structure defined in the current module.
|
||||
Sets parent projection info for a structure defined in the current module.
|
||||
Throws an error if the structure has not already been registered with `Lean.registerStructure`.
|
||||
-/
|
||||
def setStructureParents [Monad m] [MonadEnv m] [MonadError m] (structName : Name) (parentInfo : Array StructureParentInfo) : m Unit := do
|
||||
|
|
@ -154,26 +155,29 @@ def getStructureCtor (env : Environment) (constName : Name) : ConstructorVal :=
|
|||
def getStructureFields (env : Environment) (structName : Name) : Array Name :=
|
||||
(getStructureInfo env structName).fieldNames
|
||||
|
||||
/-- Get the `StructureFieldInfo` for the given direct field of the structure. -/
|
||||
/-- Gets the `StructureFieldInfo` for the given direct field of the structure. -/
|
||||
def getFieldInfo? (env : Environment) (structName : Name) (fieldName : Name) : Option StructureFieldInfo :=
|
||||
if let some info := getStructureInfo? env structName then
|
||||
info.fieldInfo.binSearch { fieldName := fieldName, projFn := default, subobject? := none, binderInfo := default } StructureFieldInfo.lt
|
||||
else
|
||||
none
|
||||
|
||||
/-- If `fieldName` is a subobject (that it, if it is an embedded parent structure), then returns the name of that parent structure. -/
|
||||
/--
|
||||
If `fieldName` is a subobject (that it, if it is an embedded parent structure),
|
||||
then returns the name of that parent structure.
|
||||
-/
|
||||
def isSubobjectField? (env : Environment) (structName : Name) (fieldName : Name) : Option Name :=
|
||||
if let some fieldInfo := getFieldInfo? env structName fieldName then
|
||||
fieldInfo.subobject?
|
||||
else
|
||||
none
|
||||
|
||||
/-- Get information for all the parents that appear in the `extends` clause. -/
|
||||
/-- Gets information for all the parents that appear in the `extends` clause. -/
|
||||
def getStructureParentInfo (env : Environment) (structName : Name) : Array StructureParentInfo :=
|
||||
(getStructureInfo env structName).parentInfo
|
||||
|
||||
/--
|
||||
Return the parent structures that are embedded in the structure.
|
||||
Returns the parent structures that are embedded in the structure.
|
||||
This is the array of all results from `Lean.isSubobjectField?` in order.
|
||||
|
||||
Note: this is *not* a subset of the parents from `getStructureParentInfo`.
|
||||
|
|
@ -184,14 +188,37 @@ def getStructureSubobjects (env : Environment) (structName : Name) : Array Name
|
|||
(getStructureFields env structName).filterMap (isSubobjectField? env structName)
|
||||
|
||||
/--
|
||||
Return the name of the structure that contains the field relative to structure `structName`.
|
||||
Returns the name of the structure that contains the field relative to structure `structName`.
|
||||
If `structName` contains the field itself, returns that,
|
||||
and otherwise recursively looks into parents that are subobjects. -/
|
||||
and otherwise recursively looks into parents that are subobjects.
|
||||
-/
|
||||
partial def findField? (env : Environment) (structName : Name) (fieldName : Name) : Option Name :=
|
||||
if (getStructureFields env structName).contains fieldName then
|
||||
some structName
|
||||
else
|
||||
getStructureSubobjects env structName |>.findSome? fun parentStructName => findField? env parentStructName fieldName
|
||||
getStructureSubobjects env structName |>.findSome? (findField? env · fieldName)
|
||||
|
||||
/--
|
||||
Given a structure `structName` and a parent projection name `projName` (e.g. `toParentStructName`),
|
||||
returns the corresponding parent structure name.
|
||||
The parent projection name is a single-component name.
|
||||
|
||||
Note: this relies on the fact that projection names are checked to be consistent across all parents.
|
||||
-/
|
||||
partial def findParentProjStruct? (env : Environment) (structName : Name) (projName : Name) : Option Name :=
|
||||
go structName |>.run' {}
|
||||
where
|
||||
-- Use a cache to navigate the DAG in polynomial time
|
||||
go (structName : Name) : StateM NameSet (Option Name) := do
|
||||
if (← get).contains structName then
|
||||
return none
|
||||
else
|
||||
let parentInfos := getStructureParentInfo env structName
|
||||
if let some parentInfo := parentInfos.find? (projName.isSuffixOf ·.projFn) then
|
||||
return some parentInfo.structName
|
||||
else
|
||||
modify fun s => s.insert structName
|
||||
parentInfos.findSomeM? (go ·.structName)
|
||||
|
||||
/--
|
||||
Gets the name for a structure constructor where the fields have been fully flattened.
|
||||
|
|
@ -204,8 +231,8 @@ The body of the flat constructor has the following properties (recursively):
|
|||
- for subobject fields, the value is the unfolded flat constructor for that field
|
||||
- for standard fields, the value is one of the flat constructor parameters
|
||||
-/
|
||||
def mkFlatCtorOfStructName (structName : Name) : Name :=
|
||||
structName ++ `_flat_ctor
|
||||
def mkFlatCtorOfStructCtorName (structCtorName : Name) : Name :=
|
||||
structCtorName ++ `_flat_ctor
|
||||
|
||||
private partial def getStructureFieldsFlattenedAux (env : Environment) (structName : Name) (fullNames : Array Name) (includeSubobjectFields : Bool) : Array Name :=
|
||||
(getStructureFields env structName).foldl (init := fullNames) fun fullNames fieldName =>
|
||||
|
|
@ -302,30 +329,27 @@ The effective autoParams are collected in the flat constructor.
|
|||
def getAutoParamFnForField? (env : Environment) (structName : Name) (fieldName : Name) : Option Name :=
|
||||
getFnForFieldUsing? mkAutoParamFnOfProjFn env structName fieldName
|
||||
|
||||
partial def getPathToBaseStructureAux (env : Environment) (baseStructName : Name) (structName : Name) (path : List Name) : Option (List Name) :=
|
||||
if baseStructName == structName then
|
||||
some path.reverse
|
||||
else
|
||||
if let some info := getStructureInfo? env structName then
|
||||
-- Prefer subobject projections
|
||||
(info.fieldInfo.findSome? fun field =>
|
||||
match field.subobject? with
|
||||
| none => none
|
||||
| some parentStructName => getPathToBaseStructureAux env baseStructName parentStructName (field.projFn :: path))
|
||||
-- Otherwise, consider other parents
|
||||
<|> info.parentInfo.findSome? fun parent =>
|
||||
if parent.subobject then
|
||||
none
|
||||
else
|
||||
getPathToBaseStructureAux env baseStructName parent.structName (parent.projFn :: path)
|
||||
else none
|
||||
|
||||
/--
|
||||
If `baseStructName` is an ancestor structure for `structName`, then return a sequence of projection functions
|
||||
If `baseStructName` is an ancestor structure for `structName`, then returns a sequence of projection functions
|
||||
to go from `structName` to `baseStructName`. Returns `[]` if `baseStructName == structName`.
|
||||
-/
|
||||
def getPathToBaseStructure? (env : Environment) (baseStructName : Name) (structName : Name) : Option (List Name) :=
|
||||
getPathToBaseStructureAux env baseStructName structName []
|
||||
partial def getPathToBaseStructure? (env : Environment) (baseStructName : Name) (structName : Name) : Option (List Name) :=
|
||||
OptionT.run (go structName []) |>.run' {}
|
||||
where
|
||||
go (structName : Name) (path : List Name) : OptionT (StateM NameSet) (List Name) := do
|
||||
if baseStructName == structName then
|
||||
return path.reverse
|
||||
else
|
||||
guard <| !(← get).contains structName
|
||||
modify fun s => s.insert structName
|
||||
let some info := getStructureInfo? env structName | failure
|
||||
-- Prefer subobject projections
|
||||
(info.fieldInfo.firstM fun field => do
|
||||
let some parentStructName := field.subobject? | failure
|
||||
go parentStructName (field.projFn :: path))
|
||||
-- Otherwise, consider other parents
|
||||
<|> info.parentInfo.firstM fun parent => do
|
||||
go parent.structName (parent.projFn :: path)
|
||||
|
||||
/--
|
||||
Returns true iff `constName` is a non-recursive inductive datatype that has only one constructor and no indices.
|
||||
|
|
@ -348,7 +372,7 @@ def getStructureLikeCtor? (env : Environment) (constName : Name) : Option Constr
|
|||
| _ => panic! "ill-formed environment"
|
||||
| _ => none
|
||||
|
||||
/-- Return number of fields for a structure-like type -/
|
||||
/-- Returns the number of fields for a structure-like type -/
|
||||
def getStructureLikeNumFields (env : Environment) (constName : Name) : Nat :=
|
||||
match env.find? constName with
|
||||
| some (.inductInfo { isRec := false, ctors := [ctor], numIndices := 0, .. }) =>
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ def loadTomlConfig (cfg: LoadConfig) : LogIO Package := do
|
|||
let defaultTargets := defaultTargets.map stringToLegalOrSimpleName
|
||||
let depConfigs ← table.tryDecodeD `require #[]
|
||||
return {
|
||||
name := name
|
||||
dir := cfg.pkgDir
|
||||
relDir := cfg.relPkgDir
|
||||
relConfigFile := cfg.relConfigFile
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ def tst : MetaM Unit :=
|
|||
|
||||
example (z : A) : z.x = 1 := by
|
||||
match z with
|
||||
| { a' := h } => trace_state; exact h
|
||||
| { a' := h, .. } => trace_state; exact h
|
||||
|
||||
example (z : A) : z.x = 1 := by
|
||||
match z with
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ a' : x = 1
|
|||
⊢ { x := x, a' := a' }.x = 1
|
||||
case mk
|
||||
x y : Nat
|
||||
⊢ { x := x, y := y } = { x := { x := x, y := y }.x, y := { x := x, y := y }.y }
|
||||
⊢ { x := x, y := y } = { x := x, y := y }
|
||||
a.1 = 1
|
||||
z : A
|
||||
x✝ : Nat
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ structure Foo1 (α : Type) extends Bar (α → α), Baz α
|
|||
#check Foo1.mk
|
||||
|
||||
def f1 (x : Nat) : Foo1 Nat :=
|
||||
{ a := id
|
||||
{ β := _
|
||||
a := id
|
||||
x := (· + ·)
|
||||
b := fun _ => "" }
|
||||
|
||||
|
|
@ -29,7 +30,8 @@ structure Foo2 (α : Type) extends Bar (α → α), Boo2 α
|
|||
#check Foo2.mk
|
||||
|
||||
def f2 (v : Nat) : Foo2 Nat :=
|
||||
{ a := id
|
||||
{ β := _
|
||||
a := id
|
||||
x := (· + ·)
|
||||
b := fun _ => ""
|
||||
x1 := 1
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
import Lean
|
||||
|
||||
structure A where
|
||||
x : Nat := 0
|
||||
|
||||
structure B extends A where
|
||||
y : Nat := 0
|
||||
|
||||
structure C extends B where
|
||||
z : Nat := 0
|
||||
|
||||
def c : C := {}
|
||||
|
||||
open Lean
|
||||
open Lean.Elab
|
||||
|
||||
def tst (varName structName fieldName : Name) : TermElabM Unit := do
|
||||
let c := mkIdent varName
|
||||
let some p ← Lean.Elab.Term.StructInst.mkProjStx? c structName fieldName | throwError "failed"
|
||||
let p ← Term.elabTerm p none
|
||||
logInfo s!"{p}"
|
||||
|
||||
#eval tst `c `C `x
|
||||
#eval tst `c `C `y
|
||||
#eval tst `c `C `z
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
A.x (B.toA (C.toB c))
|
||||
B.y (C.toB c)
|
||||
C.z c
|
||||
|
|
@ -145,11 +145,13 @@ instance PartialOrder {ι : Type u} {α : ι → Type v} [∀ i, PartialOrder (
|
|||
le_antisymm := sorry }
|
||||
|
||||
instance semilatticeSup [∀ i, SemilatticeSup (α' i)] : SemilatticeSup (∀ i, α' i) where
|
||||
sup x y i := x i ⊔ y i
|
||||
le_sup_left _ _ _ := SemilatticeSup.le_sup_left _ _
|
||||
le_sup_right _ _ _ := SemilatticeSup.le_sup_right _ _
|
||||
sup_le _ _ _ ac bc i := SemilatticeSup.sup_le _ _ _ (ac i) (bc i)
|
||||
|
||||
instance semilatticeInf [∀ i, SemilatticeInf (α' i)] : SemilatticeInf (∀ i, α' i) where
|
||||
inf x y i := x i ⊓ y i
|
||||
inf_le_left _ _ _ := SemilatticeInf.inf_le_left _ _
|
||||
inf_le_right _ _ _ := SemilatticeInf.inf_le_right _ _
|
||||
le_inf _ _ _ ac bc i := SemilatticeInf.le_inf _ _ _ (ac i) (bc i)
|
||||
|
|
|
|||
|
|
@ -15,8 +15,23 @@ structure Subalgebra [OneHom R A] : Type extends Subone A where
|
|||
algebraMap_mem : ∀ r : R, mem (OneHom.toFun r)
|
||||
one_mem := OneHom.map_one (R := R) (A := A) ▸ algebraMap_mem One.one
|
||||
|
||||
set_option pp.mvars false
|
||||
/--
|
||||
error: fields missing: 'one_mem'
|
||||
error: don't know how to synthesize placeholder
|
||||
context:
|
||||
R A : Type
|
||||
inst✝² : One R
|
||||
inst✝¹ : One A
|
||||
inst✝ : OneHom R A
|
||||
⊢ ∀ (r : R), ?_ R A _example (OneHom.toFun r)
|
||||
---
|
||||
error: don't know how to synthesize placeholder
|
||||
context:
|
||||
R A : Type
|
||||
inst✝² : One R
|
||||
inst✝¹ : One A
|
||||
inst✝ : OneHom R A
|
||||
⊢ A → Prop
|
||||
-/
|
||||
#guard_msgs in
|
||||
example [OneHom R A] : Subalgebra R A where
|
||||
|
|
|
|||
|
|
@ -522,9 +522,11 @@ namespace Pi
|
|||
variable {ι : Type _} {α' : ι → Type _}
|
||||
|
||||
instance instOrderTop [∀ i, LE (α' i)] [∀ i, OrderTop (α' i)] : OrderTop (∀ i, α' i) where
|
||||
top := fun _ => ⊤
|
||||
le_top _ := fun _ => le_top
|
||||
|
||||
instance instOrderBot [∀ i, LE (α' i)] [∀ i, OrderBot (α' i)] : OrderBot (∀ i, α' i) where
|
||||
bot := fun _ => ⊥
|
||||
bot_le _ := fun _ => bot_le
|
||||
|
||||
end Pi
|
||||
|
|
@ -2519,7 +2521,7 @@ variable {L : Type _} [Field L] [Algebra F L] [Algebra L E] [IsScalarTower F L E
|
|||
(f : L →ₐ[F] K)
|
||||
|
||||
-- This only required 16,000 heartbeats prior to #3807, and now takes ~210,000.
|
||||
set_option maxHeartbeats 20000
|
||||
set_option maxHeartbeats 16000
|
||||
theorem exists_algHom_adjoin_of_splits''' :
|
||||
∃ φ : adjoin L S →ₐ[F] K, φ.comp (IsScalarTower.toAlgHom F L _) = f := by
|
||||
let L' := (IsScalarTower.toAlgHom F L E).fieldRange
|
||||
|
|
@ -2531,7 +2533,12 @@ theorem exists_algHom_adjoin_of_splits''' :
|
|||
· simp only [← SetLike.coe_subset_coe, coe_restrictScalars, adjoin_subset_adjoin_iff]
|
||||
exact ⟨subset_adjoin_of_subset_left S (F := L'.toSubfield) le_rfl, subset_adjoin _ _⟩
|
||||
· ext x
|
||||
exact (congrFun (congrArg (fun g : L' →ₐ[F] K => (g : L' → K)) hφ) _).trans (congrArg f <| AlgEquiv.symm_apply_apply _ _)
|
||||
exact
|
||||
Eq.trans
|
||||
(congrFun (congrArg (fun g : L' →ₐ[F] K => (g : L' → K)) hφ)
|
||||
(DFunLike.coe (AlgEquiv.ofInjectiveField _) x))
|
||||
(congrArg f
|
||||
(AlgEquiv.symm_apply_apply (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F L E)) x))
|
||||
|
||||
end IntermediateField
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ class MyClass (α : Type u) extends LE α where
|
|||
sup_of_le_left : ∀ a b : α, b ≤ a → sup a b = a
|
||||
|
||||
instance : MyClass Prop where
|
||||
le p q := p → q
|
||||
sup p q := p ∨ q
|
||||
le_refl _ := id
|
||||
sup_of_le_left _ _ h := propext ⟨Or.rec id h, Or.inl⟩
|
||||
|
||||
|
|
|
|||
|
|
@ -10,5 +10,10 @@ structure BarS extends FooS where
|
|||
def f (x : Nat) : BarS :=
|
||||
{ x, y := x, h' := rfl }
|
||||
|
||||
/-- error: cannot synthesize placeholder for field 'h' -/
|
||||
#guard_msgs in
|
||||
example (x : Nat) : BarS :=
|
||||
{ x, h' := rfl, .. }
|
||||
|
||||
def f1 (x : Nat) : BarS :=
|
||||
{ x, h' := rfl }
|
||||
{ x, h' := rfl, y := _ }
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@ This is to fix a bug where structure instance notation was not working when ther
|
|||
|
||||
/-!
|
||||
Motivating issue from https://github.com/leanprover/lean4/issues/5406
|
||||
The `example` had an elaboration error because the structure instance was expanding to `{b := m.b}`.
|
||||
Now it expands to `{b := @m.b}`.
|
||||
The `example` had an elaboration error because the structure instance was expanding to `{b := m.b, x := 1}`.
|
||||
Now it expands to `{b := @m.b, x := 1}`.
|
||||
-/
|
||||
structure Methods where
|
||||
b : Nat → (opt : Nat := 42) → Nat
|
||||
x : Nat
|
||||
|
||||
example (m : Methods) : Methods := { m with }
|
||||
example (m : Methods) : Methods := { m with x := 1 }
|
||||
|
||||
/-- info: fun m => { b := @Methods.b m } : Methods → Methods -/
|
||||
#guard_msgs in #check fun (m : Methods) => { m with }
|
||||
/-- info: fun m => { b := @Methods.b m, x := 1 } : Methods → Methods -/
|
||||
#guard_msgs in #check fun (m : Methods) => { m with x := 1 }
|
||||
|
||||
|
||||
/-!
|
||||
|
|
@ -54,6 +55,7 @@ We need this so that structure instances work properly.
|
|||
|
||||
class C (α : Type) [Inhabited α] where
|
||||
f (x : α := default) : α
|
||||
x : Nat
|
||||
|
||||
/-- info: fun inst => C.f : C Nat → Nat -/
|
||||
#guard_msgs in #check fun (inst : C Nat) => inst.f
|
||||
|
|
@ -64,8 +66,8 @@ class C (α : Type) [Inhabited α] where
|
|||
/-- info: fun inst => @C.f Nat instInhabitedNat inst : C Nat → optParam Nat default → Nat -/
|
||||
#guard_msgs in #check fun (inst : C Nat) => @C.f _ _ inst
|
||||
|
||||
/-- info: fun inst => { f := @C.f Nat instInhabitedNat inst } : C Nat → C Nat -/
|
||||
#guard_msgs in #check fun (inst : C Nat) => { inst with }
|
||||
/-- info: fun inst => { f := @C.f Nat instInhabitedNat inst, x := 1 } : C Nat → C Nat -/
|
||||
#guard_msgs in #check fun (inst : C Nat) => { inst with x := 1 }
|
||||
|
||||
|
||||
/-!
|
||||
|
|
@ -93,7 +95,8 @@ Tests of implicit arguments in updates.
|
|||
|
||||
structure I where
|
||||
f : {_ : Nat} → Nat
|
||||
x := 1
|
||||
|
||||
-- used to give `fun i ↦ ?m.369 i : I → I`
|
||||
/-- info: fun i => { f := @I.f i } : I → I -/
|
||||
#guard_msgs in #check fun (i : I) => {i with}
|
||||
#guard_msgs in #check fun (i : I) => {i with x := 1 }
|
||||
|
|
|
|||
|
|
@ -338,7 +338,6 @@ end Cat
|
|||
def typeToCat : Type u ⥤ Cat where
|
||||
obj X := Cat.of (Discrete X)
|
||||
map := fun {X} {Y} f => by
|
||||
dsimp
|
||||
exact Discrete.functor (Discrete.mk ∘ f)
|
||||
|
||||
@[simp] theorem typeToCat_obj (X : Type u) : typeToCat.obj X = Cat.of (Discrete X) := rfl
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ set_option pp.explicit true
|
|||
info: def foo : Foo :=
|
||||
{ obj := fun x => @Function.const Type (@Eq Unit Unit.unit Unit.unit) Nat foo.proof_1,
|
||||
map :=
|
||||
@id ((fun x => @Function.const Type (@Eq Unit Unit.unit Unit.unit) Nat foo.proof_1) Unit.unit)
|
||||
(@OfNat.ofNat Nat 0 (instOfNatNat 0)) }
|
||||
@id (@Function.const Type (@Eq Unit Unit.unit Unit.unit) Nat foo.proof_1) (@OfNat.ofNat Nat 0 (instOfNatNat 0)) }
|
||||
-/
|
||||
#guard_msgs in
|
||||
#print foo
|
||||
|
|
|
|||
|
|
@ -265,17 +265,14 @@ instance Functor.category : Category.{max u₁ v₂} (C ⥤ D) where
|
|||
comp α β := vcomp α β
|
||||
id_comp := by
|
||||
intro X Y f
|
||||
simp_all only
|
||||
ext x : 2
|
||||
apply id_comp
|
||||
comp_id := by
|
||||
intro X Y f
|
||||
simp_all only
|
||||
ext x : 2
|
||||
apply comp_id
|
||||
assoc := by
|
||||
intro W X Y Z f g h
|
||||
simp_all only
|
||||
ext x : 2
|
||||
apply assoc
|
||||
|
||||
|
|
@ -384,7 +381,6 @@ instance functorCategoryPreadditive : Preadditive (C ⥤ D) where
|
|||
apply add_zero
|
||||
neg_add_cancel := by
|
||||
intros
|
||||
dsimp only
|
||||
ext
|
||||
apply neg_add_cancel }
|
||||
add_comp := by
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ 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.
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ example : 6 = 6 ∧ [7] = [7] := by
|
|||
|
||||
-- Test that `Config.intros` causes `solve_by_elim` to call `intro` on intermediate goals.
|
||||
example (P : Prop) : P → P := by
|
||||
fail_if_success solve_by_elim (config := {intros := false})
|
||||
fail_if_success solve_by_elim (config := {intro := false})
|
||||
solve_by_elim
|
||||
|
||||
-- This worked in mathlib3 without the `@`, but now goes into a loop.
|
||||
|
|
|
|||
|
|
@ -58,13 +58,21 @@ structure B extends A where
|
|||
structure C extends B where
|
||||
(z : Nat := 2*y) (x := z + 2) (y := z + 3)
|
||||
|
||||
/-- info: { x := 1, y := 1 + 2, z := 2 * (1 + 2) } : C -/
|
||||
-- This first example does not work because the default values at `C` are the only ones considered.
|
||||
/--
|
||||
error: fields missing: 'y', 'z'
|
||||
---
|
||||
info: { x := 1, y := sorry, z := sorry } : C
|
||||
-/
|
||||
#guard_msgs in #check { x := 1 : C }
|
||||
/-- info: { x := 2 * 1 + 2, y := 1, z := 2 * 1 } : C -/
|
||||
#guard_msgs in #check { y := 1 : C }
|
||||
/-- info: { x := 1 + 2, y := 1 + 3, z := 1 } : C -/
|
||||
#guard_msgs in #check { z := 1 : C }
|
||||
|
||||
-- This first example does not work because the default values at `C` are the only ones considered.
|
||||
/-- error: fields missing: 'y', 'z' -/
|
||||
#guard_msgs in
|
||||
def test1 : C where
|
||||
x := 1
|
||||
def test2 : C where
|
||||
|
|
@ -159,3 +167,154 @@ def test1 (z : Int) : A Int Int where
|
|||
z
|
||||
|
||||
end Ex5
|
||||
|
||||
/-!
|
||||
Default instances are applied before analyzing default values.
|
||||
Without this, `α` would be reported as being a missing field.
|
||||
-/
|
||||
namespace Ex6
|
||||
structure MyStruct where
|
||||
{α : Type u}
|
||||
{β : Type v}
|
||||
a : α
|
||||
b : β
|
||||
|
||||
/-- info: { α := Nat, β := Bool, a := 10, b := true } : MyStruct -/
|
||||
#guard_msgs in #check { a := 10, b := true : MyStruct }
|
||||
end Ex6
|
||||
|
||||
/-!
|
||||
Make sure we have the Lean 3 behavior, where field projections are unfolded.
|
||||
https://github.com/leanprover-community/mathlib4/issues/12129#issuecomment-2056134533
|
||||
-/
|
||||
namespace Mathlib12129
|
||||
|
||||
structure Foo where
|
||||
toFun : Nat → Nat
|
||||
|
||||
structure Bar extends Foo where
|
||||
prop : toFun 0 = 0
|
||||
|
||||
/-
|
||||
Rather than `(fun x => x) 0 = 0` or `{ toFun := fun x => x }.toFun 0 = 0`
|
||||
-/
|
||||
/-- info: ⊢ 0 = 0 -/
|
||||
#guard_msgs in
|
||||
def bar : Bar where
|
||||
toFun x := x
|
||||
prop := by
|
||||
trace_state
|
||||
rfl
|
||||
|
||||
end Mathlib12129
|
||||
|
||||
/-!
|
||||
Explicit fields must be provided, even if they can be inferred.
|
||||
-/
|
||||
namespace Ex7
|
||||
|
||||
structure S where
|
||||
n : Nat
|
||||
m : Fin n
|
||||
|
||||
variable (x : Fin 3)
|
||||
|
||||
/--
|
||||
error: fields missing: 'n'
|
||||
|
||||
field 'n' must be explicitly provided, its synthesized value is
|
||||
3
|
||||
---
|
||||
info: { n := 3, m := x } : S
|
||||
-/
|
||||
#guard_msgs in #check { m := x : S }
|
||||
|
||||
/-- info: { n := 3, m := x } : S -/
|
||||
#guard_msgs in #check { n := _, m := x : S }
|
||||
|
||||
/-- info: { n := 3, m := x } : S -/
|
||||
#guard_msgs in #check { m := x, .. : S }
|
||||
|
||||
/-- info: { n := 3, m := x } : S -/
|
||||
#guard_msgs in #check { n := 3, m := x : S }
|
||||
|
||||
end Ex7
|
||||
|
||||
/-!
|
||||
Diamond inheritance, acquire field values from parent classes.
|
||||
https://github.com/leanprover/lean4/issues/6046
|
||||
-/
|
||||
namespace Issue6046
|
||||
set_option structure.strictResolutionOrder true
|
||||
|
||||
class A
|
||||
|
||||
class B extends A where
|
||||
b : Unit
|
||||
|
||||
structure B' where
|
||||
b : Unit
|
||||
|
||||
class C extends B', B, A
|
||||
|
||||
instance : A where
|
||||
|
||||
instance : B where
|
||||
b := ()
|
||||
|
||||
instance : C where
|
||||
|
||||
/--
|
||||
info: def Issue6046.instC : C :=
|
||||
{ b := B.b }
|
||||
-/
|
||||
#guard_msgs in #print Issue6046.instC
|
||||
|
||||
end Issue6046
|
||||
|
||||
/-!
|
||||
Make sure parent fields still work if one parent depends on another.
|
||||
-/
|
||||
namespace Ex8
|
||||
|
||||
class A (α : Type) where
|
||||
val : α → Nat
|
||||
class B (α : Type) [A α] where
|
||||
val' : α → Nat
|
||||
h : ∃ x : α, A.val x = val' x
|
||||
class C (α : Type) extends A α, B α
|
||||
|
||||
instance : A Nat where
|
||||
val := id
|
||||
instance : B Nat where
|
||||
val' _ := 0
|
||||
h := by exists 0
|
||||
|
||||
/-
|
||||
This was "fields missing: 'val'', 'h'" at some point during testing.
|
||||
To succeed, this relies on being able to compute the type of the `B` parent,
|
||||
which depends on fields of the structure instance being elaborated.
|
||||
-/
|
||||
/-- info: { toA := instANat, toB := instBNat } : C Nat -/
|
||||
#guard_msgs in #check { : C Nat }
|
||||
|
||||
end Ex8
|
||||
|
||||
/-!
|
||||
Autoparams are elaborated eagerly. Here we see that `a` is printed before `b`.
|
||||
-/
|
||||
namespace Ex9
|
||||
structure A where
|
||||
n : Nat := by trace "a"; exact 1
|
||||
m : Fin n
|
||||
|
||||
/--
|
||||
info: a
|
||||
---
|
||||
info: b
|
||||
-/
|
||||
#guard_msgs in
|
||||
example : A where
|
||||
m := by trace "b"; exact 0
|
||||
|
||||
end Ex9
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
|
||||
universe u
|
||||
|
||||
set_option pp.structureInstanceTypes true
|
||||
|
||||
namespace Ex1
|
||||
|
||||
structure A (α : Type u) :=
|
||||
(x : α) (f : α → α := λ x => x)
|
||||
structure A (α : Type u) where
|
||||
(x : α) (f : α → α := λ x => x)
|
||||
|
||||
structure B (α : Type u) extends A α :=
|
||||
(y : α := f (f x)) (g : α → α → α := λ x y => f x)
|
||||
structure B (α : Type u) extends A α where
|
||||
(y : α := f (f x)) (g : α → α → α := λ x y => f x)
|
||||
|
||||
structure C (α : Type u) extends B α :=
|
||||
(z : α := g x y) (x := f z)
|
||||
structure C (α : Type u) extends B α where
|
||||
(z : α := g x y) (x := f z)
|
||||
|
||||
end Ex1
|
||||
|
||||
|
|
@ -18,24 +20,60 @@ open Ex1
|
|||
|
||||
def c1 : C Nat := { x := 1 }
|
||||
|
||||
#check { c1 with z := 2 }
|
||||
|
||||
#check { c1 with z := 2 }
|
||||
/--
|
||||
info: let __src := c1;
|
||||
{ toB := __src.toB, z := 2 : C Nat } : C Nat
|
||||
-/
|
||||
#guard_msgs in #check { c1 with z := 2 }
|
||||
|
||||
theorem ex1 : { c1 with z := 2 }.z = 2 :=
|
||||
rfl
|
||||
|
||||
#check ex1
|
||||
/--
|
||||
info: ex1 :
|
||||
(let __src := c1;
|
||||
{ toB := __src.toB, z := 2 : C Nat }).z =
|
||||
2
|
||||
-/
|
||||
#guard_msgs in #check ex1
|
||||
|
||||
theorem ex2 : { c1 with z := 2 }.x = c1.x :=
|
||||
rfl
|
||||
|
||||
#check ex2
|
||||
/--
|
||||
info: ex2 :
|
||||
(let __src := c1;
|
||||
{ toB := __src.toB, z := 2 : C Nat }).x =
|
||||
c1.x
|
||||
-/
|
||||
#guard_msgs in #check ex2
|
||||
|
||||
def c2 : C (Nat × Nat) := { z := (1, 1) }
|
||||
|
||||
#check { c2 with x.fst := 2 }
|
||||
/--
|
||||
info: let __src := c2;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
(2, __src.snd),
|
||||
f := __src.f, y := __src.y, g := __src.g, z := __src.z : C (Nat × Nat) } : C (Nat × Nat)
|
||||
-/
|
||||
#guard_msgs in #check { c2 with x.fst := 2 }
|
||||
|
||||
#check { c2 with x.1 := 3 }
|
||||
/--
|
||||
info: let __src := c2;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
(3, __src.snd),
|
||||
f := __src.f, y := __src.y, g := __src.g, z := __src.z : C (Nat × Nat) } : C (Nat × Nat)
|
||||
-/
|
||||
#guard_msgs in #check { c2 with x.1 := 3 }
|
||||
|
||||
#check show C _ from { c2.toB with .. }
|
||||
/--
|
||||
info: let_fun this :=
|
||||
let __src := c2.toB;
|
||||
{ toB := __src, z := __src.g __src.x __src.y : C (Nat × Nat) };
|
||||
this : C (Nat × Nat)
|
||||
-/
|
||||
#guard_msgs in #check show C _ from { c2.toB with .. }
|
||||
|
|
|
|||
|
|
@ -3,23 +3,88 @@ universe u
|
|||
def a : Array ((Nat × Nat) × Bool) := #[]
|
||||
def b : Array Nat := #[]
|
||||
|
||||
structure Foo :=
|
||||
(x : Array ((Nat × Nat) × Bool) := #[])
|
||||
(y : Nat := 0)
|
||||
structure Foo where
|
||||
(x : Array ((Nat × Nat) × Bool) := #[])
|
||||
(y : Nat := 0)
|
||||
|
||||
#check (b).modifyOp (idx := 1) (fun s => 2)
|
||||
/-- info: b.modifyOp 1 fun _s => 2 : Array Nat -/
|
||||
#guard_msgs in #check (b).modifyOp (idx := 1) (fun _s => 2)
|
||||
|
||||
#check { b with [1] := 2 }
|
||||
/--
|
||||
info: let __src := b;
|
||||
__src.modifyOp 1 fun s => 2 : Array Nat
|
||||
-/
|
||||
#guard_msgs in #check { b with [1] := 2 }
|
||||
|
||||
#check { a with [1].fst.2 := 1 }
|
||||
/--
|
||||
info: let __src := a;
|
||||
__src.modifyOp 1 fun s =>
|
||||
(let __src := s.fst;
|
||||
(__src.fst, 1),
|
||||
s.snd) : Array ((Nat × Nat) × Bool)
|
||||
-/
|
||||
#guard_msgs in #check { a with [1].fst.2 := 1 }
|
||||
|
||||
def foo : Foo := {}
|
||||
|
||||
#check foo.x[1]!.1.2
|
||||
/-- info: foo.x[1]!.fst.snd : Nat -/
|
||||
#guard_msgs in #check foo.x[1]!.1.2
|
||||
|
||||
#check { foo with x[1].2 := true }
|
||||
#check { foo with x[1].fst.snd := 1 }
|
||||
#check { foo with x[1].1.fst := 1 }
|
||||
/--
|
||||
info: let __src := foo;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
__src.modifyOp 1 fun s => (s.fst, true),
|
||||
y := __src.y } : Foo
|
||||
-/
|
||||
#guard_msgs in #check { foo with x[1].2 := true }
|
||||
/--
|
||||
info: let __src := foo;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
__src.modifyOp 1 fun s =>
|
||||
(let __src := s.fst;
|
||||
(__src.fst, 1),
|
||||
s.snd),
|
||||
y := __src.y } : Foo
|
||||
-/
|
||||
#guard_msgs in #check { foo with x[1].fst.snd := 1 }
|
||||
/--
|
||||
info: let __src := foo;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
__src.modifyOp 1 fun s =>
|
||||
(let __src := s.fst;
|
||||
(1, __src.snd),
|
||||
s.snd),
|
||||
y := __src.y } : Foo
|
||||
-/
|
||||
#guard_msgs in #check { foo with x[1].1.fst := 1 }
|
||||
|
||||
#check { foo with x[1].1.1 := 5 }
|
||||
#check { foo with x[1].1.2 := 5 }
|
||||
/--
|
||||
info: let __src := foo;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
__src.modifyOp 1 fun s =>
|
||||
(let __src := s.fst;
|
||||
(5, __src.snd),
|
||||
s.snd),
|
||||
y := __src.y } : Foo
|
||||
-/
|
||||
#guard_msgs in #check { foo with x[1].1.1 := 5 }
|
||||
/--
|
||||
info: let __src := foo;
|
||||
{
|
||||
x :=
|
||||
let __src := __src.x;
|
||||
__src.modifyOp 1 fun s =>
|
||||
(let __src := s.fst;
|
||||
(__src.fst, 5),
|
||||
s.snd),
|
||||
y := __src.y } : Foo
|
||||
-/
|
||||
#guard_msgs in #check { foo with x[1].1.2 := 5 }
|
||||
|
|
|
|||
|
|
@ -18,10 +18,25 @@ structure D extends B
|
|||
def a : A := ⟨ 0 ⟩
|
||||
|
||||
def b : B := { a with }
|
||||
#print b
|
||||
/--
|
||||
info: def b : B :=
|
||||
let __src := a;
|
||||
{ toA := __src }
|
||||
-/
|
||||
#guard_msgs in #print b
|
||||
|
||||
def c : C := { a with }
|
||||
#print c
|
||||
/--
|
||||
info: def c : C :=
|
||||
let __src := a;
|
||||
{ toB := { toA := __src } }
|
||||
-/
|
||||
#guard_msgs in #print c
|
||||
|
||||
def d : D := { c with }
|
||||
#print d
|
||||
/--
|
||||
info: def d : D :=
|
||||
let __src := c;
|
||||
{ toB := __src.toB }
|
||||
-/
|
||||
#guard_msgs in #print d
|
||||
|
|
@ -48,7 +48,7 @@ def baseTypeIdent := mkIdent (Name.mkSimple "Base")
|
|||
|
||||
def init (type val : TSyntax `ident) (width : Nat) : MacroM (TSyntax `command) := do
|
||||
let fieldsStx ← mkFieldsStx type "base_" width
|
||||
let vals := Array.mkArray width val
|
||||
let vals := Array.replicate width val
|
||||
`(structure $baseTypeIdent where
|
||||
$fieldsStx:structFields
|
||||
def $baseIdent : $baseTypeIdent := ⟨$vals,*⟩)
|
||||
|
|
|
|||
17
tests/lean/run/structInstUpdates.lean
Normal file
17
tests/lean/run/structInstUpdates.lean
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
structure A where
|
||||
x : Nat := 0
|
||||
|
||||
structure B extends A where
|
||||
y : Nat := 0
|
||||
|
||||
structure C extends B where
|
||||
z : Nat := 0
|
||||
|
||||
variable (c : C)
|
||||
|
||||
/-- info: { x := 1, y := c.y, z := c.z } : C -/
|
||||
#guard_msgs in #check { c with x := 1 }
|
||||
/-- info: { toA := c.toA, y := 1, z := c.z } : C -/
|
||||
#guard_msgs in #check { c with y := 1 }
|
||||
/-- info: { toB := c.toB, z := 1 } : C -/
|
||||
#guard_msgs in #check { c with z := 1 }
|
||||
|
|
@ -122,3 +122,15 @@ field notation resolution order:
|
|||
S2', S, U
|
||||
-/
|
||||
#guard_msgs in #print S2'
|
||||
|
||||
/-!
|
||||
Structure instances, setting a parent
|
||||
-/
|
||||
/-- info: { toTheS := s, y := 1 } : S2' -/
|
||||
#guard_msgs in variable (s : S) in #check { toTheS := s, y := 1 : S2' }
|
||||
/-- info: { x := s.x, y := 1 } : S2' -/
|
||||
#guard_msgs in variable (s : U) in #check { toTheU := s, y := 1 : S2' }
|
||||
/-- info: { x := 2, y := 1 } : S2' -/
|
||||
#guard_msgs in #check { toTheS.x := 2, y := 1 : S2' }
|
||||
/-- info: { x := 2, y := 1 } : S2' -/
|
||||
#guard_msgs in #check { toTheU.x := 2, y := 1 : S2' }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
|
||||
#check { fst := 10, snd := 20 : Nat × Nat }
|
||||
/-- info: (10, 20) : Nat × Nat -/
|
||||
#guard_msgs in #check { fst := 10, snd := 20 : Nat × Nat }
|
||||
|
||||
structure S :=
|
||||
(x : Nat) (y : Bool) (z : String)
|
||||
structure S where
|
||||
(x : Nat) (y : Bool) (z : String)
|
||||
|
||||
|
||||
#check { x := 10, y := true, z := "hello" : S }
|
||||
/-- info: { x := 10, y := true, z := "hello" } : S -/
|
||||
#guard_msgs in #check { x := 10, y := true, z := "hello" : S }
|
||||
|
||||
#check { fst := "hello", snd := "world" : Prod _ _ }
|
||||
/-- info: ("hello", "world") : String × String -/
|
||||
#guard_msgs in #check { fst := "hello", snd := "world" : Prod _ _ }
|
||||
|
|
|
|||
|
|
@ -34,27 +34,27 @@ structure S4 (α : Type) extends S2 α, S3 α where
|
|||
/-- info: Test1.S4.mk {α : Type} (toS2 : S2 α) (w : Nat) (x' : α) : S4 α -/
|
||||
#guard_msgs in #check S4.mk
|
||||
/--
|
||||
info: def Test1.S1._flat_ctor : {α : Type} → α → Nat → S1 α :=
|
||||
info: def Test1.S1.mk._flat_ctor : {α : Type} → α → Nat → S1 α :=
|
||||
fun α x y => S1.mk x y
|
||||
-/
|
||||
#guard_msgs in #print S1._flat_ctor
|
||||
#guard_msgs in #print S1.mk._flat_ctor
|
||||
/--
|
||||
info: def Test1.S2._flat_ctor : {α : Type} → α → Nat → Nat → S2 α :=
|
||||
info: def Test1.S2.mk._flat_ctor : {α : Type} → α → Nat → Nat → S2 α :=
|
||||
fun α x y z => S2.mk (S1.mk x y) z
|
||||
-/
|
||||
#guard_msgs in #print S2._flat_ctor
|
||||
#guard_msgs in #print S2.mk._flat_ctor
|
||||
/--
|
||||
info: def Test1.S3._flat_ctor : {α : Type} → α → Nat → Nat → S3 α :=
|
||||
info: def Test1.S3.mk._flat_ctor : {α : Type} → α → Nat → Nat → S3 α :=
|
||||
fun α x y w => S3.mk (S1.mk x y) w
|
||||
-/
|
||||
#guard_msgs in #print S3._flat_ctor
|
||||
#guard_msgs in #print S3.mk._flat_ctor
|
||||
/--
|
||||
info: def Test1.S4._flat_ctor : {α : Type} → α → Nat → Nat → Nat → α → S4 α :=
|
||||
info: def Test1.S4.mk._flat_ctor : {α : Type} → α → Nat → Nat → Nat → α → S4 α :=
|
||||
fun α x y z w x' => S4.mk (S2.mk (S1.mk x y) z) w x'
|
||||
-/
|
||||
#guard_msgs in #print S4._flat_ctor
|
||||
/-- info: Test1.S4._flat_ctor {α : Type} (x : α) (y z w : Nat) (x' : α) : S4 α -/
|
||||
#guard_msgs in #check S4._flat_ctor
|
||||
#guard_msgs in #print S4.mk._flat_ctor
|
||||
/-- info: Test1.S4.mk._flat_ctor {α : Type} (x : α) (y z w : Nat) (x' : α) : S4 α -/
|
||||
#guard_msgs in #check S4.mk._flat_ctor
|
||||
|
||||
end Test1
|
||||
|
||||
|
|
@ -146,16 +146,16 @@ info: Test2_1.Semigroup.mk.{u_1} {α : Type u_1} [toMul : Mul α] [toAssociative
|
|||
-/
|
||||
#guard_msgs in #check Semigroup.mk
|
||||
/--
|
||||
info: def Test2_1.Semigroup._flat_ctor.{u_1} : {α : Type u_1} →
|
||||
info: def Test2_1.Semigroup.mk._flat_ctor.{u_1} : {α : Type u_1} →
|
||||
(mul : α → α → α) → (∀ (x y z : α), @Eq α (mul (mul x y) z) (mul x (mul y z))) → Semigroup α :=
|
||||
fun α mul mul_assoc => @Semigroup.mk α (@Mul.mk α mul) (@AssociativeMul.mk α (@Mul.mk α mul) mul_assoc)
|
||||
-/
|
||||
#guard_msgs in set_option pp.explicit true in #print Semigroup._flat_ctor
|
||||
#guard_msgs in set_option pp.explicit true in #print Semigroup.mk._flat_ctor
|
||||
/--
|
||||
info: Test2_1.Semigroup._flat_ctor.{u_1} {α : Type u_1} (mul : α → α → α)
|
||||
info: Test2_1.Semigroup.mk._flat_ctor.{u_1} {α : Type u_1} (mul : α → α → α)
|
||||
(mul_assoc : ∀ (x y z : α), @Eq α (mul (mul x y) z) (mul x (mul y z))) : Semigroup α
|
||||
-/
|
||||
#guard_msgs in set_option pp.explicit true in #check Semigroup._flat_ctor
|
||||
#guard_msgs in set_option pp.explicit true in #check Semigroup.mk._flat_ctor
|
||||
|
||||
end Test2_1
|
||||
|
||||
|
|
@ -171,10 +171,10 @@ class Add3 (α : Type _) extends Add2 α, Add α where
|
|||
h (x : α) : x + x = x
|
||||
|
||||
/--
|
||||
info: Test2_2.Add3._flat_ctor.{u_1} {α : Type u_1} (add : α → α → α)
|
||||
info: Test2_2.Add3.mk._flat_ctor.{u_1} {α : Type u_1} (add : α → α → α)
|
||||
(h : ∀ (x : α), @Eq α (@HAdd.hAdd α α α (@instHAdd α (@Add.mk α add)) x x) x) : Add3 α
|
||||
-/
|
||||
#guard_msgs in set_option pp.explicit true in #check Add3._flat_ctor
|
||||
#guard_msgs in set_option pp.explicit true in #check Add3.mk._flat_ctor
|
||||
|
||||
end Test2_2
|
||||
|
||||
|
|
@ -243,7 +243,7 @@ info: Test4.Semigroup.mk.{u_1} (toMagma : Magma)
|
|||
#guard_msgs in set_option pp.explicit true in #check Semigroup.mk
|
||||
|
||||
/--
|
||||
info: def Test4.Semigroup._flat_ctor.{u_1} : (α : Type u_1) →
|
||||
info: def Test4.Semigroup.mk._flat_ctor.{u_1} : (α : Type u_1) →
|
||||
(mul : α → α → α) →
|
||||
(∀ (a b c : α),
|
||||
@Eq α (@Test4.mul (Magma.mk α mul) (@Test4.mul (Magma.mk α mul) a b) c)
|
||||
|
|
@ -251,7 +251,7 @@ info: def Test4.Semigroup._flat_ctor.{u_1} : (α : Type u_1) →
|
|||
Semigroup :=
|
||||
fun α mul mul_assoc => Semigroup.mk (Magma.mk α mul) mul_assoc
|
||||
-/
|
||||
#guard_msgs in set_option pp.explicit true in #print Semigroup._flat_ctor
|
||||
#guard_msgs in set_option pp.explicit true in #print Semigroup.mk._flat_ctor
|
||||
|
||||
end Test4
|
||||
|
||||
|
|
@ -332,10 +332,10 @@ structure A2 extends A1 where
|
|||
h : n > 0
|
||||
|
||||
/--
|
||||
info: def Test7.A2._flat_ctor : (n : Nat) → n > 0 → A2 :=
|
||||
info: def Test7.A2.mk._flat_ctor : (n : Nat) → n > 0 → A2 :=
|
||||
fun n h => A2.mk (A1.mk n) h
|
||||
-/
|
||||
#guard_msgs in #print A2._flat_ctor
|
||||
#guard_msgs in #print A2.mk._flat_ctor
|
||||
|
||||
end Test7
|
||||
|
||||
|
|
@ -384,23 +384,22 @@ structure S4 extends S2, S3
|
|||
#guard_msgs in #check S3.mk
|
||||
/-- info: TestO1.S4.mk (toS2 : S2) : S4 -/
|
||||
#guard_msgs in #check S4.mk
|
||||
/-- info: TestO1.S1._flat_ctor (x : Nat := by exact 0) : S1 -/
|
||||
#guard_msgs in #check S1._flat_ctor
|
||||
/-- info: TestO1.S2._flat_ctor (x : Nat := by exact 0) : S2 -/
|
||||
#guard_msgs in #check S2._flat_ctor
|
||||
/-- info: TestO1.S3._flat_ctor (x : Nat := by exact 1) : S3 -/
|
||||
#guard_msgs in #check S3._flat_ctor
|
||||
/-- info: TestO1.S4._flat_ctor (x : Nat := by exact 1) : S4 -/
|
||||
#guard_msgs in #check S4._flat_ctor
|
||||
/-- info: TestO1.S1.mk._flat_ctor (x : Nat := by exact 0) : S1 -/
|
||||
#guard_msgs in #check S1.mk._flat_ctor
|
||||
/-- info: TestO1.S2.mk._flat_ctor (x : Nat := by exact 0) : S2 -/
|
||||
#guard_msgs in #check S2.mk._flat_ctor
|
||||
/-- info: TestO1.S3.mk._flat_ctor (x : Nat := by exact 1) : S3 -/
|
||||
#guard_msgs in #check S3.mk._flat_ctor
|
||||
/-- info: TestO1.S4.mk._flat_ctor (x : Nat := by exact 1) : S4 -/
|
||||
#guard_msgs in #check S4.mk._flat_ctor
|
||||
|
||||
-- TODO These don't work yet. Need to fix structure instance notation elaborator.
|
||||
/-- info: S1.mk 0 : S1 -/
|
||||
#guard_msgs in #check { : S1 }
|
||||
/-- info: S2.mk (S1.mk 0) : S2 -/
|
||||
#guard_msgs in #check { : S2 }
|
||||
/-- info: S3.mk (S1.mk 0) : S3 -/
|
||||
/-- info: S3.mk (S1.mk 1) : S3 -/
|
||||
#guard_msgs in #check { : S3 }
|
||||
/-- info: S4.mk (S2.mk (S1.mk 0)) : S4 -/
|
||||
/-- info: S4.mk (S2.mk (S1.mk 1)) : S4 -/
|
||||
#guard_msgs in #check { : S4 }
|
||||
|
||||
end TestO1
|
||||
|
|
@ -426,27 +425,26 @@ structure S4 extends S2, S3
|
|||
#guard_msgs in #check S3.mk
|
||||
/-- info: TestO2.S4.mk (toS2 : S2) : S4 -/
|
||||
#guard_msgs in #check S4.mk
|
||||
/-- info: TestO2.S1._flat_ctor (x : Nat := by exact 0) : S1 -/
|
||||
#guard_msgs in #check S1._flat_ctor
|
||||
/-- info: TestO2.S2._flat_ctor (x : Nat := by exact 0) : S2 -/
|
||||
#guard_msgs in #check S2._flat_ctor
|
||||
/-- info: TestO2.S3._flat_ctor (x : Nat) : S3 -/
|
||||
#guard_msgs in #check S3._flat_ctor
|
||||
/-- info: TestO2.S1.mk._flat_ctor (x : Nat := by exact 0) : S1 -/
|
||||
#guard_msgs in #check S1.mk._flat_ctor
|
||||
/-- info: TestO2.S2.mk._flat_ctor (x : Nat := by exact 0) : S2 -/
|
||||
#guard_msgs in #check S2.mk._flat_ctor
|
||||
/-- info: TestO2.S3.mk._flat_ctor (x : Nat) : S3 -/
|
||||
#guard_msgs in #check S3.mk._flat_ctor
|
||||
/-- info: TestO2.S3.x._default : Nat -/
|
||||
#guard_msgs in #check S3.x._default
|
||||
/-- info: TestO2.S4._flat_ctor (x : Nat) : S4 -/
|
||||
#guard_msgs in #check S4._flat_ctor
|
||||
/-- info: TestO2.S4.mk._flat_ctor (x : Nat) : S4 -/
|
||||
#guard_msgs in #check S4.mk._flat_ctor
|
||||
/-- info: TestO2.S4.x._inherited_default : Nat -/
|
||||
#guard_msgs in #check S4.x._inherited_default
|
||||
|
||||
-- TODO These don't work yet. Need to fix structure instance notation elaborator.
|
||||
/-- info: S1.mk 0 : S1 -/
|
||||
#guard_msgs in #check { : S1 }
|
||||
/-- info: S2.mk (S1.mk 0) : S2 -/
|
||||
#guard_msgs in #check { : S2 }
|
||||
/-- info: S3.mk (S1.mk 0) : S3 -/
|
||||
/-- info: S3.mk (S1.mk 1) : S3 -/
|
||||
#guard_msgs in #check { : S3 }
|
||||
/-- info: S4.mk (S2.mk (S1.mk 0)) : S4 -/
|
||||
/-- info: S4.mk (S2.mk (S1.mk 1)) : S4 -/
|
||||
#guard_msgs in #check { : S4 }
|
||||
|
||||
end TestO2
|
||||
|
|
|
|||
|
|
@ -150,10 +150,21 @@ Responds to recovery mode. In these, `ctac` continues even though configuration
|
|||
error: structure 'C' does not have a field named 'x'
|
||||
---
|
||||
info: config is { b := { toA := { x := true } } }
|
||||
---
|
||||
info: ⊢ True
|
||||
-/
|
||||
#guard_msgs in
|
||||
example : True := by
|
||||
ctac -x
|
||||
trace_state
|
||||
trivial
|
||||
|
||||
-- Check that when recovery mode is false, no error is reported.
|
||||
/-- info: ⊢ True -/
|
||||
#guard_msgs in
|
||||
example : True := by
|
||||
fail_if_success ctac -x
|
||||
trace_state
|
||||
trivial
|
||||
|
||||
/--
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
structInst1.lean:12:11-12:19: error: field 'toA' has already been specified
|
||||
structInst1.lean:12:21-12:22: error: field 'x' has already been specified
|
||||
f5 (c : C) (a : A) : C
|
||||
f6 (c : C) (a : A) : A
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
def b : B :=
|
||||
let __src := a;
|
||||
{ toA := __src }
|
||||
def c : C :=
|
||||
let __src := a;
|
||||
{ toB := { toA := __src } }
|
||||
def d : D :=
|
||||
let __src := c;
|
||||
{ toB := __src.toB }
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
def foo : A → B → B :=
|
||||
fun a b => { x := a.x, y := b.y }
|
||||
def boo : A → B → B :=
|
||||
fun a b => { x := b.x, y := b.y }
|
||||
fun a b => b
|
||||
def baz : A → B → C :=
|
||||
fun a b => { toB := { x := a.x, y := b.y } }
|
||||
def biz : A → B → C :=
|
||||
|
|
@ -9,4 +9,4 @@ fun a b => { toB := b }
|
|||
def faz : A → C → C :=
|
||||
fun a c => { toB := { x := a.x, y := c.y } }
|
||||
def fiz : A → C → C :=
|
||||
fun a c => { toB := c.toB }
|
||||
fun a c => c
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ error: overloaded, errors ⏎
|
|||
⏎
|
||||
Additional diagnostic information may be available using the `set_option diagnostics true` command.
|
||||
⏎
|
||||
invalid {...} notation, constructor for `Name` is marked as private
|
||||
invalid {...} notation, constructor for 'Name' is marked as private
|
||||
-/
|
||||
#guard_msgs in
|
||||
def m1 : Name "hello" := {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue