theorem affineLocally_stableUnderComposition : (affineLocally @P).StableUnderComposition := by
  intro X Y S f g hf hg
  let 𝒰 : ∀ i, ((S.affineCover.pullbackCover (f ≫ g)).obj i).OpenCover := by
    intro i
    refine' Scheme.OpenCover.bind _ fun i => Scheme.affineCover _
    apply Scheme.OpenCover.pushforwardIso _
      (pullbackRightPullbackFstIso g (S.affineCover.map i) f).hom
    apply Scheme.Pullback.openCoverOfRight
    exact (pullback g (S.affineCover.map i)).affineCover
  -- Porting note: used to be - rw [hP.affine_openCover_iff (f ≫ g) S.affineCover _] - but
  -- metavariables cause problems in the instance search
  apply (@affine_openCover_iff _ hP _ _ (f ≫ g) S.affineCover _ ?_ ?_).mpr
  rotate_left
  · exact 𝒰
  · intro i j; dsimp at *; infer_instance
  · rintro i ⟨j, k⟩
    dsimp at i j k
    dsimp only [Scheme.OpenCover.bind_map, Scheme.OpenCover.pushforwardIso_obj,
      Scheme.Pullback.openCoverOfRight_obj, Scheme.OpenCover.pushforwardIso_map,
      Scheme.Pullback.openCoverOfRight_map, Scheme.OpenCover.bind_obj]
    rw [Category.assoc, Category.assoc, pullbackRightPullbackFstIso_hom_snd,
      pullback.lift_snd_assoc, Category.assoc, ← Category.assoc, op_comp, Functor.map_comp]
    apply hP.StableUnderComposition
    · -- Porting note: used to be exact _|>. hg i j but that can't find an instance
      apply hP.affine_openCover_iff _ _ _|>.mp
      exact hg
    · delta affineLocally at hf
      -- Porting note: again strange behavior of TFAE
      have := (hP.isLocal_sourceAffineLocally.affine_openCover_TFAE f).out 0 3
      rw [this] at hf
      -- Porting note: needed to help Lean with this instance (same as above)
      

Proof state:
case mk.x
P : {R S : Type u} → [inst : CommRing R] → [inst_1 : CommRing S] → (R →+* S) → Prop
hP : PropertyIsLocal P
X Y S : Scheme
f : X ⟶ Y
g : Y ⟶ S
hf : ∀ {U : Scheme} (g : U ⟶ Y) [inst : IsAffine U] [inst_1 : IsOpenImmersion g], sourceAffineLocally P pullback.snd
hg : affineLocally P g
𝒰 : (i : (Scheme.OpenCover.pullbackCover (Scheme.affineCover S) (f ≫ g)).J) →
  Scheme.OpenCover (Scheme.OpenCover.obj (Scheme.OpenCover.pullbackCover (Scheme.affineCover S) (f ≫ g)) i) :=
  fun i =>
    Scheme.OpenCover.bind
      (Scheme.OpenCover.pushforwardIso
        (Scheme.Pullback.openCoverOfRight
          (Scheme.affineCover (pullback g (Scheme.OpenCover.map (Scheme.affineCover S) i))) f pullback.fst)
        (pullbackRightPullbackFstIso g (Scheme.OpenCover.map (Scheme.affineCover S) i) f).hom)
      fun i_1 =>
      Scheme.affineCover
        (Scheme.OpenCover.obj
          (Scheme.OpenCover.pushforwardIso
            (Scheme.Pullback.openCoverOfRight
              (Scheme.affineCover (pullback g (Scheme.OpenCover.map (Scheme.affineCover S) i))) f pullback.fst)
            (pullbackRightPullbackFstIso g (Scheme.OpenCover.map (Scheme.affineCover S) i) f).hom)
          i_1)
i : (Scheme.affineCover S).J
j : (Scheme.affineCover (pullback g (Scheme.OpenCover.map (Scheme.affineCover S) i))).J
k :
  (Scheme.affineCover
      (pullback f
        (Scheme.OpenCover.map (Scheme.affineCover (pullback g (Scheme.OpenCover.map (Scheme.affineCover S) i))) j ≫
          pullback.fst))).J
this :
  targetAffineLocally (sourceAffineLocally P) f ↔
    ∀ {U : Scheme} (g : U ⟶ Y) [inst : IsAffine U] [inst_1 : IsOpenImmersion g], sourceAffineLocally P pullback.snd
⊢ P
    (Scheme.Γ.map
      (Scheme.OpenCover.map
            (Scheme.affineCover
              (pullback f
                (Scheme.OpenCover.map (Scheme.affineCover (pullback g (Scheme.OpenCover.map (Scheme.affineCover S) i)))
                    j ≫
                  pullback.fst)))
            k ≫
          pullback.snd).op)

Next tactic:
have : IsOpenImmersion <|
          ((pullback g (S.affineCover.map i)).affineCover.map j ≫ pullback.fst) :=
        LocallyRingedSpace.IsOpenImmersion.comp _ _