-- Mathlib/Topology/Covering.lean
theorem isSeparatedMap : IsSeparatedMap f :=
  fun e₁ e₂ he hne ↦ by
    obtain ⟨_, t, he₁⟩ := hf (f e₁)
    have he₂ := he₁; simp_rw [he] at he₂; rw [← t.mem_source] at he₁ he₂
    refine ⟨t.source ∩ (Prod.snd ∘ t) ⁻¹' {(t e₁).2}, t.source ∩ (Prod.snd ∘ t) ⁻¹' {(t e₂).2},
      ?_, ?_, ⟨he₁, rfl⟩, ⟨he₂, rfl⟩, Set.disjoint_left.mpr fun x h₁ h₂ ↦ hne (t.injOn he₁ he₂ ?_)⟩
    iterate 2
      exact t.continuousOn_toFun.isOpen_inter_preimage t.open_source
        (continuous_snd.isOpen_preimage _ <| isOpen_discrete _)
    refine Prod.ext ?_ (h₁.2.symm.trans h₂.2)
    rwa [t.proj_toFun e₁ he₁, t.proj_toFun e₂ he₂]

Proof state:
case intro.intro.refine_1
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
⊢ IsOpen (t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₁).2})

case intro.intro.refine_2
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
⊢ IsOpen (t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₂).2})

case intro.intro.refine_3
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
x : E
h₁ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₁).2}
h₂ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₂).2}
⊢ ↑t.toPartialHomeomorph e₁ = ↑t.toPartialHomeomorph e₂

Tactic:
iterate 2
  exact t.continuousOn_toFun.isOpen_inter_preimage t.open_source
    (continuous_snd.isOpen_preimage _ <| isOpen_discrete _)

Result:
case intro.intro.refine_3
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
x : E
h₁ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₁).2}
h₂ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₂).2}
⊢ ↑t.toPartialHomeomorph e₁ = ↑t.toPartialHomeomorph e₂

Proof state:
case intro.intro
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : f e₁ ∈ t.baseSet
⊢ ∃ s₁ s₂, IsOpen s₁ ∧ IsOpen s₂ ∧ e₁ ∈ s₁ ∧ e₂ ∈ s₂ ∧ Disjoint s₁ s₂

Tactic:
have he₂ := he₁

Result:
case intro.intro
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ he₂ : f e₁ ∈ t.baseSet
⊢ ∃ s₁ s₂, IsOpen s₁ ∧ IsOpen s₂ ∧ e₁ ∈ s₁ ∧ e₂ ∈ s₂ ∧ Disjoint s₁ s₂

Proof state:
case intro.intro.refine_3
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
x : E
h₁ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₁).2}
h₂ : x ∈ t.source ∩ Prod.snd ∘ ↑t ⁻¹' {(↑t e₂).2}
⊢ (↑t.toPartialHomeomorph e₁).1 = (↑t.toPartialHomeomorph e₂).1

Tactic:
rwa [t.proj_toFun e₁ he₁, t.proj_toFun e₂ he₂]

Result:
no goals

Proof state:
case intro.intro
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : f e₁ ∈ t.baseSet
he₂ : f e₂ ∈ t.baseSet
⊢ ∃ s₁ s₂, IsOpen s₁ ∧ IsOpen s₂ ∧ e₁ ∈ s₁ ∧ e₂ ∈ s₂ ∧ Disjoint s₁ s₂

Tactic:
rw [← t.mem_source] at he₁ he₂

Result:
case intro.intro
E : Type u_1
X : Type u_2
inst✝¹ : TopologicalSpace E
inst✝ : TopologicalSpace X
f : E → X
hf : IsCoveringMap f
e₁ e₂ : E
he : f e₁ = f e₂
hne : e₁ ≠ e₂
left✝ : DiscreteTopology ↑(f ⁻¹' {f e₁})
t : Trivialization (↑(f ⁻¹' {f e₁})) f
he₁ : e₁ ∈ t.source
he₂ : e₂ ∈ t.source
⊢ ∃ s₁ s₂, IsOpen s₁ ∧ IsOpen s₂ ∧ e₁ ∈ s₁ ∧ e₂ ∈ s₂ ∧ Disjoint s₁ s₂