refactor: extract try? suggestions via TryThisInfo (#13774)
This PR makes `try?`'s `expandUserTactic` walk the info tree for `TryThisInfo` nodes (introduced in #10524) instead of parsing the rendered `Try this:` message text. The previous approach scraped lines prefixed with ` [apply] ` from the message log, which would break the moment that wire format changed. The user tactic is run under `withSaveInfoContext` so the in-flight trees come out wrapped with a `PartialContextInfo.commandCtx`, which is what `InfoTree.foldInfo` needs in order to descend; the structured suggestions can then be read directly from the `TryThisInfo` nodes that `TryThis.addSuggestion` already pushes. The prior manual `Core.setMessageLog` save/restore dance is no longer needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6d5ec050f4
commit
705ba6404b
1 changed files with 23 additions and 18 deletions
|
|
@ -7,6 +7,8 @@ module
|
|||
prelude
|
||||
public import Lean.Meta.Tactic.ExposeNames
|
||||
public import Lean.Meta.Tactic.Try
|
||||
public import Lean.Meta.TryThis
|
||||
public import Lean.Server.InfoUtils
|
||||
public import Lean.Elab.Tactic.SimpTrace
|
||||
public import Lean.Elab.Tactic.LibrarySearch
|
||||
public import Lean.Elab.Tactic.Grind.Main
|
||||
|
|
@ -333,40 +335,43 @@ def elabRegisterTryTactic : Command.CommandElab := fun stx => do
|
|||
|
||||
/--
|
||||
Evaluates a user-generated tactic and captures any "Try this" suggestions it produces
|
||||
by examining the message log.
|
||||
by walking the info tree for `TryThisInfo` nodes registered by `TryThis.addSuggestion`.
|
||||
|
||||
Returns an array of tactics: the original tactic followed by any extracted suggestions.
|
||||
-/
|
||||
private def expandUserTactic (tac : TSyntax `tactic) (goal : MVarId) : MetaM (Array (TSyntax `tactic)) := do
|
||||
Term.TermElabM.run' <| do
|
||||
let initialState ← saveState
|
||||
let initialLog ← Core.getMessageLog
|
||||
let initialMsgCount := initialLog.toList.length
|
||||
let initialTreeSize := (← getInfoState).trees.size
|
||||
|
||||
let result ← tryCatchRuntimeEx
|
||||
(do
|
||||
-- Run the tactic to capture its "Try this" messages
|
||||
discard <| Tactic.run goal do
|
||||
-- Run the tactic under `withSaveInfoContext` so its "Try this" suggestions
|
||||
-- get pushed onto info trees that are wrapped with a `ContextInfo` (which
|
||||
-- `foldInfo` needs in order to actually descend).
|
||||
withSaveInfoContext <| discard <| Tactic.run goal do
|
||||
evalTactic tac
|
||||
|
||||
-- Extract tactic suggestions from new messages
|
||||
-- This parses the format produced by TryThis.addSuggestions: "Try this:\n [apply] tactic"
|
||||
let newMsgs := (← Core.getMessageLog).toList.drop initialMsgCount
|
||||
let mut suggestions : Array (TSyntax `tactic) := #[]
|
||||
for msg in newMsgs do
|
||||
if msg.severity == MessageSeverity.information then
|
||||
let msgText ← msg.data.toString
|
||||
for line in msgText.split '\n' do
|
||||
if let some tacticText := line.dropPrefix? " [apply] " then
|
||||
let env ← getEnv
|
||||
if let .ok stx := Parser.runParserCategory env `tactic tacticText.copy then
|
||||
suggestions := suggestions.push ⟨stx⟩
|
||||
-- Walk only the info trees added by this tactic and pull out the
|
||||
-- structured suggestions stored in `TryThisInfo` nodes.
|
||||
let trees := (← getInfoState).trees.toArray
|
||||
let newTrees := trees.extract initialTreeSize trees.size
|
||||
let env ← getEnv
|
||||
let suggestions := newTrees.foldl (init := #[]) fun acc tree =>
|
||||
tree.foldInfo (init := acc) fun _ info acc => Id.run do
|
||||
let .ofCustomInfo { value, .. } := info | acc
|
||||
let some tti := value.get? Meta.Tactic.TryThis.TryThisInfo | acc
|
||||
match tti.suggestion.suggestion with
|
||||
| .tsyntax stx => acc.push ⟨stx.raw⟩
|
||||
| .string s =>
|
||||
match Parser.runParserCategory env `tactic s with
|
||||
| .ok stx => acc.push ⟨stx⟩
|
||||
| .error _ => acc
|
||||
|
||||
pure (some suggestions))
|
||||
(fun _ => pure none)
|
||||
|
||||
initialState.restore
|
||||
Core.setMessageLog initialLog
|
||||
return #[tac] ++ (result.getD #[])
|
||||
|
||||
-- TODO: polymorphic `Tactic.focus`
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue