/-- 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
    · 

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
⊢ 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)) ≅
    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)))

Next tactic:
refine Cones.ext (Iso.refl _) ?_