This PR fixes `getStuckMVar?` to detect stuck metavariables through auxiliary parent projections created for diamond inheritance. These coercions (e.g., `AddMonoid'.toAddZero'`) are not registered as regular projections because they construct the parent value from individual fields rather than extracting a single field. Previously, `getStuckMVar?` would give up when encountering them, preventing TC synthesis from being triggered. - Add `AuxParentProjectionInfo` environment extension to `ProjFns.lean` recording `numParams` and `fromClass` for these coercions - Register the info during structure elaboration in `mkCoercionToCopiedParent` - Consult the new extension in `getStuckMVar?` as a fallback when `getProjectionFnInfo?` returns `none` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Kim Morrison <kim@tqft.net>
95 lines
3.6 KiB
Text
95 lines
3.6 KiB
Text
/-
|
|
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
module
|
|
|
|
prelude
|
|
public import Lean.EnvExtension
|
|
|
|
public section
|
|
|
|
namespace Lean
|
|
|
|
/--
|
|
Given a structure `S`, Lean automatically creates an auxiliary definition (projection function)
|
|
for each field. This structure caches information about these auxiliary definitions.
|
|
-/
|
|
structure ProjectionFunctionInfo where
|
|
/-- Constructor associated with the auxiliary projection function. -/
|
|
ctorName : Name
|
|
/-- Number of parameters in the structure -/
|
|
numParams : Nat
|
|
/-- The field index associated with the auxiliary projection function. -/
|
|
i : Nat
|
|
/-- `true` if the structure is a class. -/
|
|
fromClass : Bool
|
|
deriving Inhabited, Repr
|
|
|
|
@[export lean_mk_projection_info]
|
|
def mkProjectionInfoEx (ctorName : Name) (numParams : Nat) (i : Nat) (fromClass : Bool) : ProjectionFunctionInfo :=
|
|
{ ctorName, numParams, i, fromClass }
|
|
@[export lean_projection_info_from_class]
|
|
def ProjectionFunctionInfo.fromClassEx (info : ProjectionFunctionInfo) : Bool :=
|
|
info.fromClass
|
|
|
|
builtin_initialize projectionFnInfoExt : MapDeclarationExtension ProjectionFunctionInfo ← mkMapDeclarationExtension
|
|
|
|
def addProjectionFnInfo (env : Environment) (projName : Name) (ctorName : Name) (numParams : Nat) (i : Nat) (fromClass : Bool) : Environment :=
|
|
projectionFnInfoExt.insert env projName { ctorName, numParams, i, fromClass }
|
|
|
|
namespace Environment
|
|
|
|
def getProjectionFnInfo? (env : Environment) (projName : Name) : Option ProjectionFunctionInfo :=
|
|
projectionFnInfoExt.find? env projName
|
|
|
|
def isProjectionFn (env : Environment) (declName : Name) : Bool :=
|
|
projectionFnInfoExt.contains env declName
|
|
|
|
/-- If `projName` is the name of a projection function, return the associated structure name -/
|
|
def getProjectionStructureName? (env : Environment) (projName : Name) : Option Name :=
|
|
match env.getProjectionFnInfo? projName with
|
|
| none => none
|
|
| some projInfo =>
|
|
match env.find? projInfo.ctorName with
|
|
| some (ConstantInfo.ctorInfo val) => some val.induct
|
|
| _ => none
|
|
|
|
end Environment
|
|
|
|
def isProjectionFn [MonadEnv m] [Monad m] (declName : Name) : m Bool :=
|
|
return (← getEnv).isProjectionFn declName
|
|
|
|
def getProjectionFnInfo? [MonadEnv m] [Monad m] (declName : Name) : m (Option ProjectionFunctionInfo) :=
|
|
return (← getEnv).getProjectionFnInfo? declName
|
|
|
|
/--
|
|
Auxiliary parent projection created when a parent structure cannot be represented as a subobject
|
|
(e.g., due to diamond inheritance). Unlike regular projections, these construct the parent value
|
|
from individual fields rather than extracting a single field.
|
|
Example: `AddMonoid'.toAddZero'` when `AddZero'` cannot be a subobject of `AddMonoid'`.
|
|
-/
|
|
structure AuxParentProjectionInfo where
|
|
/-- Number of parameters in the child structure. -/
|
|
numParams : Nat
|
|
/-- `true` if the child structure is a class. -/
|
|
fromClass : Bool
|
|
deriving Inhabited, Repr
|
|
|
|
builtin_initialize auxParentProjInfoExt : MapDeclarationExtension AuxParentProjectionInfo ← mkMapDeclarationExtension
|
|
|
|
def addAuxParentProjectionInfo (env : Environment) (projName : Name) (numParams : Nat) (fromClass : Bool) : Environment :=
|
|
auxParentProjInfoExt.insert env projName { numParams, fromClass }
|
|
|
|
namespace Environment
|
|
|
|
def getAuxParentProjectionInfo? (env : Environment) (projName : Name) : Option AuxParentProjectionInfo :=
|
|
auxParentProjInfoExt.find? env projName
|
|
|
|
end Environment
|
|
|
|
def getAuxParentProjectionInfo? [MonadEnv m] [Monad m] (declName : Name) : m (Option AuxParentProjectionInfo) :=
|
|
return (← getEnv).getAuxParentProjectionInfo? declName
|
|
|
|
end Lean
|