/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
    -- `k : J ⟶ K` records where the representative of the
    -- element in the `j`-th element of `x` lives
    let k : J → K := fun j => (z j).choose
    -- `y j : F.obj (j, k j)` is the representative
    let y : ∀ j, F.obj (j, k j) := fun j => (z j).choose_spec.choose
    -- and we record that these representatives, when mapped back into the relevant colimits,
    -- are actually the components of `x`.
    have e : ∀ j,
        colimit.ι ((curry.obj F).obj j) (k j) (y j) = limit.π (curry.obj F ⋙ Limits.colim) j x :=
      fun j => (z j).choose_spec.choose_spec
    clear_value k y
    -- A little tidying up of things we no longer need.
    clear z
    -- As a first step, we use that `K` is filtered to pick some point `k' : K` above all the `k j`
    let k' : K := IsFiltered.sup (Finset.univ.image k) ∅
    -- and name the morphisms as `g j : k j ⟶ k'`.
    have g : ∀ j, k j ⟶ k' := fun j => IsFiltered.toSup (Finset.univ.image k) ∅ (by simp)
    clear_value k'
    -- Recalling that the components of `x`, which are indexed by `j : J`, are "coherent",
    -- in other words preserved by morphisms in the `J` direction,
    -- we see that for any morphism `f : j ⟶ j'` in `J`,
    -- the images of `y j` and `y j'`, when mapped to `F.obj (j', k')` respectively by
    -- `(f, g j)` and `(𝟙 j', g j')`, both represent the same element in the colimit.
    have w :
      ∀ {j j' : J} (f : j ⟶ j'),
        colimit.ι ((curry.obj F).obj j') k' (F.map ((𝟙 j', g j') : (j', k j') ⟶ (j', k')) (y j')) =
          colimit.ι ((curry.obj F).obj j') k' (F.map ((f, g j) : (j, k j) ⟶ (j', k')) (y j)) := by
      intro j j' f
      have t : (f, g j) =
          (((f, 𝟙 (k j)) : (j, k j) ⟶ (j', k j)) ≫ (𝟙 j', g j) : (j, k j) ⟶ (j', k')) := by
        simp only [id_comp, comp_id, prod_comp]
      erw [Colimit.w_apply', t, FunctorToTypes.map_comp_apply, Colimit.w_apply', e, ←
        Limit.w_apply' f, ← e]
      simp
    -- Because `K` is filtered, we can restate this as saying that
    -- for each such `f`, there is some place to the right of `k'`
    -- where these images of `y j` and `y j'` become equal.
    simp_rw [colimit_eq_iff.{v, v}] at w
    -- We take a moment to restate `w` more conveniently.
    let kf : ∀ {j j'} (_ : j ⟶ j'), K := fun f => (w f).choose
    let gf : ∀ {j j'} (f : j ⟶ j'), k' ⟶ kf f := fun f => (w f).choose_spec.choose
    let hf : ∀ {j j'} (f : j ⟶ j'), k' ⟶ kf f := fun f =>
      (w f).choose_spec.choose_spec.choose
    have wf :
      ∀ {j j'} (f : j ⟶ j'),
        F.map ((𝟙 j', g j' ≫ gf f) : (j', k j') ⟶ (j', kf f)) (y j') =
          F.map ((f, g j ≫ hf f) : (j, k j) ⟶ (j', kf f)) (y j) :=
      fun {j j'} f => by
      have q :
        ((curry.obj F).obj j').map (gf f) (F.map ((𝟙 j', g j') : (j', k j') ⟶ (j', k')) (y j')) =
          ((curry.obj F).obj j').map (hf f) (F.map ((f, g j) : (j, k j) ⟶ (j', k')) (y j)) :=
        (w f).choose_spec.choose_spec.choose_spec
      rw [curry_obj_obj_map, curry_obj_obj_map] at q
      -- porting note: Lean 4 `dsimp` unfolds `gf` and `hf` in `q` :-(
      -- See discussion at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.60dsimp.60.20unfolding.20local.20lets
      

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
k : J → K
y : (j : J) → F.obj (j, k j)
e : ∀ (j : J), colimit.ι ((curry.obj F).obj j) (k j) (y j) = limit.π (curry.obj F ⋙ colim) j x
k' : K
g : (j : J) → k j ⟶ k'
w :
  ∀ {j j' : J} (f : j ⟶ j'),
    ∃ k_1 f_1 g_1,
      ((curry.obj F).obj j').map f_1 (F.map (𝟙 j', g j') (y j')) = ((curry.obj F).obj j').map g_1 (F.map (f, g j) (y j))
kf : {j j' : J} → (j ⟶ j') → K :=
  fun {j j'} f =>
    Exists.choose
      (_ :
        ∃ k_1 f_1 g_1,
          ((curry.obj F).obj j').map f_1 (F.map (𝟙 j', g j') (y j')) =
            ((curry.obj F).obj j').map g_1 (F.map (f, g j) (y j)))
gf : {j j' : J} → (f : j ⟶ j') → k' ⟶ kf f :=
  fun {j j'} f =>
    Exists.choose
      (_ :
        ∃ f_1 g_1,
          ((curry.obj F).obj j').map f_1 (F.map (𝟙 j', g j') (y j')) =
            ((curry.obj F).obj j').map g_1 (F.map (f, g j) (y j)))
hf : {j j' : J} → (f : j ⟶ j') → k' ⟶ kf f :=
  fun {j j'} f =>
    Exists.choose
      (_ :
        ∃ g_1,
          ((curry.obj F).obj j').map
              (Exists.choose
                (_ :
                  ∃ f_1 g_2,
                    ((curry.obj F).obj j').map f_1 (F.map (𝟙 j', g j') (y j')) =
                      ((curry.obj F).obj j').map g_2 (F.map (f, g j) (y j))))
              (F.map (𝟙 j', g j') (y j')) =
            ((curry.obj F).obj j').map g_1 (F.map (f, g j) (y j)))
j j' : J
f : j ⟶ j'
q : F.map (𝟙 j', gf f) (F.map (𝟙 j', g j') (y j')) = F.map (𝟙 j', hf f) (F.map (f, g j) (y j))
⊢ F.map (𝟙 j', g j' ≫ gf f) (y j') = F.map (f, g j ≫ hf f) (y j)

Next tactic:
simp_rw [← FunctorToTypes.map_comp_apply, CategoryStruct.comp] at q