/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    simp? [colimit_eq_iff.{v, v}] at h says
      simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
    let k j := (h j).choose
    let f : ∀ j, kx ⟶ k j := fun j => (h j).choose_spec.choose
    let g : ∀ j, ky ⟶ k j := fun j => (h j).choose_spec.choose_spec.choose
    -- where the images of the components of the representatives become equal:
    have w :
      ∀ j, F.map ((𝟙 j, f j) :
        (j, kx) ⟶ (j, k j)) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
          F.map ((𝟙 j, g j) : (j, ky) ⟶ (j, k j))
            (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y) :=
      fun j => (h j).choose_spec.choose_spec.choose_spec
    -- We now use that `K` is filtered, picking some point to the right of all these
    -- morphisms `f j` and `g j`.
    let O : Finset K := Finset.univ.image k ∪ {kx, ky}
    have kxO : kx ∈ O := Finset.mem_union.mpr (Or.inr (by simp))
    have kyO : ky ∈ O := Finset.mem_union.mpr (Or.inr (by simp))
    have kjO : ∀ j, k j ∈ O := fun j => Finset.mem_union.mpr (Or.inl (by simp))
    let H : Finset (Σ' (X Y : K) (_ : X ∈ O) (_ : Y ∈ O), X ⟶ Y) :=
      (Finset.univ.image fun j : J =>
          ⟨kx, k j, kxO, Finset.mem_union.mpr (Or.inl (by simp)), f j⟩) ∪
        Finset.univ.image fun j : J => ⟨ky, k j, kyO, Finset.mem_union.mpr (Or.inl (by simp)), g j⟩
    obtain ⟨S, T, W⟩ := IsFiltered.sup_exists O H
    have fH : ∀ j, (⟨kx, k j, kxO, kjO j, f j⟩ : Σ' (X Y : K) (_ : X ∈ O) (_ : Y ∈ O), X ⟶ Y) ∈ H :=
      fun j =>
      Finset.mem_union.mpr
        (Or.inl
          (by
            simp only [true_and_iff, Finset.mem_univ, eq_self_iff_true, exists_prop_of_true,
              Finset.mem_image, heq_iff_eq]
            refine' ⟨j, _⟩
            simp only [heq_iff_eq] ))
    have gH :
      ∀ j, (⟨ky, k j, kyO, kjO j, g j⟩ : Σ' (X Y : K) (_ : X ∈ O) (_ : Y ∈ O), X ⟶ Y) ∈ H :=
      fun j =>
      Finset.mem_union.mpr
        (Or.inr
          (by
            simp only [true_and_iff, Finset.mem_univ, eq_self_iff_true, exists_prop_of_true,
              Finset.mem_image, heq_iff_eq]
            refine' ⟨j, _⟩
            simp only [heq_iff_eq]))
    -- Our goal is now an equation between equivalence classes of representatives of a colimit,
    -- and so it suffices to show those representative become equal somewhere, in particular at `S`.
    apply colimit_sound'.{v, v} (T kxO) (T kyO)
    -- We can check if two elements of a limit (in `Type`)
    -- are equal by comparing them componentwise.
    ext j
    -- Now it's just a calculation using `W` and `w`.
    simp only [Functor.comp_map, Limit.map_π_apply, curry_obj_map_app, swap_map]
    rw [← W _ _ (fH j)]
    rw [← W _ _ (gH j)]
    -- porting note: this was `simp [w]` in lean 3; this is presumably a confluence issue
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.w
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    ∃ k f g,
      F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
        F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)
k : J → K :=
  fun j =>
    Exists.choose
      (_ :
        ∃ k f g,
          F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
f : (j : J) → kx ⟶ k j :=
  fun j =>
    Exists.choose
      (_ :
        ∃ f g,
          F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
g : (j : J) → ky ⟶ k j :=
  fun j =>
    Exists.choose
      (_ :
        ∃ g,
          F.map
              (𝟙 j,
                Exists.choose
                  (_ :
                    ∃ f g,
                      F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
                        F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)))
              (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
w :
  ∀ (j : J),
    F.map (𝟙 j, f j) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
      F.map (𝟙 j, g j) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)
O : Finset K := Finset.image k Finset.univ ∪ {kx, ky}
kxO : kx ∈ O
kyO : ky ∈ O
kjO : ∀ (j : J), k j ∈ O
H : Finset ((X : K) ×' (Y : K) ×' (_ : X ∈ O) ×' (_ : Y ∈ O) ×' (X ⟶ Y)) :=
  Finset.image
      (fun j =>
        { fst := kx,
          snd :=
            { fst := k j,
              snd :=
                { fst := kxO, snd := { fst := (_ : k j ∈ Finset.image k Finset.univ ∪ {kx, ky}), snd := f j } } } })
      Finset.univ ∪
    Finset.image
      (fun j =>
        { fst := ky,
          snd :=
            { fst := k j,
              snd :=
                { fst := kyO, snd := { fst := (_ : k j ∈ Finset.image k Finset.univ ∪ {kx, ky}), snd := g j } } } })
      Finset.univ
S : K
T : {X : K} → X ∈ O → (X ⟶ S)
W :
  ∀ {X Y : K} (mX : X ∈ O) (mY : Y ∈ O) {f : X ⟶ Y},
    { fst := X, snd := { fst := Y, snd := { fst := mX, snd := { fst := mY, snd := f } } } } ∈ H → f ≫ T mY = T mX
fH :
  ∀ (j : J),
    { fst := kx, snd := { fst := k j, snd := { fst := kxO, snd := { fst := (_ : k j ∈ O), snd := f j } } } } ∈ H
gH :
  ∀ (j : J),
    { fst := ky, snd := { fst := k j, snd := { fst := kyO, snd := { fst := (_ : k j ∈ O), snd := g j } } } } ∈ H
j : J
⊢ limit.π ((curry.obj (swap K J ⋙ F)).obj S) j (lim.map ((curry.obj (swap K J ⋙ F)).map (f j ≫ T (_ : k j ∈ O))) x) =
    limit.π ((curry.obj (swap K J ⋙ F)).obj S) j (lim.map ((curry.obj (swap K J ⋙ F)).map (g j ≫ T (_ : k j ∈ O))) y)

Next tactic:
rw [lim_map, lim_map, Limit.map_π_apply', Limit.map_π_apply', Functor.map_comp,
      Functor.map_comp, FunctorToTypes.comp, FunctorToTypes.comp, curry_obj_map_app,
      curry_obj_map_app, curry_obj_map_app, Functor.comp_map, Functor.comp_map,
      Functor.comp_map, swap_map, swap_map, swap_map, w]