perf: consider functions with ordinary implicit arguments of instance type to be template-like (#9536)

This extends the specialization behavior of functions taking instance
implicits to ordinary implicit arguments that are of instance type. The
choice between the two is often made for subtle inference-related
reasons. It also affects visibility of these functions, because the
module system makes template-like decls visible to the compiler in other
modules.
This commit is contained in:
Cameron Zwarich 2025-07-25 09:03:30 -07:00 committed by GitHub
parent 15f0cd9527
commit 6300329057
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 5 deletions

View file

@ -644,17 +644,20 @@ def Decl.instantiateParamsLevelParams (decl : Decl) (us : List Level) : Array Pa
/--
Return `true` if the arrow type contains an instance implicit argument.
-/
def hasLocalInst (type : Expr) : Bool :=
def hasLocalInst (type : Expr) : CoreM Bool := do
match type with
| .forallE _ _ b bi => bi.isInstImplicit || hasLocalInst b
| _ => false
| .forallE _ d b bi =>
(pure bi.isInstImplicit) <||>
((pure bi.isImplicit) <&&> (pure (← isArrowClass? d).isSome)) <||>
hasLocalInst b
| _ => return false
/--
Return `true` if `decl` is supposed to be inlined/specialized.
-/
def Decl.isTemplateLike (decl : Decl) : CoreM Bool := do
let env ← getEnv
if hasLocalInst decl.type then
if hasLocalInst decl.type then
return true -- `decl` applications will be specialized
else if Meta.isInstanceCore env decl.name then
return true -- `decl` is "fuel" for code specialization

View file

@ -81,7 +81,7 @@ def etaPolyApp? (letDecl : LetDecl) : OptionT SimpM FunDecl := do
guard <| (← read).config.etaPoly
let .const declName us args := letDecl.value | failure
let some info := (← getEnv).find? declName | failure
guard <| hasLocalInst info.type
guard <| (← hasLocalInst info.type)
guard <| !(← Meta.isInstance declName)
let some decl ← getDecl? declName | failure
guard <| decl.getArity > args.size