/-- If a functor preserves equalizers and the appropriate products, it preserves limits. -/
noncomputable def preservesLimitOfPreservesEqualizersAndProduct : PreservesLimitsOfShape J G where
  preservesLimit {K} := by
    let P := ∏ K.obj
    let Q := ∏ fun f : Σp : J × J, p.fst ⟶ p.snd => K.obj f.1.2
    let s : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) ⟨_⟩ ≫ K.map f.2
    let t : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) ⟨f.1.2⟩
    let I := equalizer s t
    let i : I ⟶ P := equalizer.ι s t
    apply
      preservesLimitOfPreservesLimitCone
        (buildIsLimit s t (by simp) (by simp) (limit.isLimit _) (limit.isLimit _)
          (limit.isLimit _))
    refine' IsLimit.ofIsoLimit (buildIsLimit _ _ _ _ _ _ _) _
    · exact Fan.mk _ fun j => G.map (Pi.π _ j)
    · exact Fan.mk (G.obj Q) fun f => G.map (Pi.π _ f)
    · apply G.map s
    · apply G.map t
    · intro f
      dsimp [Fan.mk]
      simp only [← G.map_comp, limit.lift_π]
      congr
    · intro f
      dsimp [Fan.mk]
      simp only [← G.map_comp, limit.lift_π]
      apply congrArg G.map
      dsimp
    · apply Fork.ofι (G.map i)
      rw [← G.map_comp, ← G.map_comp]
      apply congrArg G.map
      exact equalizer.condition s t
    · apply isLimitOfHasProductOfPreservesLimit
    · apply isLimitOfHasProductOfPreservesLimit
    · apply isLimitForkMapOfIsLimit
      apply equalizerIsEqualizer
    · refine Cones.ext (Iso.refl _) ?_
      

Proof state:
case refine'_11
C : Type u
inst✝⁸ : Category.{v, u} C
J : Type w
inst✝⁷ : SmallCategory J
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
inst✝⁵ : HasLimitsOfShape (Discrete J) C
inst✝⁴ : HasLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) C
inst✝³ : HasEqualizers C
G : C ⥤ D
inst✝² : PreservesLimitsOfShape WalkingParallelPair G
inst✝¹ : PreservesLimitsOfShape (Discrete J) G
inst✝ : PreservesLimitsOfShape (Discrete ((p : J × J) × (p.1 ⟶ p.2))) G
K : J ⥤ C
P : C := ∏ K.obj
Q : C := ∏ fun f => K.obj f.fst.2
s : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd
t : P ⟶ Q := Pi.lift fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 }
I : C := equalizer s t
i : I ⟶ P := equalizer.ι s t
⊢ ∀ (j : J),
    (buildLimit (G.map s) (G.map t)
              (_ :
                ∀ (f : (p : J × J) × (p.1 ⟶ p.2)),
                  G.map s ≫ (Fan.mk (G.obj Q) fun f => G.map (Pi.π (fun f => K.obj f.fst.2) f)).π.app { as := f } =
                    (Fan.mk (G.obj (∏ fun j => K.obj j)) fun j => G.map (Pi.π (fun j => K.obj j) j)).π.app
                        { as := f.fst.1 } ≫
                      (K ⋙ G).map f.snd)
              (_ :
                ∀ (f : (p : J × J) × (p.1 ⟶ p.2)),
                  G.map t ≫ (Fan.mk (G.obj Q) fun f => G.map (Pi.π (fun f => K.obj f.fst.2) f)).π.app { as := f } =
                    (Fan.mk (G.obj (∏ fun j => K.obj j)) fun j => G.map (Pi.π (fun j => K.obj j) j)).π.app
                      { as := f.fst.2 })
              (Fork.ofι (G.map i) (_ : G.map i ≫ G.map s = G.map i ≫ G.map t))).π.app
        j =
      (Iso.refl
            (buildLimit (G.map s) (G.map t)
                (_ :
                  ∀ (f : (p : J × J) × (p.1 ⟶ p.2)),
                    G.map s ≫ (Fan.mk (G.obj Q) fun f => G.map (Pi.π (fun f => K.obj f.fst.2) f)).π.app { as := f } =
                      (Fan.mk (G.obj (∏ fun j => K.obj j)) fun j => G.map (Pi.π (fun j => K.obj j) j)).π.app
                          { as := f.fst.1 } ≫
                        (K ⋙ G).map f.snd)
                (_ :
                  ∀ (f : (p : J × J) × (p.1 ⟶ p.2)),
                    G.map t ≫ (Fan.mk (G.obj Q) fun f => G.map (Pi.π (fun f => K.obj f.fst.2) f)).π.app { as := f } =
                      (Fan.mk (G.obj (∏ fun j => K.obj j)) fun j => G.map (Pi.π (fun j => K.obj j) j)).π.app
                        { as := f.fst.2 })
                (Fork.ofι (G.map i) (_ : G.map i ≫ G.map s = G.map i ≫ G.map t))).pt).hom ≫
        (G.mapCone
                (buildLimit s t
                  (_ :
                    ∀ (a : (p : J × J) × (p.1 ⟶ p.2)),
                      limit.lift (Discrete.functor fun b => (fun f => K.obj f.fst.2) b)
                            (Fan.mk (∏ K.obj) fun f =>
                              limit.π (Discrete.functor K.obj) { as := f.fst.1 } ≫ K.map f.snd) ≫
                          limit.π (Discrete.functor fun b => (fun f => K.obj f.fst.2) b) { as := a } =
                        limit.π (Discrete.functor K.obj) { as := a.fst.1 } ≫ K.map a.snd)
                  (_ :
                    ∀ (a : (p : J × J) × (p.1 ⟶ p.2)),
                      limit.lift (Discrete.functor fun b => (fun f => K.obj f.fst.2) b)
                            (Fan.mk (∏ K.obj) fun f => limit.π (Discrete.functor K.obj) { as := f.fst.2 }) ≫
                          limit.π (Discrete.functor fun b => (fun f => K.obj f.fst.2) b) { as := a } =
                        limit.π (Discrete.functor K.obj) { as := a.fst.2 })
                  (limit.cone (parallelPair s t)))).π.app
          j

Next tactic:
intro j