/-- If `A : S → T.obj B` is a structured arrow for `S : D` and `T : C ⥤ D`, then we can explicitly
    describe the subobjects of `A` as the subobjects `P` of `B` in `C` for which `A.hom` factors
    through the image of `P` under `T`. -/
@[simps!]
def subobjectEquiv [HasLimits C] [PreservesLimits T] (A : StructuredArrow S T) :
    Subobject A ≃o { P : Subobject A.right // ∃ q, q ≫ T.map P.arrow = A.hom } where
  toFun P := ⟨projectSubobject P, projectSubobject_factors P⟩
  invFun P := liftSubobject P.val P.prop.choose_spec
  left_inv P := lift_projectSubobject _ _
  right_inv P := Subtype.ext (by simp only [liftSubobject, homMk_right, projectSubobject_mk,
      Subobject.mk_arrow, Subtype.coe_eta])
  map_rel_iff' := by
    apply Subobject.ind₂
    intro P Q f g hf hg
    refine' ⟨fun h => Subobject.mk_le_mk_of_comm _ _, fun h => _⟩
    · exact homMk (Subobject.ofMkLEMk _ _ h)
        ((cancel_mono (T.map g.right)).1 (by simp [← T.map_comp]))
    · aesop_cat
    · 

Proof state:
case h.refine'_3
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : D
T : C ⥤ D
inst✝¹ : HasLimits C
inst✝ : PreservesLimits T
A P Q : StructuredArrow S T
f : P ⟶ A
g : Q ⟶ A
hf : Mono f
hg : Mono g
h : Subobject.mk f ≤ Subobject.mk g
⊢ {
        toFun := fun P =>
          { val := projectSubobject P,
            property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) },
        invFun := fun P =>
          liftSubobject ↑P
            (_ : Exists.choose (_ : ∃ q, q ≫ T.map (Subobject.arrow ↑P) = A.hom) ≫ T.map (Subobject.arrow ↑P) = A.hom),
        left_inv :=
          (_ :
            ∀ (P : Subobject A),
              liftSubobject (projectSubobject P)
                  (_ :
                    Exists.choose
                          (_ :
                            ∃ q,
                              q ≫
                                  T.map
                                    (Subobject.arrow
                                      ↑((fun P =>
                                            { val := projectSubobject P,
                                              property :=
                                                (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                                          P)) =
                                A.hom) ≫
                        T.map
                          (Subobject.arrow
                            ↑((fun P =>
                                  { val := projectSubobject P,
                                    property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                                P)) =
                      A.hom) =
                P),
        right_inv :=
          (_ :
            ∀ (P : { P // ∃ q, q ≫ T.map (Subobject.arrow P) = A.hom }),
              (fun P =>
                    { val := projectSubobject P,
                      property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                  ((fun P =>
                      liftSubobject ↑P
                        (_ :
                          Exists.choose (_ : ∃ q, q ≫ T.map (Subobject.arrow ↑P) = A.hom) ≫ T.map (Subobject.arrow ↑P) =
                            A.hom))
                    P) =
                P) }
      (Subobject.mk f) ≤
    {
        toFun := fun P =>
          { val := projectSubobject P,
            property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) },
        invFun := fun P =>
          liftSubobject ↑P
            (_ : Exists.choose (_ : ∃ q, q ≫ T.map (Subobject.arrow ↑P) = A.hom) ≫ T.map (Subobject.arrow ↑P) = A.hom),
        left_inv :=
          (_ :
            ∀ (P : Subobject A),
              liftSubobject (projectSubobject P)
                  (_ :
                    Exists.choose
                          (_ :
                            ∃ q,
                              q ≫
                                  T.map
                                    (Subobject.arrow
                                      ↑((fun P =>
                                            { val := projectSubobject P,
                                              property :=
                                                (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                                          P)) =
                                A.hom) ≫
                        T.map
                          (Subobject.arrow
                            ↑((fun P =>
                                  { val := projectSubobject P,
                                    property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                                P)) =
                      A.hom) =
                P),
        right_inv :=
          (_ :
            ∀ (P : { P // ∃ q, q ≫ T.map (Subobject.arrow P) = A.hom }),
              (fun P =>
                    { val := projectSubobject P,
                      property := (_ : ∃ q, q ≫ T.map (Subobject.arrow (projectSubobject P)) = A.hom) })
                  ((fun P =>
                      liftSubobject ↑P
                        (_ :
                          Exists.choose (_ : ∃ q, q ≫ T.map (Subobject.arrow ↑P) = A.hom) ≫ T.map (Subobject.arrow ↑P) =
                            A.hom))
                    P) =
                P) }
      (Subobject.mk g)

Next tactic:
refine' Subobject.mk_le_mk_of_comm (Subobject.ofMkLEMk _ _ h).right _