set_option maxHeartbeats 300000 in
-- TODO: Generalize to `FunLike` classes,
/-- Lift a monoid with zero homomorphism `R[X] →*₀ G₀` to a `RatFunc R →*₀ G₀`
on the condition that `φ` maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them. -/
def liftMonoidWithZeroHom (φ : R[X] →*₀ G₀) (hφ : R[X]⁰ ≤ G₀⁰.comap φ) : RatFunc R →*₀ G₀ where
  toFun f :=
    RatFunc.liftOn f (fun p q => φ p / φ q) fun {p q p' q'} hq hq' h => by
      cases subsingleton_or_nontrivial R
      · rw [Subsingleton.elim p q, Subsingleton.elim p' q, Subsingleton.elim q' q]
      rw [div_eq_div_iff, ← map_mul, mul_comm p, h, map_mul, mul_comm] <;>
        exact nonZeroDivisors.ne_zero (hφ ‹_›)
  map_one' := by
    dsimp only -- porting note: force the function to be applied
    rw [← ofFractionRing_one, ← Localization.mk_one, liftOn_ofFractionRing_mk]
    simp only [map_one, OneMemClass.coe_one, div_one]
  map_mul' x y := by
    cases' x with x
    cases' y with y
    induction' x using Localization.rec with p q
    

