-- Mathlib/CategoryTheory/Extensive.lean
lemma FinitaryPreExtensive.hasPullbacks_of_is_coproduct [FinitaryPreExtensive C] {ι : Type*}
    [Finite ι] {F : Discrete ι ⥤ C} {c : Cocone F} (hc : IsColimit c) (i : Discrete ι) {X : C}
    (g : X ⟶ _) : HasPullback g (c.ι.app i)

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j := hc.coconePointUniqueUpToIso (getColimitCocone (Discrete.functor f)).isColimit ≪≫ e
⊢ HasPullback g (c.ι.app { as := i })

Tactic:
have : coprod.inl ≫ e'.inv = c.ι.app ⟨i⟩ := by
  simp only [e, e', Iso.trans_inv, coprod.desc_comp, colimit.ι_desc, BinaryCofan.mk_pt,
    BinaryCofan.ι_app_left, BinaryCofan.mk_inl]
  exact colimit.comp_coconePointUniqueUpToIso_inv _ _

Result:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j := hc.coconePointUniqueUpToIso (getColimitCocone (Discrete.functor f)).isColimit ≪≫ e
this : coprod.inl ≫ e'.inv = c.ι.app { as := i }
⊢ HasPullback g (c.ι.app { as := i })

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j
this : coprod.inl ≫ e'.inv = c.ι.app { as := i }
⊢ HasPullback g (coprod.inl ≫ e'.inv)

Tactic:
have : IsPullback (𝟙 _) (g ≫ e'.hom) g e'.inv := IsPullback.of_horiz_isIso ⟨by simp⟩

Result:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j
this✝ : coprod.inl ≫ e'.inv = c.ι.app { as := i }
this : IsPullback (𝟙 X) (g ≫ e'.hom) g e'.inv
⊢ HasPullback g (coprod.inl ≫ e'.inv)

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
F : Discrete ι ⥤ C
c : Cocone F
hc : IsColimit c
i : Discrete ι
X : C
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
f : ι → C := F.obj ∘ Discrete.mk
⊢ ∀ (X Y : Discrete ι) (f_1 : X ⟶ Y), HEq (F.map f_1) ((Discrete.functor f).map f_1)

Tactic:
rintro ⟨i⟩ ⟨j⟩ ⟨⟨rfl : i = j⟩⟩

Result:
case mk.mk.up.up
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
F : Discrete ι ⥤ C
c : Cocone F
hc : IsColimit c
i✝ : Discrete ι
X : C
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i✝
f : ι → C := F.obj ∘ Discrete.mk
i : ι
⊢ HEq (F.map { down := { down := ⋯ } }) ((Discrete.functor f).map { down := { down := ⋯ } })

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j
this : coprod.inl ≫ e'.inv = c.ι.app { as := i }
⊢ 𝟙 X ≫ g = (g ≫ e'.hom) ≫ e'.inv

Tactic:
simp

Result:
no goals

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
i : Discrete ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
⊢ HasPullback g (c.ι.app i)

Tactic:
obtain ⟨i⟩ := i

Result:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
⊢ HasPullback g (c.ι.app { as := i })

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
i : Discrete ι
X : C
f : ι → C
c : Cocone (Discrete.functor f)
hc : IsColimit c
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
⊢ HasPullback g (c.ι.app i)

Tactic:
change Cofan f at c

Result:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
i : Discrete ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
⊢ HasPullback g (c.ι.app i)

Proof state:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j := hc.coconePointUniqueUpToIso (getColimitCocone (Discrete.functor f)).isColimit ≪≫ e
this : coprod.inl ≫ e'.inv = c.ι.app { as := i }
⊢ HasPullback g (c.ι.app { as := i })

Tactic:
clear_value e'

Result:
case mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
X : C
f : ι → C
c : Cofan f
hc : IsColimit c
i : ι
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj { as := i }
e : ∐ f ≅ f i ⨿ ∐ fun j => f ↑j :=
  {
    hom :=
      Sigma.desc fun j => if h : j = i then eqToHom ⋯ ≫ coprod.inl else Sigma.ι (fun j => f ↑j) ⟨j, h⟩ ≫ coprod.inr,
    inv := coprod.desc (Sigma.ι f i) (Sigma.desc fun j => Sigma.ι f ↑j), hom_inv_id := ⋯, inv_hom_id := ⋯ }
e' : c.pt ≅ f i ⨿ ∐ fun j => f ↑j
this : coprod.inl ≫ e'.inv = c.ι.app { as := i }
⊢ HasPullback g (c.ι.app { as := i })

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
F : Discrete ι ⥤ C
c : Cocone F
hc : IsColimit c
i : Discrete ι
X : C
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
f : ι → C := F.obj ∘ Discrete.mk
this : F = Discrete.functor f
⊢ HasPullback g (c.ι.app i)

Tactic:
clear_value f

Result:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
ι : Type u_1
inst✝ : Finite ι
F : Discrete ι ⥤ C
c : Cocone F
hc : IsColimit c
i : Discrete ι
X : C
g : X ⟶ ((Functor.const (Discrete ι)).obj c.pt).obj i
f : ι → C
this : F = Discrete.functor f
⊢ HasPullback g (c.ι.app i)