@@ -685,11 +685,21 @@ def getMatchCore (root : Std.HashMap Key TrieIndex) (e : Expr) :
685685 | .star =>
686686 pure #[]
687687 /- When goal has fvar head like `p (ite c t e)`, follow the star edge with the fvar's arguments.
688- This finds "eliminator-style" theorems indexed by argument structure. -/
689- | .fvar _ _ =>
690- match root[Key.star]? with
691- | some c => pure #[{ todo := args, score := 0 , c }]
692- | none => pure #[]
688+ This finds "eliminator-style" theorems indexed by argument structure.
689+ We also check the first argument's const key directly, which enables finding
690+ eliminator-style theorems even with -star (when star entries are dropped). -/
691+ | .fvar _ _ => do
692+ let mut cases := #[]
693+ -- Follow star edge if available (for generic fvar-headed lemmas)
694+ if let some c := root[Key.star]? then
695+ cases := cases.push { todo := args, score := 0 , c }
696+ -- Also check first argument's const key (for eliminator-style theorems)
697+ if !args.isEmpty then
698+ let firstArg := args[0 ]!
699+ let (argKey, argArgs) ← MatchClone.getMatchKeyArgs firstArg (root := false )
700+ if let some c := root[argKey]? then
701+ cases := cases.push { todo := argArgs, score := 1 , c }
702+ pure cases
693703 /- See note about "dep-arrow vs arrow" at `getMatchLoop` -/
694704 | .arrow =>
695705 pure (#[] |> pushRootCase root .other #[]
@@ -939,6 +949,57 @@ def createLocalPreDiscrTree
939949def dropKeys (t : LazyDiscrTree α) (keys : List (List LazyDiscrTree.Key)) : MetaM (LazyDiscrTree α) := do
940950 keys.foldlM (init := t) (·.dropKey ·)
941951
952+ /-- Collect all values from a subtree recursively and clear them. -/
953+ partial def collectSubtreeAux (next : TrieIndex) : MatchM α (Array α) :=
954+ if next = 0 then
955+ pure #[]
956+ else do
957+ let (values, star, children) ← evalNode next
958+ -- Collect from star subtrie
959+ let starVals ← collectSubtreeAux star
960+ -- Collect from all children
961+ let mut childVals : Array α := #[]
962+ for (_, childIdx) in children do
963+ childVals := childVals ++ (← collectSubtreeAux childIdx)
964+ -- Clear this node (keep structure but remove values)
965+ modify (·.set! next {values := #[], star, children})
966+ return values ++ starVals ++ childVals
967+
968+ /-- Navigate to a key path and return all values in that subtree, then drop them. -/
969+ def extractKeyAux (next : TrieIndex) (rest : List Key) :
970+ MatchM α (Array α) :=
971+ if next = 0 then
972+ pure #[]
973+ else do
974+ let (_, star, children) ← evalNode next
975+ match rest with
976+ | [] =>
977+ -- At the target node: collect ALL values from entire subtree
978+ collectSubtreeAux next
979+ | k :: r => do
980+ let next := if k == .star then star else children.getD k 0
981+ extractKeyAux next r
982+
983+ /-- Extract and drop entries at a specific key, returning the dropped entries. -/
984+ def extractKey (t : LazyDiscrTree α) (path : List LazyDiscrTree.Key) :
985+ MetaM (Array α × LazyDiscrTree α) :=
986+ match path with
987+ | [] => pure (#[], t)
988+ | rootKey :: rest => do
989+ let idx := t.roots.getD rootKey 0
990+ runMatch t (extractKeyAux idx rest)
991+
992+ /-- Extract entries at the given keys and also drop them from the tree. -/
993+ def extractKeys (t : LazyDiscrTree α) (keys : List (List LazyDiscrTree.Key)) :
994+ MetaM (Array α × LazyDiscrTree α) := do
995+ let mut allExtracted : Array α := #[]
996+ let mut tree := t
997+ for path in keys do
998+ let (extracted, newTree) ← extractKey tree path
999+ allExtracted := allExtracted ++ extracted
1000+ tree := newTree
1001+ return (allExtracted, tree)
1002+
9421003def logImportFailure [Monad m] [MonadLog m] [AddMessageContext m] [MonadOptions m] (f : ImportFailure) : m Unit :=
9431004 logError m!"Processing failure with {f.const} in {f.module}:\n {f.exception.toMessageData}"
9441005
@@ -990,6 +1051,7 @@ def findImportMatches
9901051 (addEntry : Name → ConstantInfo → MetaM (Array (InitEntry α)))
9911052 (droppedKeys : List (List LazyDiscrTree.Key) := [])
9921053 (constantsPerTask : Nat := 1000 )
1054+ (droppedEntriesRef : Option (IO.Ref (Option (Array α))) := none)
9931055 (ty : Expr) : MetaM (MatchResult α) := do
9941056 let cctx ← (read : CoreM Core.Context)
9951057 let ngen ← getNGen
@@ -1001,7 +1063,13 @@ def findImportMatches
10011063 profileitM Exception "lazy discriminator import initialization" (←getOptions) $ do
10021064 let t ← createImportedDiscrTree (createTreeCtx cctx) cNGen (←getEnv) addEntry
10031065 (constantsPerTask := constantsPerTask)
1004- dropKeys t droppedKeys
1066+ -- If a reference is provided, extract and store dropped entries
1067+ if let some droppedRef := droppedEntriesRef then
1068+ let (extracted, t) ← extractKeys t droppedKeys
1069+ droppedRef.set (some extracted)
1070+ pure t
1071+ else
1072+ dropKeys t droppedKeys
10051073 let (importCandidates, importTree) ← importTree.getMatch ty
10061074 ref.set (some importTree)
10071075 pure importCandidates
@@ -1075,10 +1143,11 @@ def findMatchesExt
10751143 (addEntry : Name → ConstantInfo → MetaM (Array (InitEntry α)))
10761144 (droppedKeys : List (List LazyDiscrTree.Key) := [])
10771145 (constantsPerTask : Nat := 1000 )
1146+ (droppedEntriesRef : Option (IO.Ref (Option (Array α))) := none)
10781147 (adjustResult : Nat → α → β)
10791148 (ty : Expr) : MetaM (Array β) := do
10801149 let moduleMatches ← findModuleMatches moduleTreeRef ty
1081- let importMatches ← findImportMatches ext addEntry droppedKeys constantsPerTask ty
1150+ let importMatches ← findImportMatches ext addEntry droppedKeys constantsPerTask droppedEntriesRef ty
10821151 return Array.mkEmpty (moduleMatches.size + importMatches.size)
10831152 |> moduleMatches.appendResultsAux (f := adjustResult)
10841153 |> importMatches.appendResultsAux (f := adjustResult)
@@ -1091,13 +1160,15 @@ def findMatchesExt
10911160* `addEntry` is the function for creating discriminator tree entries from constants.
10921161* `droppedKeys` contains keys we do not want to consider when searching for matches.
10931162 It is used for dropping very general keys.
1163+ * `droppedEntriesRef` optionally stores entries dropped from the tree for later use.
10941164 -/
10951165def findMatches (ext : EnvExtension (IO.Ref (Option (LazyDiscrTree α))))
10961166 (addEntry : Name → ConstantInfo → MetaM (Array (InitEntry α)))
10971167 (droppedKeys : List (List LazyDiscrTree.Key) := [])
10981168 (constantsPerTask : Nat := 1000 )
1169+ (droppedEntriesRef : Option (IO.Ref (Option (Array α))) := none)
10991170 (ty : Expr) : MetaM (Array α) := do
11001171
11011172 let moduleTreeRef ← createModuleTreeRef addEntry droppedKeys
11021173 let incPrio _ v := v
1103- findMatchesExt moduleTreeRef ext addEntry droppedKeys constantsPerTask incPrio ty
1174+ findMatchesExt moduleTreeRef ext addEntry droppedKeys constantsPerTask droppedEntriesRef incPrio ty
0 commit comments