perf: ctorIdx for single-constructor inductives: no casesOn, macro_inline (#10135)

This PR lets the `ctorIdx` definition for single constructor inductives
avoid the pointless `.casesOn`, and uses `macro_inline` to avoid
compiling the function and wasting symbols.
This commit is contained in:
Joachim Breitner 2025-08-26 15:00:10 +02:00 committed by GitHub
parent 9e47edd0df
commit 0803f1e77e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 17 deletions

View file

@ -55,26 +55,34 @@ public def mkCtorIdx (indName : Name) : MetaM Unit := do
let declType ← mkArrow indType natType
let declType ← mkForallFVars xs declType
let declValue ← withLocalDeclD `x indType fun x => do
let motive ← mkLambdaFVars (indices.push x) natType
let mut value := mkConst casesOnName (levelOne::us)
value := mkAppN value params
value := mkApp value motive
value := mkAppN value indices
value := mkApp value x
for c in info.ctors do
let cInfo ← getConstInfoCtor c
let cType ← instantiateForall cInfo.type params
let alt ← forallBoundedTelescope cType cInfo.numFields fun ys _ =>
mkLambdaFVars ys <| mkRawNatLit cInfo.cidx
value := mkApp value alt
let value ← if info.numCtors = 1 then
pure (mkRawNatLit 0)
else
let motive ← mkLambdaFVars (indices.push x) natType
let mut value := mkConst casesOnName (levelOne::us)
value := mkAppN value params
value := mkApp value motive
value := mkAppN value indices
value := mkApp value x
for c in info.ctors do
let cInfo ← getConstInfoCtor c
let cType ← instantiateForall cInfo.type params
let alt ← forallBoundedTelescope cType cInfo.numFields fun ys _ =>
mkLambdaFVars ys <| mkRawNatLit cInfo.cidx
value := mkApp value alt
pure value
mkLambdaFVars (xs.push x) value
addAndCompile (.defnDecl (← mkDefinitionValInferringUnsafe
let decl := .defnDecl (← mkDefinitionValInferringUnsafe
(name := declName)
(levelParams := info.levelParams)
(type := declType)
(value := declValue)
(hints := ReducibilityHints.abbrev)
))
)
addDecl decl
if info.numCtors = 1 then
setInlineAttribute declName .macroInline
compileDecl decl
modifyEnv fun env => addToCompletionBlackList env declName
modifyEnv fun env => addProtected env declName
setReducibleAttribute declName
@ -82,13 +90,16 @@ public def mkCtorIdx (indName : Name) : MetaM Unit := do
-- Deprecated alias for enumeration types (which used to have `toCtorIdx`)
if (← isEnumType indName) then
let aliasName := mkToCtorIdxName indName
addAndCompile (.defnDecl (← mkDefinitionValInferringUnsafe
let decl := .defnDecl (← mkDefinitionValInferringUnsafe
(name := aliasName)
(levelParams := info.levelParams)
(type := declType)
(value := mkConst declName us)
(hints := ReducibilityHints.abbrev)
))
)
addDecl decl
setInlineAttribute aliasName .macroInline
compileDecl decl
modifyEnv fun env => addToCompletionBlackList env aliasName
modifyEnv fun env => addProtected env aliasName
setReducibleAttribute aliasName

View file

@ -54,11 +54,30 @@ fun {m a} x => x.casesOn (fun {n} a => 0) (fun {n} a => 1) 2
#guard_msgs in
#print B.ctorIdx
-- Single constructor inductives do not use casesOn
inductive Single where | only (n : Nat)
/--
info: @[reducible] protected def Single.ctorIdx : Single → Nat :=
fun x => 0
-/
#guard_msgs in #print Single.ctorIdx
structure Struct where
field1 : Nat
field2 : Bool
/--
info: @[reducible] protected def Struct.ctorIdx : Struct → Nat :=
fun x => 0
-/
#guard_msgs in #print Struct.ctorIdx
-- Unsafe inductives do get a definition
unsafe inductive U : Type | mk : (U → U) → U
/--
info: @[reducible] unsafe protected def U.ctorIdx : U → Nat :=
fun x => U.casesOn x fun a => 0
fun x => 0
-/
#guard_msgs in
#print U.ctorIdx