Proof state:
case ofFractionRing.ofFractionRing.f
K : Type u
inst✝⁴ : CommRing K
G₀ : Type u_1
L : Type u_2
R : Type u_3
S : Type u_4
F : Type u_5
inst✝³ : CommGroupWithZero G₀
inst✝² : Field L
inst✝¹ : CommRing R
inst✝ : CommRing S
φ : R[X] →*₀ G₀
hφ : R[X]⁰ ≤ Submonoid.comap φ G₀⁰
y : FractionRing R[X]
p : R[X]
q : ↥R[X]⁰
⊢ ZeroHom.toFun
      {
        toFun := fun f =>
          RatFunc.liftOn f (fun p q => φ p / φ q)
            (_ :
              ∀ {p q p' q' : R[X]},
                q ∈ R[X]⁰ → q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
        map_zero' :=
          (_ :
            (fun f =>
                  RatFunc.liftOn f (fun p q => φ p / φ q)
                    (_ :
                      ∀ {p q p' q' : R[X]},
                        q ∈ R[X]⁰ →
                          q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                0 =
              0) }
      ({ toFractionRing := Localization.mk p q } * { toFractionRing := y }) =
    ZeroHom.toFun
        {
          toFun := fun f =>
            RatFunc.liftOn f (fun p q => φ p / φ q)
              (_ :
                ∀ {p q p' q' : R[X]},
                  q ∈ R[X]⁰ → q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
          map_zero' :=
            (_ :
              (fun f =>
                    RatFunc.liftOn f (fun p q => φ p / φ q)
                      (_ :
                        ∀ {p q p' q' : R[X]},
                          q ∈ R[X]⁰ →
                            q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                  0 =
                0) }
        { toFractionRing := Localization.mk p q } *
      ZeroHom.toFun
        {
          toFun := fun f =>
            RatFunc.liftOn f (fun p q => φ p / φ q)
              (_ :
                ∀ {p q p' q' : R[X]},
                  q ∈ R[X]⁰ → q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
          map_zero' :=
            (_ :
              (fun f =>
                    RatFunc.liftOn f (fun p q => φ p / φ q)
                      (_ :
                        ∀ {p q p' q' : R[X]},
                          q ∈ R[X]⁰ →
                            q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                  0 =
                0) }
        { toFractionRing := y }
case ofFractionRing.ofFractionRing.H
K : Type u
inst✝⁴ : CommRing K
G₀ : Type u_1
L : Type u_2
R : Type u_3
S : Type u_4
F : Type u_5
inst✝³ : CommGroupWithZero G₀
inst✝² : Field L
inst✝¹ : CommRing R
inst✝ : CommRing S
φ : R[X] →*₀ G₀
hφ : R[X]⁰ ≤ Submonoid.comap φ G₀⁰
x y : FractionRing R[X]
a✝ c✝ : R[X]
b✝ d✝ : ↥R[X]⁰
h✝ : (Localization.r R[X]⁰) (a✝, b✝) (c✝, d✝)
⊢ (_ :
      ZeroHom.toFun
          {
            toFun := fun f =>
              RatFunc.liftOn f (fun p q => φ p / φ q)
                (_ :
                  ∀ {p q p' q' : R[X]},
                    q ∈ R[X]⁰ →
                      q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
            map_zero' :=
              (_ :
                (fun f =>
                      RatFunc.liftOn f (fun p q => φ p / φ q)
                        (_ :
                          ∀ {p q p' q' : R[X]},
                            q ∈ R[X]⁰ →
                              q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                    0 =
                  0) }
          ({ toFractionRing := Localization.mk c✝ d✝ } * { toFractionRing := y }) =
        ZeroHom.toFun
            {
              toFun := fun f =>
                RatFunc.liftOn f (fun p q => φ p / φ q)
                  (_ :
                    ∀ {p q p' q' : R[X]},
                      q ∈ R[X]⁰ →
                        q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
              map_zero' :=
                (_ :
                  (fun f =>
                        RatFunc.liftOn f (fun p q => φ p / φ q)
                          (_ :
                            ∀ {p q p' q' : R[X]},
                              q ∈ R[X]⁰ →
                                q' ∈ R[X]⁰ →
                                  q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                      0 =
                    0) }
            { toFractionRing := Localization.mk c✝ d✝ } *
          ZeroHom.toFun
            {
              toFun := fun f =>
                RatFunc.liftOn f (fun p q => φ p / φ q)
                  (_ :
                    ∀ {p q p' q' : R[X]},
                      q ∈ R[X]⁰ →
                        q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
              map_zero' :=
                (_ :
                  (fun f =>
                        RatFunc.liftOn f (fun p q => φ p / φ q)
                          (_ :
                            ∀ {p q p' q' : R[X]},
                              q ∈ R[X]⁰ →
                                q' ∈ R[X]⁰ →
                                  q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                      0 =
                    0) }
            { toFractionRing := y }) =
    (_ :
      ZeroHom.toFun
          {
            toFun := fun f =>
              RatFunc.liftOn f (fun p q => φ p / φ q)
                (_ :
                  ∀ {p q p' q' : R[X]},
                    q ∈ R[X]⁰ →
                      q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
            map_zero' :=
              (_ :
                (fun f =>
                      RatFunc.liftOn f (fun p q => φ p / φ q)
                        (_ :
                          ∀ {p q p' q' : R[X]},
                            q ∈ R[X]⁰ →
                              q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                    0 =
                  0) }
          ({ toFractionRing := Localization.mk c✝ d✝ } * { toFractionRing := y }) =
        ZeroHom.toFun
            {
              toFun := fun f =>
                RatFunc.liftOn f (fun p q => φ p / φ q)
                  (_ :
                    ∀ {p q p' q' : R[X]},
                      q ∈ R[X]⁰ →
                        q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
              map_zero' :=
                (_ :
                  (fun f =>
                        RatFunc.liftOn f (fun p q => φ p / φ q)
                          (_ :
                            ∀ {p q p' q' : R[X]},
                              q ∈ R[X]⁰ →
                                q' ∈ R[X]⁰ →
                                  q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                      0 =
                    0) }
            { toFractionRing := Localization.mk c✝ d✝ } *
          ZeroHom.toFun
            {
              toFun := fun f =>
                RatFunc.liftOn f (fun p q => φ p / φ q)
                  (_ :
                    ∀ {p q p' q' : R[X]},
                      q ∈ R[X]⁰ →
                        q' ∈ R[X]⁰ → q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'),
              map_zero' :=
                (_ :
                  (fun f =>
                        RatFunc.liftOn f (fun p q => φ p / φ q)
                          (_ :
                            ∀ {p q p' q' : R[X]},
                              q ∈ R[X]⁰ →
                                q' ∈ R[X]⁰ →
                                  q' * p = q * p' → (fun p q => φ p / φ q) p q = (fun p q => φ p / φ q) p' q'))
                      0 =
                    0) }
            { toFractionRing := y })

Next tactic:
induction' y using Localization.rec with p' q'