@@ -30,6 +30,29 @@ public structure EqnInfo extends EqnInfoCore where
3030 fixedParamPerms : FixedParamPerms
3131 deriving Inhabited
3232
33+ /--
34+ Searches in the lhs of goal for a `.brecOn` application, possibly with extra arguments
35+ and under `PProd` projections. Returns the `.brecOn` application and the context
36+ `(fun x => (x).1.2.3 extraArgs = rhs)`.
37+ -/
38+ partial def findBRecOnLHS (goal : Expr) : MetaM (Expr × Expr) := do
39+ let some (_, lhs, rhs) := goal.eq? | throwError "goal not an equality{indentExpr goal}"
40+ go lhs fun brecOnApp x c =>
41+ return (brecOnApp, ← mkLambdaFVars #[x] (← mkEq c rhs))
42+ where
43+ go {α} (e : Expr) (k : Expr → Expr → Expr → MetaM α) : MetaM α := e.withApp fun f xs => do
44+ if let .proj t n e := f then
45+ return ← go e fun brecOnApp x c => k brecOnApp x (mkAppN (mkProj t n c) xs)
46+ if let .const name _ := f then
47+ if isBRecOnRecursor (← getEnv) name then
48+ let arity ← forallTelescope (← inferType f) fun xs _ => return xs.size
49+ if arity ≤ xs.size then
50+ let brecOnApp := mkAppN f xs[:arity]
51+ let extraArgs := xs[arity:]
52+ return ← withLocalDeclD `x (← inferType brecOnApp) fun x =>
53+ k brecOnApp x (mkAppN x extraArgs)
54+ throwError "could not find `.brecOn` application in{indentExpr e}"
55+
3356private partial def mkProof (declName : Name) (type : Expr) : MetaM Expr := do
3457 withTraceNode `Elab.definition.structural.eqns (return m!"{exceptEmoji ·} proving:{indentExpr type}" ) do
3558 prependError m!"failed to generate equational theorem for `{.ofConstName declName}`" do
@@ -45,33 +68,25 @@ where
4568 let mvarId' ← mvarId.withContext do
4669 -- This should now be headed by `.brecOn`
4770 let goal ← mvarId.getType
48- let some (α, lhs, rhs) := goal.eq? | throwError "goal not an equality\n {MessageData.ofGoal mvarId}"
49- let brecOn := lhs.getAppFn
50- unless brecOn.isConst do
51- throwError "goal not headed by `.brecOn`\n {MessageData.ofGoal mvarId}"
52- let brecOnName := brecOn.constName!
53- unless isBRecOnRecursor (← getEnv) brecOnName do
54- throwError "goal not headed by `.brecOn`\n {MessageData.ofGoal mvarId}"
71+ let (brecOnApp, context) ← findBRecOnLHS goal
72+ let brecOnName := brecOnApp.getAppFn.constName!
73+ let us := brecOnApp.getAppFn.constLevels!
5574 let brecOnThmName := brecOnName.str "eq"
75+ let brecOnAppArgs := brecOnApp.getAppArgs
5676 unless (← hasConst brecOnThmName) do
5777 throwError "no theorem `{brecOnThmName}`\n {MessageData.ofGoal mvarId}"
5878 -- We don't just `← inferType eqThmApp` as that beta-reduces more than we want
59- let eqThmType ← inferType (mkConst brecOnThmName brecOn.constLevels!)
60- let eqThmArity ← forallTelescope eqThmType fun xs _ => return xs.size
61- let mut eqThmApp := mkAppN (mkConst brecOnThmName brecOn.constLevels!) lhs.getAppArgs[:eqThmArity]
62- let eqThmType ← instantiateForall eqThmType eqThmApp.getAppArgs[:eqThmArity]
79+ let eqThmType ← inferType (mkConst brecOnThmName us)
80+ let eqThmType ← instantiateForall eqThmType brecOnAppArgs
6381 let some (_, _, rwRhs) := eqThmType.eq? | throwError "theorem `{brecOnThmName}` is not an equality\n {MessageData.ofGoal mvarId}"
6482 let recArg := rwRhs.getAppArgs.back!
6583 trace[Elab.definition.structural.eqns] "abstracting{inlineExpr recArg} from{indentExpr rwRhs}"
6684 let mvarId2 ← mvarId.define `r (← inferType recArg) recArg
6785 let (r, mvarId3) ← mvarId2.intro1P
68- let mut rwRhs := mkApp rwRhs.appFn! (mkFVar r)
69- for extraArg in lhs.getAppArgs[eqThmArity:] do
70- rwRhs := mkApp rwRhs extraArg
71- eqThmApp ← mkCongrFun eqThmApp extraArg
72- let eqThmAppTrans := mkApp5 (mkConst ``Eq.trans goal.getAppFn.constLevels!) α lhs rwRhs rhs eqThmApp
73- let [mvarId4] ← mvarId3.applyN eqThmAppTrans 1 |
74- throwError "rewriting with{inlineExpr eqThmAppTrans} failed\n {MessageData.ofGoal mvarId}"
86+ let mvarId4 ← mvarId3.withContext do
87+ let goal' := mkApp rwRhs.appFn! (mkFVar r)
88+ let thm ← mkCongrArg context (mkAppN (mkConst brecOnThmName us) brecOnAppArgs)
89+ mvarId3.replaceTargetEq (mkApp context goal') thm
7590 pure mvarId4
7691 go mvarId'
7792
0 commit comments