@@ -334,15 +334,17 @@ Sequentially invokes a tactic `act` on each value in candidates on the current s
334334
335335The tactic `act` should return a list of meta-variables that still need to be resolved.
336336If this list is empty, then no variables remain to be solved, and `tryOnEach` returns
337- `none` with the environment set so each goal is resolved.
337+ `none` with the environment set so each goal is resolved (unless `collectAll` is true,
338+ in which case it continues searching and collects complete solutions in the array).
338339
339340If the action throws an internal exception with the `abortSpeculationId` id then
340341further computation is stopped and intermediate results returned. If any other
341342exception is thrown, then it is silently discarded.
342343-/
343344def tryOnEach
344345 (act : Candidate → MetaM (List MVarId))
345- (candidates : Array Candidate) :
346+ (candidates : Array Candidate)
347+ (collectAll : Bool := false ) :
346348 MetaM (Option (Array (List MVarId × MetavarContext))) := do
347349 let mut a := #[]
348350 let s ← saveState
@@ -353,7 +355,7 @@ def tryOnEach
353355 if isAbortSpeculation e then
354356 break
355357 | .ok remaining =>
356- if remaining.isEmpty then
358+ if remaining.isEmpty && !collectAll then
357359 return none
358360 let ctx ← getMCtx
359361 restoreState s
@@ -364,7 +366,8 @@ private def librarySearch' (goal : MVarId)
364366 (tactic : List MVarId → MetaM (List MVarId))
365367 (allowFailure : MVarId → MetaM Bool)
366368 (leavePercentHeartbeats : Nat)
367- (includeStar : Bool := true ) :
369+ (includeStar : Bool := true )
370+ (collectAll : Bool := false ) :
368371 MetaM (Option (Array (List MVarId × MetavarContext))) := do
369372 withTraceNode `Tactic.librarySearch (return m!"{librarySearchEmoji ·} {← goal.getType}" ) do
370373 profileitM Exception "librarySearch" (← getOptions) do
@@ -376,32 +379,35 @@ private def librarySearch' (goal : MVarId)
376379 librarySearchLemma cfg tactic allowFailure cand
377380 -- First pass: search with droppedKeys (excludes star-indexed lemmas)
378381 let candidates ← librarySearchSymm libSearchFindDecls goal
379- match ← tryOnEach act candidates with
380- | none => return none -- Found a complete solution
382+ match ← tryOnEach act candidates collectAll with
383+ | none => return none -- Found a complete solution (only when collectAll = false)
381384 | some results =>
382385 -- Only do star fallback if:
383- -- 1. No results from primary search
386+ -- 1. No complete solutions from primary search (when collectAll, check for empty remaining)
384387 -- 2. includeStar is true
385- if !results.isEmpty || !includeStar then
388+ let hasCompleteSolution := results.any (·.1 .isEmpty)
389+ if hasCompleteSolution || !results.isEmpty || !includeStar then
386390 return some results
387391 -- Second pass: try star-indexed lemmas (those with [ * ] or [ Eq,*,*,* ] keys)
388392 -- No need for librarySearchSymm since getStarLemmas ignores the goal type
389393 let starLemmas ← getStarLemmas
390394 if starLemmas.isEmpty then return some results
391395 let mctx ← getMCtx
392396 let starCandidates := starLemmas.map ((goal, mctx), ·)
393- tryOnEach act starCandidates
397+ tryOnEach act starCandidates collectAll
394398
395399/--
396400Tries to solve the goal by applying a library lemma
397401then calling `tactic` on the resulting goals.
398402
399403Typically here `tactic` is `solveByElim`.
400404
401- If it successfully closes the goal, returns `none`.
405+ If it successfully closes the goal, returns `none` (unless `collectAll` is true) .
402406Otherwise, it returns `some a`, where `a : Array (List MVarId × MetavarContext)`,
403407with an entry for each library lemma which was successfully applied,
404408containing a list of the subsidiary goals, and the metavariable context after the application.
409+ When `collectAll` is true, complete solutions (with empty remaining goals) are also included
410+ in the array instead of returning early.
405411
406412(Always succeeds, and the metavariable context stored in the monad is reverted,
407413unless the goal was completely solved.)
@@ -414,9 +420,10 @@ def librarySearch (goal : MVarId)
414420 fun g => solveByElim [] (maxDepth := 6 ) (exfalso := false ) g)
415421 (allowFailure : MVarId → MetaM Bool := fun _ => pure true )
416422 (leavePercentHeartbeats : Nat := 10 )
417- (includeStar : Bool := true ) :
423+ (includeStar : Bool := true )
424+ (collectAll : Bool := false ) :
418425 MetaM (Option (Array (List MVarId × MetavarContext))) := do
419- librarySearch' goal tactic allowFailure leavePercentHeartbeats includeStar
426+ librarySearch' goal tactic allowFailure leavePercentHeartbeats includeStar collectAll
420427
421428end LibrarySearch
422429
0 commit comments