-- Mathlib/.lake/packages/lean4/src/lean/Std/Sat/AIG/CachedLemmas.lean
theorem mkGateCached.go_decl_eq (aig : AIG α) (input : GateInput aig) :
    ∀ (idx : Nat) (h1) (h2), (go aig input).aig.decls[idx]'h1 = aig.decls[idx]'h2

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
input : aig.GateInput
res : Entrypoint α
hres :
  (match aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) with
    | some hit =>
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ }, ref := { gate := hit.idx, hgate := ⋯ } }
    | none =>
      match aig.decls[input.lhs.ref.gate], aig.decls[input.rhs.ref.gate], input.lhs.inv, input.rhs.inv with
      | Decl.const true, x, true, x_1 => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
      | Decl.const false, x, false, x_1 =>
        { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
      | x, Decl.const true, x_1, true => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
      | x, Decl.const false, x_1, false =>
        { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
      | Decl.const true, x, false, false =>
        { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
          ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
      | Decl.const false, x, true, false =>
        { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
          ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
      | x, Decl.const true, false, false =>
        { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
          ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
      | x, Decl.const false, false, true =>
        { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
          ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
      | x, x_1, x_2, x_3 =>
        if (input.lhs.ref.gate == input.rhs.ref.gate && input.lhs.inv == false && input.rhs.inv == false) = true then
          { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
            ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
        else
          if (input.lhs.ref.gate == input.rhs.ref.gate && input.lhs.inv == !input.rhs.inv) = true then
            { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
          else
            {
              aig :=
                { decls := aig.decls.push (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                  cache :=
                    Cache.insert aig.decls aig.cache
                      (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                  invariant := ⋯ },
              ref := { gate := aig.decls.size, hgate := ⋯ } }) =
    res
⊢ ∀ (idx : Nat) (h1 : idx < res.aig.decls.size) (h2 : idx < aig.decls.size), res.aig.decls[idx] = aig.decls[idx]

Tactic:
split at hres

Result:
case h_1
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
input : aig.GateInput
res : Entrypoint α
x✝ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
hit✝ : CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv)
heq✝ : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = some hit✝
hres :
  { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ }, ref := { gate := hit✝.idx, hgate := ⋯ } } = res
⊢ ∀ (idx : Nat) (h1 : idx < res.aig.decls.size) (h2 : idx < aig.decls.size), res.aig.decls[idx] = aig.decls[idx]

case h_2
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
input : aig.GateInput
res : Entrypoint α
x✝ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝ : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
hres :
  (match aig.decls[input.lhs.ref.gate], aig.decls[input.rhs.ref.gate], input.lhs.inv, input.rhs.inv with
    | Decl.const true, x, true, x_1 => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
    | Decl.const false, x, false, x_1 => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
    | x, Decl.const true, x_1, true => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
    | x, Decl.const false, x_1, false => { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
    | Decl.const true, x, false, false =>
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
    | Decl.const false, x, true, false =>
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
    | x, Decl.const true, false, false =>
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
    | x, Decl.const false, false, true =>
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
    | x, x_1, x_2, x_3 =>
      if (input.lhs.ref.gate == input.rhs.ref.gate && input.lhs.inv == false && input.rhs.inv == false) = true then
        { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
          ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
      else
        if (input.lhs.ref.gate == input.rhs.ref.gate && input.lhs.inv == !input.rhs.inv) = true then
          { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false
        else
          {
            aig :=
              { decls := aig.decls.push (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                cache :=
                  Cache.insert aig.decls aig.cache
                    (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                invariant := ⋯ },
            ref := { gate := aig.decls.size, hgate := ⋯ } }) =
    res
⊢ ∀ (idx : Nat) (h1 : idx < res.aig.decls.size) (h2 : idx < aig.decls.size), res.aig.decls[idx] = aig.decls[idx]