-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean
theorem confirmRupHint_preserves_invariant_helper {n : Nat} (f : DefaultFormula n)
    (f_assignments_size : f.assignments.size = n)
    (acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool) (hsize : acc.1.size = n)
    (l : Literal (PosFin n)) (ih : DerivedLitsInvariant f f_assignments_size acc.1 hsize acc.2.1)
    (h : ¬hasAssignment l.snd acc.fst[l.fst.val]! = true) :
    have hsize' : (Array.modify acc.1 l.1.1 (addAssignment l.snd)).size = n

Proof state:
case inl.intro
n : Nat
f : DefaultFormula n
f_assignments_size : f.assignments.size = n
acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool
hsize : acc.fst.size = n
l : Literal (PosFin n)
ih : f.DerivedLitsInvariant f_assignments_size acc.fst hsize acc.snd.fst
h : ¬hasAssignment l.snd acc.fst[l.fst.val]! = true
hsize'✝ : (acc.fst.modify l.fst.val (addAssignment l.snd)).size = n :=
  Eq.mpr (id (congrArg (fun _a => _a = n) (Array.size_modify acc.fst l.fst.val (addAssignment l.snd)))) hsize
i : Fin n
i_in_bounds : ↑i < acc.fst.size
l_in_bounds : l.fst.val < acc.fst.size
h1 : acc.fst[↑i] = f.assignments[↑i]
h2 : ∀ (l : Literal (PosFin n)), l ∈ acc.snd.fst → l.fst.val ≠ ↑i
⊢ let_fun i_lt_assignments_size := ⋯;
  let_fun i_lt_f_assignments_size := ⋯;
  let assignments_i := (acc.fst.modify l.fst.val (addAssignment l.snd))[↑i];
  let fassignments_i := f.assignments[↑i];
  (assignments_i = fassignments_i ∧ ∀ (l_1 : Literal (PosFin n)), l_1 ∈ l :: acc.snd.fst → l_1.fst.val ≠ ↑i) ∨
    (∃ j,
        ((l :: acc.snd.fst).get j).fst.val = ↑i ∧
          assignments_i = addAssignment ((l :: acc.snd.fst).get j).snd fassignments_i ∧
            ¬hasAssignment ((l :: acc.snd.fst).get j).snd fassignments_i = true ∧
              ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i) ∨
      ∃ j1 j2,
        ((l :: acc.snd.fst).get j1).fst.val = ↑i ∧
          ((l :: acc.snd.fst).get j2).fst.val = ↑i ∧
            ((l :: acc.snd.fst).get j1).snd = true ∧
              ((l :: acc.snd.fst).get j2).snd = false ∧
                assignments_i = both ∧
                  fassignments_i = unassigned ∧
                    ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j1 → k ≠ j2 → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i

Tactic:
by_cases l.1.1 = i.1

Result:
case pos
n : Nat
f : DefaultFormula n
f_assignments_size : f.assignments.size = n
acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool
hsize : acc.fst.size = n
l : Literal (PosFin n)
ih : f.DerivedLitsInvariant f_assignments_size acc.fst hsize acc.snd.fst
h : ¬hasAssignment l.snd acc.fst[l.fst.val]! = true
hsize'✝ : (acc.fst.modify l.fst.val (addAssignment l.snd)).size = n :=
  Eq.mpr (id (congrArg (fun _a => _a = n) (Array.size_modify acc.fst l.fst.val (addAssignment l.snd)))) hsize
i : Fin n
i_in_bounds : ↑i < acc.fst.size
l_in_bounds : l.fst.val < acc.fst.size
h1 : acc.fst[↑i] = f.assignments[↑i]
h2 : ∀ (l : Literal (PosFin n)), l ∈ acc.snd.fst → l.fst.val ≠ ↑i
h✝ : l.fst.val = ↑i
⊢ let_fun i_lt_assignments_size := ⋯;
  let_fun i_lt_f_assignments_size := ⋯;
  let assignments_i := (acc.fst.modify l.fst.val (addAssignment l.snd))[↑i];
  let fassignments_i := f.assignments[↑i];
  (assignments_i = fassignments_i ∧ ∀ (l_1 : Literal (PosFin n)), l_1 ∈ l :: acc.snd.fst → l_1.fst.val ≠ ↑i) ∨
    (∃ j,
        ((l :: acc.snd.fst).get j).fst.val = ↑i ∧
          assignments_i = addAssignment ((l :: acc.snd.fst).get j).snd fassignments_i ∧
            ¬hasAssignment ((l :: acc.snd.fst).get j).snd fassignments_i = true ∧
              ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i) ∨
      ∃ j1 j2,
        ((l :: acc.snd.fst).get j1).fst.val = ↑i ∧
          ((l :: acc.snd.fst).get j2).fst.val = ↑i ∧
            ((l :: acc.snd.fst).get j1).snd = true ∧
              ((l :: acc.snd.fst).get j2).snd = false ∧
                assignments_i = both ∧
                  fassignments_i = unassigned ∧
                    ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j1 → k ≠ j2 → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i

case neg
n : Nat
f : DefaultFormula n
f_assignments_size : f.assignments.size = n
acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool
hsize : acc.fst.size = n
l : Literal (PosFin n)
ih : f.DerivedLitsInvariant f_assignments_size acc.fst hsize acc.snd.fst
h : ¬hasAssignment l.snd acc.fst[l.fst.val]! = true
hsize'✝ : (acc.fst.modify l.fst.val (addAssignment l.snd)).size = n :=
  Eq.mpr (id (congrArg (fun _a => _a = n) (Array.size_modify acc.fst l.fst.val (addAssignment l.snd)))) hsize
i : Fin n
i_in_bounds : ↑i < acc.fst.size
l_in_bounds : l.fst.val < acc.fst.size
h1 : acc.fst[↑i] = f.assignments[↑i]
h2 : ∀ (l : Literal (PosFin n)), l ∈ acc.snd.fst → l.fst.val ≠ ↑i
h✝ : ¬l.fst.val = ↑i
⊢ let_fun i_lt_assignments_size := ⋯;
  let_fun i_lt_f_assignments_size := ⋯;
  let assignments_i := (acc.fst.modify l.fst.val (addAssignment l.snd))[↑i];
  let fassignments_i := f.assignments[↑i];
  (assignments_i = fassignments_i ∧ ∀ (l_1 : Literal (PosFin n)), l_1 ∈ l :: acc.snd.fst → l_1.fst.val ≠ ↑i) ∨
    (∃ j,
        ((l :: acc.snd.fst).get j).fst.val = ↑i ∧
          assignments_i = addAssignment ((l :: acc.snd.fst).get j).snd fassignments_i ∧
            ¬hasAssignment ((l :: acc.snd.fst).get j).snd fassignments_i = true ∧
              ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i) ∨
      ∃ j1 j2,
        ((l :: acc.snd.fst).get j1).fst.val = ↑i ∧
          ((l :: acc.snd.fst).get j2).fst.val = ↑i ∧
            ((l :: acc.snd.fst).get j1).snd = true ∧
              ((l :: acc.snd.fst).get j2).snd = false ∧
                assignments_i = both ∧
                  fassignments_i = unassigned ∧
                    ∀ (k : Fin (l :: acc.snd.fst).length), k ≠ j1 → k ≠ j2 → ((l :: acc.snd.fst).get k).fst.val ≠ ↑i