-- Mathlib/Topology/Bases.lean
theorem IsSeparable.univ_pi {ι : Type*} [Countable ι] {X : ι → Type*} {s : ∀ i, Set (X i)}
    [∀ i, TopologicalSpace (X i)] (h : ∀ i, IsSeparable (s i)) :
    IsSeparable (univ.pi s)

Proof state:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
⊢ IsSeparable (univ.pi s)

Tactic:
refine ⟨range g, countable_range g, fun f hf ↦ mem_closure_iff.2 fun o ho hfo ↦ ?_⟩

Result:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f : (i : ι) → X i
hf : f ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f ∈ o
⊢ (o ∩ range g).Nonempty

Proof state:
case inl
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
he : univ.pi s = ∅
⊢ IsSeparable (univ.pi s)

Tactic:
rw [he]

Result:
case inl
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
he : univ.pi s = ∅
⊢ IsSeparable ∅

Proof state:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
⊢ IsSeparable (univ.pi s)

Tactic:
set g : (I : Finset ι) × ((i : I) → c i) → (i : ι) → X i := fun ⟨I, f⟩ i ↦
  if hi : i ∈ I then f ⟨i, hi⟩ else f₀ i

Result:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
⊢ IsSeparable (univ.pi s)

Proof state:
case inr.intro.intro.intro.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f : (i : ι) → X i
hf : f ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f ∈ o
I : Finset ι
u : (a : ι) → Set (X a)
huo : ∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a
hI : (↑I).pi u ⊆ o
⊢ (o ∩ range g).Nonempty

Tactic:
rsuffices ⟨f, hf⟩ : ∃ f : (i : I) → c i, g ⟨I, f⟩ ∈ Set.pi I u

Result:
case inr.intro.intro.intro.intro.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f✝ : (i : ι) → X i
hf✝ : f✝ ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f✝ ∈ o
I : Finset ι
u : (a : ι) → Set (X a)
huo : ∀ a ∈ I, IsOpen (u a) ∧ f✝ a ∈ u a
hI : (↑I).pi u ⊆ o
f : (i : { x // x ∈ I }) → ↑(c ↑i)
hf : g ⟨I, f⟩ ∈ (↑I).pi u
⊢ (o ∩ range g).Nonempty

ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f : (i : ι) → X i
hf : f ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f ∈ o
I : Finset ι
u : (a : ι) → Set (X a)
huo : ∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a
hI : (↑I).pi u ⊆ o
⊢ ∃ f, g ⟨I, f⟩ ∈ (↑I).pi u

Proof state:
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
⊢ IsSeparable (univ.pi s)

Tactic:
rcases eq_empty_or_nonempty (univ.pi s) with he | ⟨f₀, -⟩

Result:
case inl
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
he : univ.pi s = ∅
⊢ IsSeparable (univ.pi s)

case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
f₀ : (i : ι) → X i
⊢ IsSeparable (univ.pi s)

Proof state:
case inl
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
he : univ.pi s = ∅
⊢ IsSeparable ∅

Tactic:
exact countable_empty.isSeparable

Result:
no goals

Proof state:
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f : (i : ι) → X i
hf : f ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f ∈ o
I : Finset ι
u : (a : ι) → Set (X a)
huo : ∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a
hI : (↑I).pi u ⊆ o
⊢ ∀ i ∈ I, (u i ∩ c i).Nonempty

Tactic:
intro i hi

Result:
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
this : ∀ (i : ι), Countable ↑(c i)
g : (I : Finset ι) × ((i : { x // x ∈ I }) → ↑(c ↑i)) → (i : ι) → X i :=
  fun x i =>
    match x with
    | ⟨I, f⟩ => if hi : i ∈ I then ↑(f ⟨i, hi⟩) else f₀ i
f : (i : ι) → X i
hf : f ∈ univ.pi s
o : Set ((i : ι) → X i)
ho : IsOpen o
hfo : f ∈ o
I : Finset ι
u : (a : ι) → Set (X a)
huo : ∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a
hI : (↑I).pi u ⊆ o
i : ι
hi : i ∈ I
⊢ (u i ∩ c i).Nonempty

Proof state:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
h : ∀ (i : ι), IsSeparable (s i)
f₀ : (i : ι) → X i
⊢ IsSeparable (univ.pi s)

Tactic:
choose c c_count hc using h

Result:
case inr.intro
ι : Type u_2
inst✝¹ : Countable ι
X : ι → Type u_3
s : (i : ι) → Set (X i)
inst✝ : (i : ι) → TopologicalSpace (X i)
f₀ : (i : ι) → X i
c : (i : ι) → Set (X i)
c_count : ∀ (i : ι), (c i).Countable
hc : ∀ (i : ι), s i ⊆ closure (c i)
⊢ IsSeparable (univ.pi s)