Skip to content

Commit f4564e3

Browse files
committed
use Kyle's nicer getParentStructType?
1 parent 5fb808a commit f4564e3

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

src/Lean/Meta/WrapInstance.lean

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public import Lean.Meta.SynthInstance
1111
public import Lean.Meta.CtorRecognizer
1212
public import Lean.Elab.Term.TermElabM
1313
import Lean.Structure
14-
import all Lean.Elab.App
1514

1615
/-!
1716
# Instance Wrapping
@@ -63,7 +62,7 @@ Given an instance `i : I` and expected type `I'` (where `I'` must be mvar-free),
6362
- `backward.inferInstanceAs.wrap.data`: wrap data fields in auxiliary definitions
6463
-/
6564

66-
namespace Lean.Elab.Term
65+
namespace Lean.Meta
6766

6867
public register_builtin_option backward.inferInstanceAs.wrap : Bool := {
6968
defValue := true
@@ -113,12 +112,30 @@ partial def getFieldOrigin (structName field : Name) : MetaM (Name × StructureF
113112
| throwError "no such field {field} in {structName}"
114113
return (structName, fi)
115114

115+
/-- Projects application of a structure type to corresponding application of a parent structure. -/
116+
def getParentStructType? (structName parentStructName : Name) (structType : Expr) : MetaM (Option Expr) := OptionT.run do
117+
let env ← getEnv
118+
let some path := getPathToBaseStructure? env parentStructName structName | failure
119+
withLocalDeclD `self structType fun self => do
120+
let proj ← path.foldlM (init := self) fun e projFn => do
121+
let ty ← whnf (← inferType e)
122+
let .const _ us := ty.getAppFn
123+
| trace[Meta.wrapInstance] "could not reduce type `{ty}`"
124+
failure
125+
let params := ty.getAppArgs
126+
pure <| mkApp (mkAppN (.const projFn us) params) e
127+
let projTy ← whnf <| ← inferType proj
128+
if projTy.containsFVar self.fvarId! then
129+
trace[Meta.wrapInstance] "parent type depends on instance fields{indentExpr projTy}"
130+
failure
131+
return projTy
132+
116133
/--
117134
Wrap an instance value so its type matches the expected type exactly.
118135
See the module docstring for the full algorithm specification.
119136
-/
120137
public partial def wrapInstance (inst expectedType : Expr) (compile : Bool := true)
121-
(logCompileErrors : Bool := true) (isMeta : Bool := false) : Term.TermElabM Expr := withTransparency .instances do
138+
(logCompileErrors : Bool := true) (isMeta : Bool := false) : MetaM Expr := withTransparency .instances do
122139
withTraceNode `Meta.wrapInstance
123140
(fun _ => return m!"type: {expectedType}") do
124141
let some className ← isClass? expectedType
@@ -199,19 +216,15 @@ public partial def wrapInstance (inst expectedType : Expr) (compile : Bool := tr
199216
let (baseClassName, fieldInfo) ← getFieldOrigin className mvarDecl.userName
200217
if baseClassName != className then
201218
trace[Meta.wrapInstance] "found inherited field `{mvarDecl.userName}` from parent `{baseClassName}`"
202-
-- find appropriate arguments to `baseClassName` by unification with projection chain
203-
let baseClassType ← do
204-
let instMVar ← mkFreshExprMVar (some expectedType)
205-
let baseClassInst ← mkBaseProjections baseClassName className instMVar
206-
inferType baseClassInst
207-
try
208-
if let .some existingBaseClassInst ← trySynthInstance baseClassType then
209-
trace[Meta.wrapInstance] "using projection of existing instance `{existingBaseClassInst}`"
210-
mvarId.assign (← mkProjection existingBaseClassInst fieldInfo.fieldName)
211-
continue
212-
trace[Meta.wrapInstance] "did not find existing instance for `{baseClassName}`"
213-
catch e =>
214-
trace[Meta.wrapInstance] "error when attempting to reuse existing instance for `{baseClassName}`: {e.toMessageData}"
219+
if let some baseClassType ← getParentStructType? className baseClassName expectedType then
220+
try
221+
if let .some existingBaseClassInst ← trySynthInstance baseClassType then
222+
trace[Meta.wrapInstance] "using projection of existing instance `{existingBaseClassInst}`"
223+
mvarId.assign (← mkProjection existingBaseClassInst fieldInfo.fieldName)
224+
continue
225+
trace[Meta.wrapInstance] "did not find existing instance for `{baseClassName}`"
226+
catch e =>
227+
trace[Meta.wrapInstance] "error when attempting to reuse existing instance for `{baseClassName}`: {e.toMessageData}"
215228

216229
-- For data fields, assign directly or wrap in aux def to fix types.
217230
if backward.inferInstanceAs.wrap.data.get (← getOptions) then

0 commit comments

Comments
 (0)