theorem DiscreteValuationRing.TFAE [IsNoetherianRing R] [LocalRing R] [IsDomain R]
    (h : ¬IsField R) :
    List.TFAE
      [DiscreteValuationRing R, ValuationRing R, IsDedekindDomain R,
        IsIntegrallyClosed R ∧ ∃! P : Ideal R, P ≠ ⊥ ∧ P.IsPrime, (maximalIdeal R).IsPrincipal,
        FiniteDimensional.finrank (ResidueField R) (CotangentSpace R) = 1,
        ∀ (I) (_ : I ≠ ⊥), ∃ n : ℕ, I = maximalIdeal R ^ n] := by
  have ne_bot := Ring.ne_bot_of_isMaximal_of_not_isField (maximalIdeal.isMaximal R) h
  

Proof state:
R : Type u_1
inst✝⁶ : CommRing R
K : Type u_2
inst✝⁵ : Field K
inst✝⁴ : Algebra R K
inst✝³ : IsFractionRing R K
inst✝² : IsNoetherianRing R
inst✝¹ : LocalRing R
inst✝ : IsDomain R
h : ¬IsField R
ne_bot : maximalIdeal R ≠ ⊥
⊢ List.TFAE
    [DiscreteValuationRing R, ValuationRing R, IsDedekindDomain R, IsIntegrallyClosed R ∧ ∃! P, P ≠ ⊥ ∧ Ideal.IsPrime P,
      Submodule.IsPrincipal (maximalIdeal R), FiniteDimensional.finrank (ResidueField R) (CotangentSpace R) = 1,
      ∀ (I : Ideal R), I ≠ ⊥ → ∃ n, I = maximalIdeal R ^ n]

Next tactic:
classical
  rw [finrank_eq_one_iff']
  tfae_have 1 → 2
  · intro; infer_instance
  tfae_have 2 → 1
  · intro
    haveI := IsBezout.toGCDDomain R
    haveI : UniqueFactorizationMonoid R := ufm_of_gcd_of_wfDvdMonoid
    apply DiscreteValuationRing.of_ufd_of_unique_irreducible
    · obtain ⟨x, hx₁, hx₂⟩ := Ring.exists_not_isUnit_of_not_isField h
      obtain ⟨p, hp₁, -⟩ := WfDvdMonoid.exists_irreducible_factor hx₂ hx₁
      exact ⟨p, hp₁⟩
    · exact ValuationRing.unique_irreducible
  tfae_have 1 → 4
  · intro H
    exact ⟨inferInstance, ((DiscreteValuationRing.iff_pid_with_one_nonzero_prime R).mp H).2⟩
  tfae_have 4 → 3
  · rintro ⟨h₁, h₂⟩;
    exact { h₁ with
      maximalOfPrime := fun hI hI' => ExistsUnique.unique h₂ ⟨ne_bot, inferInstance⟩ ⟨hI, hI'⟩ ▸
        maximalIdeal.isMaximal R, }
  tfae_have 3 → 5
  · intro h; exact maximalIdeal_isPrincipal_of_isDedekindDomain R
  tfae_have 5 → 6
  · rintro ⟨x, hx⟩
    have : x ∈ maximalIdeal R := by rw [hx]; exact Submodule.subset_span (Set.mem_singleton x)
    let x' : maximalIdeal R := ⟨x, this⟩
    use Submodule.Quotient.mk x'
    constructor
    swap
    · intro e
      rw [Submodule.Quotient.mk_eq_zero] at e
      apply Ring.ne_bot_of_isMaximal_of_not_isField (maximalIdeal.isMaximal R) h
      apply Submodule.eq_bot_of_le_smul_of_le_jacobson_bot (maximalIdeal R)
      · exact ⟨{x}, (Finset.coe_singleton x).symm ▸ hx.symm⟩
      · conv_lhs => rw [hx]
        rw [Submodule.mem_smul_top_iff] at e
        rwa [Submodule.span_le, Set.singleton_subset_iff]
      · rw [LocalRing.jacobson_eq_maximalIdeal (⊥ : Ideal R) bot_ne_top]
    · refine' fun w => Quotient.inductionOn' w fun y => _
      obtain ⟨y, hy⟩ := y
      rw [hx, Submodule.mem_span_singleton] at hy
      obtain ⟨a, rfl⟩ := hy
      exact ⟨Ideal.Quotient.mk _ a, rfl⟩
  tfae_have 6 → 5
  · rintro ⟨x, hx, hx'⟩
    induction x using Quotient.inductionOn' with | h x => ?_
    use x
    apply le_antisymm
    swap; · rw [Submodule.span_le, Set.singleton_subset_iff]; exact x.prop
    have h₁ :
      (Ideal.span {(x : R)} : Ideal R) ⊔ maximalIdeal R ≤
        Ideal.span {(x : R)} ⊔ maximalIdeal R • maximalIdeal R := by
      refine' sup_le le_sup_left _
      rintro m hm
      obtain ⟨c, hc⟩ := hx' (Submodule.Quotient.mk ⟨m, hm⟩)
      induction c using Quotient.inductionOn' with | h c => ?_
      rw [← sub_sub_cancel (c * x) m]
      apply sub_mem _ _
      · refine' Ideal.mem_sup_left (Ideal.mem_span_singleton'.mpr ⟨c, rfl⟩)
      · have := (Submodule.Quotient.eq _).mp hc
        rw [Submodule.mem_smul_top_iff] at this
        exact Ideal.mem_sup_right this
    have h₂ : maximalIdeal R ≤ (⊥ : Ideal R).jacobson := by
      rw [LocalRing.jacobson_eq_maximalIdeal]
      exact bot_ne_top
    have :=
      Submodule.sup_smul_eq_sup_smul_of_le_smul_of_le_jacobson (IsNoetherian.noetherian _) h₂ h₁
    rw [Submodule.bot_smul, sup_bot_eq] at this
    rw [← sup_eq_left, eq_comm]
    exact le_sup_left.antisymm (h₁.trans <| le_of_eq this)
  tfae_have 5 → 7
  · exact exists_maximalIdeal_pow_eq_of_principal R h
  tfae_have 7 → 2
  · rw [ValuationRing.iff_ideal_total]
    intro H
    constructor
    intro I J
    -- `by_cases` should invoke `classical` by itself if it can't find a `Decidable` instance,
    -- however the `tfae` hypotheses trigger a looping instance search.
    -- See also:
    -- https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/.60by_cases.60.20trying.20to.20find.20a.20weird.20instance
    -- As a workaround, add the desired instance ourselves.
    let _ := Classical.decEq (Ideal R)
    by_cases hI : I = ⊥; · subst hI; left; exact bot_le
    by_cases hJ : J = ⊥; · subst hJ; right; exact bot_le
    obtain ⟨n, rfl⟩ := H I hI
    obtain ⟨m, rfl⟩ := H J hJ
    rcases le_total m n with h' | h'
    · left; exact Ideal.pow_le_pow_right h'
    · right; exact Ideal.pow_le_pow_right h'
  tfae_finish