diff --git a/src/Lean/Meta/Tactic/Grind/Main.lean b/src/Lean/Meta/Tactic/Grind/Main.lean index 66f94adb6b..ffca603fdd 100644 --- a/src/Lean/Meta/Tactic/Grind/Main.lean +++ b/src/Lean/Meta/Tactic/Grind/Main.lean @@ -215,16 +215,7 @@ private def addHypotheses (goal : Goal) : GrindM Goal := GoalM.run' goal do | none => add r.expr localDecl.toExpr | some h => add r.expr <| mkApp4 (mkConst ``Eq.mp [0]) type r.expr h localDecl.toExpr else - /- - **Note**: We must internalize local variables because their types may be empty, and may not be - referenced anywhere else. Example: - ``` - example (a : { x : Int // x < 0 ∧ x > 0 }) : False := by grind - ``` - -/ - let e ← shareCommon localDecl.toExpr - internalize e 0 - processNewFacts + internalizeLocalDecl localDecl private def initCore (mvarId : MVarId) (params : Params) : GrindM Goal := do /- diff --git a/src/Lean/Meta/Tactic/Grind/Types.lean b/src/Lean/Meta/Tactic/Grind/Types.lean index 29d93131a7..af8db6bec3 100644 --- a/src/Lean/Meta/Tactic/Grind/Types.lean +++ b/src/Lean/Meta/Tactic/Grind/Types.lean @@ -1288,6 +1288,23 @@ opaque internalize (e : Expr) (generation : Nat) (parent? : Option Expr := none) @[extern "lean_grind_process_new_facts"] opaque processNewFacts : GoalM Unit +/-- +Internalizes a local declaration which is not a proposition. +**Note**: We must internalize local variables because their types may be empty, and may not be +referenced anywhere else. Example: +``` +example (a : { x : Int // x < 0 ∧ x > 0 }) : False := by grind +``` +`etaStruct` may also be applicable. +-/ +def internalizeLocalDecl (localDecl : LocalDecl) : GoalM Unit := do + let e ← shareCommon localDecl.toExpr + internalize e 0 + /- + **Note**: `internalize` may add new facts (e.g., `etaStruct` equality) + -/ + processNewFacts + /-- Returns a proof that `a = b` if they have the same type. Otherwise, returns a proof of `a ≍ b`. It assumes `a` and `b` are in the same equivalence class. diff --git a/tests/lean/run/grind_eta_struct_internalize.lean b/tests/lean/run/grind_eta_struct_internalize.lean new file mode 100644 index 0000000000..6b5fff08e2 --- /dev/null +++ b/tests/lean/run/grind_eta_struct_internalize.lean @@ -0,0 +1,38 @@ +namespace List + +/- +This example exposed a bug in the `grind` internalizer when `grind -revert` +is used. +-/ + +variable {α : Type} {β : α → Type} + +def keys : List (Sigma β) → List α := + map Sigma.fst + +@[grind =] +theorem keys_cons {s} {l : List (Sigma β)} : (s :: l).keys = s.1 :: l.keys := + rfl + +variable [DecidableEq α] + +def dlookup (a : α) : List (Sigma β) → Option (β a) + | [] => none + | ⟨a', b⟩ :: l => if h : a' = a then some (Eq.recOn h b) else dlookup a l + +@[grind =] +theorem dlookup_cons_eq (l) (a : α) (b : β a) : dlookup a (⟨a, b⟩ :: l) = some b := + dif_pos rfl + +@[grind =] +theorem dlookup_cons_ne (l) {a} : ∀ s : Sigma β, a ≠ s.1 → dlookup a (s :: l) = dlookup a l + | ⟨_, _⟩, h => dif_neg h.symm + +@[grind =] +theorem dlookup_isSome {a : α} {l : List (Sigma β)} : (dlookup a l).isSome ↔ a ∈ l.keys := by + induction l with + | nil => sorry + | cons s _ _ => + by_cases a = s.fst + · grind + · sorry