This commit is contained in:
Leonardo de Moura 2021-08-05 16:14:04 -07:00
parent 789c7073dc
commit bcfc927799
4 changed files with 71 additions and 18 deletions

View file

@ -157,11 +157,18 @@ structure SavedState where
deriving Inhabited
structure Context where
config : Config := {}
lctx : LocalContext := {}
localInstances : LocalInstances := #[]
config : Config := {}
lctx : LocalContext := {}
localInstances : LocalInstances := #[]
/-- Not `none` when inside of an `isDefEq` test. See `PostponedEntry`. -/
defEqCtx? : Option DefEqContext := none
defEqCtx? : Option DefEqContext := none
/--
Track the number of nested `synthPending` invocations. Nested invocations can happen
when the type class resolution invokes `synthPending`.
Remark: in the current implementation, `synthPending` fails if `synthPendingDepth > 0`.
We will add a configuration option if necessary. -/
synthPendingDepth : Nat := 0
abbrev MetaM := ReaderT Context $ StateRefT State CoreM

View file

@ -1365,7 +1365,8 @@ end
failK
| none => failK
private def isDefEqOnFailure (t s : Expr) : MetaM Bool :=
private def isDefEqOnFailure (t s : Expr) : MetaM Bool := do
trace[Meta.isDefEq.onFailure] "{t} =?= {s}"
unstuckMVar t (fun t => Meta.isExprDefEqAux t s) <|
unstuckMVar s (fun s => Meta.isExprDefEqAux t s) <|
tryUnificationHints t s <||> tryUnificationHints s t

View file

@ -647,20 +647,32 @@ def synthInstance (type : Expr) (maxResultSize? : Option Nat := none) : MetaM Ex
private def synthPendingImp (mvarId : MVarId) : MetaM Bool := withIncRecDepth <| withMVarContext mvarId do
let mvarDecl ← getMVarDecl mvarId
match mvarDecl.kind with
| MetavarKind.synthetic =>
| MetavarKind.syntheticOpaque =>
return false
| _ =>
/- Check whether the type of the given metavariable is a class or not. If yes, then try to synthesize
it using type class resolution. We only do it for `synthetic` and `natural` metavariables. -/
match (← isClass? mvarDecl.type) with
| none => pure false
| some _ => do
let val? ← catchInternalId isDefEqStuckExceptionId (synthInstance? mvarDecl.type (maxResultSize? := none)) (fun _ => pure none)
match val? with
| none => pure false
| some val =>
if (← isExprMVarAssigned mvarId) then
pure false
else
assignExprMVar mvarId val
pure true
| _ => pure false
| none =>
return false
| some _ =>
/- TODO: use a configuration option instead of the hard-coded limit `1`. -/
if (← read).synthPendingDepth > 1 then
trace[Meta.synthPending] "too many nested synthPending invocations"
return false
else
withReader (fun ctx => { ctx with synthPendingDepth := ctx.synthPendingDepth + 1 }) do
trace[Meta.synthPending] "synthPending {mkMVar mvarId}"
let val? ← catchInternalId isDefEqStuckExceptionId (synthInstance? mvarDecl.type (maxResultSize? := none)) (fun _ => pure none)
match val? with
| none =>
return false
| some val =>
if (← isExprMVarAssigned mvarId) then
return false
else
assignExprMVar mvarId val
return true
builtin_initialize
registerTraceClass `Meta.synthInstance
@ -669,5 +681,6 @@ builtin_initialize
registerTraceClass `Meta.synthInstance.tryResolve
registerTraceClass `Meta.synthInstance.resume
registerTraceClass `Meta.synthInstance.generate
registerTraceClass `Meta.synthPending
end Lean.Meta

32
tests/lean/run/602.lean Normal file
View file

@ -0,0 +1,32 @@
class Semiring (α : Type) where add : ααα
class Ring (α : Type) where add : ααα
class AddCommMonoid (α : Type) where
class AddCommGroup (α : Type) where
class Module (α β : Type) [Semiring α] [AddCommMonoid β] where
class NormedField (α : Type) where
add : ααα
add_comm : ∀ (x y : α), @Add.add _ ⟨add⟩ x y = @Add.add _ ⟨add⟩ y x
class SemiNormedGroup (α : Type) where
class SemiNormedSpace (α β : Type) [NormedField α] [SemiNormedGroup β] where
instance SemiNormedGroup.toAddCommMonoid [SemiNormedGroup α] : AddCommMonoid α := {}
instance Ring.toSemiring [instR : Ring α] : Semiring α := { add := instR.add }
instance NormedField.toRing [instNF : NormedField α] : Ring α := { add := instNF.add }
-- @[inferTCGoalsRL]
instance SemiNormedSpace.toModule [NormedField α] [SemiNormedGroup β] [SemiNormedSpace α β] : Module α β := {}
constant R : Type := Unit
constant foo (a b : R) : R := a
instance R.NormedField : NormedField R := { add := foo, add_comm := sorry }
instance R.Ring : Ring R := { add := foo }
variable {E : Type} [instSNG : SemiNormedGroup E] [instSNS : SemiNormedSpace R E]
#synth Module R E