@@ -27,6 +27,11 @@ structure ApplyConfig where
27
27
-/
28
28
synthAssignedInstances := true
29
29
/--
30
+ If `allowSynthFailures` is `true`, then `apply` will return instance implicit arguments
31
+ for which typeclass search failed as new goals.
32
+ -/
33
+ allowSynthFailures := false
34
+ /--
30
35
If `approx := true`, then we turn on `isDefEq` approximations. That is, we use
31
36
the `approxDefEq` combinator.
32
37
-/
@@ -47,15 +52,18 @@ def getExpectedNumArgs (e : Expr) : MetaM Nat := do
47
52
private def throwApplyError {α} (mvarId : MVarId) (eType : Expr) (targetType : Expr) : MetaM α :=
48
53
throwTacticEx `apply mvarId m!"failed to unify{indentExpr eType}\n with{indentExpr targetType}"
49
54
50
- def synthAppInstances (tacticName : Name) (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Array BinderInfo) (synthAssignedInstances : Bool) : MetaM Unit :=
55
+ def synthAppInstances (tacticName : Name) (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Array BinderInfo)
56
+ (synthAssignedInstances : Bool) (allowSynthFailures : Bool) : MetaM Unit :=
51
57
newMVars.size.forM fun i => do
52
58
if binderInfos[i]!.isInstImplicit then
53
59
let mvar := newMVars[i]!
54
60
if synthAssignedInstances || !(← mvar.mvarId!.isAssigned) then
55
61
let mvarType ← inferType mvar
56
- let mvarVal ← synthInstance mvarType
57
- unless (← isDefEq mvar mvarVal) do
58
- throwTacticEx tacticName mvarId "failed to assign synthesized instance"
62
+ try
63
+ let mvarVal ← synthInstance mvarType
64
+ unless (← isDefEq mvar mvarVal) do
65
+ throwTacticEx tacticName mvarId "failed to assign synthesized instance"
66
+ catch e => unless allowSynthFailures do throw e
59
67
60
68
def appendParentTag (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Array BinderInfo) : MetaM Unit := do
61
69
let parentTag ← mvarId.getTag
@@ -76,8 +84,9 @@ If `synthAssignedInstances` is `true`, then `apply` will synthesize instance imp
76
84
even if they have assigned by `isDefEq`, and then check whether the synthesized value matches the
77
85
one inferred. The `congr` tactic sets this flag to false.
78
86
-/
79
- def postprocessAppMVars (tacticName : Name) (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Array BinderInfo) (synthAssignedInstances := true ) : MetaM Unit := do
80
- synthAppInstances tacticName mvarId newMVars binderInfos synthAssignedInstances
87
+ def postprocessAppMVars (tacticName : Name) (mvarId : MVarId) (newMVars : Array Expr) (binderInfos : Array BinderInfo)
88
+ (synthAssignedInstances := true ) (allowSynthFailures := false ) : MetaM Unit := do
89
+ synthAppInstances tacticName mvarId newMVars binderInfos synthAssignedInstances allowSynthFailures
81
90
-- TODO: default and auto params
82
91
appendParentTag mvarId newMVars binderInfos
83
92
@@ -163,7 +172,7 @@ def _root_.Lean.MVarId.apply (mvarId : MVarId) (e : Expr) (cfg : ApplyConfig :=
163
172
let (_, _, eType) ← forallMetaTelescopeReducing eType (some rangeNumArgs.start)
164
173
throwApplyError mvarId eType targetType
165
174
let (newMVars, binderInfos) ← go rangeNumArgs.start
166
- postprocessAppMVars `apply mvarId newMVars binderInfos cfg.synthAssignedInstances
175
+ postprocessAppMVars `apply mvarId newMVars binderInfos cfg.synthAssignedInstances cfg.allowSynthFailures
167
176
let e ← instantiateMVars e
168
177
mvarId.assign (mkAppN e newMVars)
169
178
let newMVars ← newMVars.filterM fun mvar => not <$> mvar.mvarId!.isAssigned
0 commit comments