fix: synthesize tc instances before propagating expected type

This commit is contained in:
Gabriel Ebner 2022-11-28 14:29:17 -08:00 committed by Leonardo de Moura
parent 5286c2b5aa
commit bdbab653fd
2 changed files with 36 additions and 6 deletions

View file

@ -164,19 +164,33 @@ abbrev M := ReaderT Context (StateRefT State TermElabM)
private def addInstMVar (mvarId : MVarId) : M Unit :=
modify fun s => { s with instMVars := s.instMVars.push mvarId }
/--
Try to synthesize metavariables are `instMVars` using type class resolution.
The ones that cannot be synthesized yet stay in the `instMVars` list.
Remark: we use this method
- before trying to apply coercions to function,
- before unifying the expected type.
-/
def trySynthesizeAppInstMVars : M Unit := do
let instMVars ← (← get).instMVars.filterM fun instMVar => do
unless (← instantiateMVars (← inferType (.mvar instMVar))).isMVar do try
if (← synthesizeInstMVarCore instMVar) then
return false
catch _ => pure ()
return true
modify ({ · with instMVars })
/--
Try to synthesize metavariables are `instMVars` using type class resolution.
The ones that cannot be synthesized yet are registered.
Remark: we use this method before trying to apply coercions to function. -/
-/
def synthesizeAppInstMVars : M Unit := do
let s ← get
let instMVars := s.instMVars
modify fun s => { s with instMVars := #[] }
Term.synthesizeAppInstMVars instMVars s.f
Term.synthesizeAppInstMVars (← get).instMVars (← get).f
modify ({ · with instMVars := #[] })
/-- fType may become a forallE after we synthesize pending metavariables. -/
private def synthesizePendingAndNormalizeFunType : M Unit := do
synthesizeAppInstMVars
trySynthesizeAppInstMVars
synthesizeSyntheticMVars
let s ← get
let fType ← whnfForall s.fType
@ -348,6 +362,7 @@ private def propagateExpectedType (arg : Arg) : M Unit := do
| some fTypeBody =>
unless fTypeBody.hasLooseBVars do
unless (← hasOptAutoParams fTypeBody) do
trySynthesizeAppInstMVars
trace[Elab.app.propagateExpectedType] "{expectedType} =?= {fTypeBody}"
if (← isDefEq expectedType fTypeBody) then
/- Note that we only set `propagateExpected := false` when propagation has succeeded. -/
@ -389,6 +404,7 @@ private def finalize : M Expr := do
else
return e
if let some expectedType := s.expectedType? then
trySynthesizeAppInstMVars
-- Try to propagate expected type. Ignore if types are not definitionally equal, caller must handle it.
trace[Elab.app.finalize] "expected type: {expectedType}"
discard <| isDefEq expectedType eType

14
tests/lean/run/1892.lean Normal file
View file

@ -0,0 +1,14 @@
def OrderDual (α : Type u) : Type u := α
variable (α : Type u) [LE α] {a b : α}
instance : LE (OrderDual α) := ⟨fun x y : α => y ≤ x⟩
theorem foo' (c : α) : a ≤ b := sorry
example : a ≤ b :=
foo' (OrderDual α) a
theorem foo : a ≤ b := sorry
example : a ≤ b :=
foo (OrderDual α)