@@ -40,29 +40,11 @@ private partial def recProjTarget (e : Expr) (nm : Name := e.getAppFn.constName!
4040 else
4141 return nm
4242
43- /-- Expand coercions occurring in `e` -/
44- partial def expandCoe (e : Expr) : MetaM Expr :=
45- withReducibleAndInstances do
46- transform e fun e => do
47- let f := e.getAppFn
48- if f.isConst then
49- let declName := f.constName!
50- if isCoeDecl (← getEnv) declName then
51- /-
52- Unfolding an instance projection corresponds to unfolding the target of the projection
53- (and then reducing the projection). Thus we can recursively visit projections before
54- recording the declaration. We shouldn't need to record any other arguments because they
55- should still appear after unfolding (unless there are unused variables in the instances).
56- -/
57- recordExtraModUseFromDecl (isMeta := false ) (← recProjTarget e)
58- if let some e ← unfoldDefinition? e then
59- return .visit e.headBeta
60- return .continue
61-
62-
63-
64- /-- Expand coercions occurring in `e` -/
65- partial def expandCoe' (e : Expr) : MetaM (Expr × List Name) := StateT.run (s := ([] : List Name)) do
43+ /--
44+ Expands coercions occurring in `e` and return the result together with a list of applied
45+ `Coe` instances.
46+ -/
47+ partial def expandCoe (e : Expr) : MetaM (Expr × List Name) := StateT.run (s := ([] : List Name)) do
6648 withReducibleAndInstances do
6749 transform e fun e => do
6850 let f := e.getAppFn
@@ -77,6 +59,10 @@ partial def expandCoe' (e : Expr) : MetaM (Expr × List Name) := StateT.run (s :
7759 -/
7860 recordExtraModUseFromDecl (isMeta := false ) (← recProjTarget e)
7961 if let some e' ← unfoldDefinition? e then
62+ /-
63+ If the unfolded coercion is an application of `Coe.coe` and its third argument is
64+ an application of a constant, record this constant's name.
65+ -/
8066 if declName = ``Coe.coe then
8167 if let some inst := e.getAppArgs[2 ]? then
8268 let g := inst.getAppFn
@@ -99,7 +85,7 @@ def coerceSimple? (expr expectedType : Expr) : MetaM (LOption (Expr × List Name
9985 let coeTInstType := mkAppN (mkConst ``CoeT [u, v]) #[eType, expr, expectedType]
10086 match ← trySynthInstance coeTInstType with
10187 | .some inst =>
102- let result ← expandCoe' (mkAppN (mkConst ``CoeT.coe [u, v]) #[eType, expr, expectedType, inst])
88+ let result ← expandCoe (mkAppN (mkConst ``CoeT.coe [u, v]) #[eType, expr, expectedType, inst])
10389 unless ← isDefEq (← inferType result.1 ) expectedType do
10490 throwError "Could not coerce{indentExpr expr}\n to{indentExpr expectedType}\n coerced expression has wrong type:{indentExpr result.1}"
10591 return .some result
@@ -114,7 +100,7 @@ def coerceToFunction? (expr : Expr) : MetaM (Option Expr) := do
114100 let v ← mkFreshLevelMVar
115101 let γ ← mkFreshExprMVar (← mkArrow α (mkSort v))
116102 let .some inst ← trySynthInstance (mkApp2 (.const ``CoeFun [u,v]) α γ) | return none
117- let expanded ← expandCoe (mkApp4 (.const ``CoeFun.coe [u,v]) α γ inst expr)
103+ let ( expanded, _) ← expandCoe (mkApp4 (.const ``CoeFun.coe [u,v]) α γ inst expr)
118104 unless (← whnf (← inferType expanded)).isForall do
119105 throwError m!"Failed to coerce{indentExpr expr}\n to a function: After applying `CoeFun.coe`, result is still not a function{indentExpr expanded}"
120106 ++ .hint' m!"This is often due to incorrect `CoeFun` instances; the synthesized instance was{indentExpr inst}"
@@ -128,7 +114,7 @@ def coerceToSort? (expr : Expr) : MetaM (Option Expr) := do
128114 let v ← mkFreshLevelMVar
129115 let β ← mkFreshExprMVar (mkSort v)
130116 let .some inst ← trySynthInstance (mkApp2 (.const ``CoeSort [u,v]) α β) | return none
131- let expanded ← expandCoe (mkApp4 (.const ``CoeSort.coe [u,v]) α β inst expr)
117+ let ( expanded, _) ← expandCoe (mkApp4 (.const ``CoeSort.coe [u,v]) α β inst expr)
132118 unless (← whnf (← inferType expanded)).isSort do
133119 throwError m!"Failed to coerce{indentExpr expr}\n to a type: After applying `CoeSort.coe`, result is still not a type{indentExpr expanded}"
134120 ++ .hint' m!"This is often due to incorrect `CoeSort` instances; the synthesized instance was{indentExpr inst}"
@@ -217,7 +203,10 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
217203 let saved ← saveState
218204 if (← isDefEq m n) then
219205 let some monadInst ← isMonad? n | restoreState saved; return none
220- try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => restoreState saved; return none
206+ try
207+ let (result, _) ← expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e])
208+ pure result
209+ catch _ => restoreState saved; return none
221210 else if autoLift.get (← getOptions) then
222211 try
223212 -- Construct lift from `m` to `n`
@@ -244,7 +233,7 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
244233 let v ← getLevel β
245234 let coeTInstType := Lean.mkForall `a BinderInfo.default α <| mkAppN (mkConst ``CoeT [u, v]) #[α, mkBVar 0 , β]
246235 let .some coeTInstVal ← trySynthInstance coeTInstType | return none
247- let eNew ← expandCoe (mkAppN (Lean.mkConst ``Lean.Internal.liftCoeM [u_1, u_2, u_3]) #[m, n, α, β, monadLiftVal, coeTInstVal, monadInst, e])
236+ let ( eNew, _) ← expandCoe (mkAppN (Lean.mkConst ``Lean.Internal.liftCoeM [u_1, u_2, u_3]) #[m, n, α, β, monadLiftVal, coeTInstVal, monadInst, e])
248237 let eNewType ← inferType eNew
249238 unless (← isDefEq expectedType eNewType) do return none
250239 return some eNew -- approach 3 worked
@@ -254,10 +243,15 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
254243 else
255244 return none
256245
257- /-- Coerces `expr` to the type `expectedType`.
258- Returns `.some coerced` on successful coercion,
246+ /--
247+ Coerces `expr` to the type `expectedType`.
248+ Returns `.some (coerced, appliedCoeDecls)` on successful coercion,
259249`.none` if the expression cannot by coerced to that type,
260- or `.undef` if we need more metavariable assignments. -/
250+ or `.undef` if we need more metavariable assignments.
251+
252+ `appliedCoeDecls` is a list of names representing the names of the `Coe` instances that were
253+ applied.
254+ -/
261255def coerce? (expr expectedType : Expr) : MetaM (LOption (Expr × List Name)) := do
262256 if let some lifted ← coerceMonadLift? expr expectedType then
263257 return .some (lifted, [])
0 commit comments