Issue:
[UNEXPECTED BEHAVIOR] DFUKS to_rhf() will get DF removed

**Describe the unexpected behavior**
```
>>> from pyscf import gto
>>> mol = gto.M(atom='He .0 .0 .0', spin=2).build()
>>> mf = mol.UKS().density_fit()
>>> mf1 = mf.to_rks()
>>> mf1
<pyscf.df.df_jk.DFROKS object at 0x2b1997d0c6a0>
>>> mf1 = mf.to_rhf()
>>> mf1
<pyscf.scf.rohf.ROHF object at 0x2b188ebc9c00>
```
Applying `to_rks` on a DFUKS object is fine, but `to_rhf` will get the DF lost. 
I guess `to_rhf` should align its behavior with `to_rks`, i.e. returning DFROHF/DFRHF.
Probably something is wrong in `to_hf` function.

**Version and hardware (please complete the following information):**
- PySCF version commit bee0ce288a655105e27fcb0293b203939b7aecc9
- PySCF install type, built from source




Fix patch:
diff --git a/pyscf/lib/misc.py b/pyscf/lib/misc.py
index 2f19f44507..0c15266b8c 100644
--- a/pyscf/lib/misc.py
+++ b/pyscf/lib/misc.py
@@ -870,10 +870,7 @@ def fn(obj, *args, **kwargs):
     fn.__name__ = name
     return fn
 
-@functools.lru_cache(None)
-def _define_class(name, bases):
-    return type(name, bases, {})
-
+_registered_classes = {}
 def make_class(bases, name=None, attrs=None):
     '''
     Construct a class
@@ -883,14 +880,17 @@ def make_class(bases, name=None, attrs=None):
         class {name}(*bases):
             __dict__ = attrs
     '''
+    _registered_classes
     if name is None:
         name = ''.join(getattr(x, '__name_mixin__', x.__name__) for x in bases)
 
-    cls = _define_class(name, bases)
-    cls.__name_mixin__ = name
-    if attrs is not None:
-        for key, val in attrs.items():
-            setattr(cls, key, val)
+    cls = _registered_classes.get((name, bases))
+    if cls is None:
+        if attrs is None:
+            attrs = {}
+        cls = type(name, bases, attrs)
+        cls.__name_mixin__ = name
+        _registered_classes[name, bases] = cls
     return cls
 
 def set_class(obj, bases, name=None, attrs=None):
@@ -929,7 +929,8 @@ def drop_class(cls, base_cls, name_mixin=None):
 
     # rebuild the dynamic_mixin class
     attrs = {**cls.__dict__, '__name_mixin__': cls_name}
-    cls_undressed = type(cls_name, tuple(filter_bases), attrs)
+    cls_undressed = make_class(tuple(filter_bases), cls_name, attrs)
+    cls_undressed.__module__ = cls.__module__
     return cls_undressed
 
 def replace_class(cls, old_cls, new_cls):
@@ -951,7 +952,9 @@ def replace_class(cls, old_cls, new_cls):
 
     name = cls.__name__.replace(old_cls.__name__, new_cls.__name__)
     attrs = {**cls.__dict__, '__name_mixin__': name}
-    return type(name, tuple(bases), attrs)
+    _cls = make_class(tuple(bases), name, attrs)
+    _cls.__module__ = cls.__module__
+    return _cls
 
 def overwrite_mro(obj, mro):
     '''A hacky function to overwrite the __mro__ attribute'''
diff --git a/pyscf/scf/hf.py b/pyscf/scf/hf.py
index a4fef8e9ed..85264174ec 100644
--- a/pyscf/scf/hf.py
+++ b/pyscf/scf/hf.py
@@ -2303,6 +2303,13 @@ def _transfer_attrs_(self, dst):
         '''This helper function transfers attributes from one SCF object to
         another SCF object. It is invoked by to_ks and to_hf methods.
         '''
+        from pyscf.df.df_jk import _DFHF
+        if isinstance(self, _DFHF) and not hasattr(dst, 'with_df'):
+            # * Handle DF_SCF instances for to_xxx methods.
+            # * Only the molecular SCF methods need to be explicitly converted.
+            #   For PBC SCF methods, DF is enabled by default. calling density_fit()
+            #   may alter the DF class. Conversion should be avoided here.
+            dst = dst.density_fit(auxbasis=self.with_df.auxbasis)
         # Search for all tracked attributes, including those in base classes
         cls_keys = [getattr(cls, '_keys', ()) for cls in dst.__class__.__mro__[:-1]]
         dst_keys = set(dst.__dict__).union(*cls_keys)


Test patch:
diff --git a/pyscf/dft/test/test_h2o.py b/pyscf/dft/test/test_h2o.py
index 8b00096095..585239bdb6 100644
--- a/pyscf/dft/test/test_h2o.py
+++ b/pyscf/dft/test/test_h2o.py
@@ -18,6 +18,7 @@
 from pyscf import gto
 from pyscf import lib
 from pyscf import dft
+from pyscf import scf
 try:
     from pyscf.dispersion import dftd3, dftd4
 except ImportError:
@@ -639,6 +640,88 @@ def test_init(self):
         self.assertTrue(isinstance(mol_u.DKS(), dft.dks.UDKS))
         #TODO: self.assertTrue(isinstance(dft.X2C(mol_r), x2c.dft.UKS))
 
+    def test_to_hf(self):
+        self.assertEqual(dft.RKS(h2o).to_rhf().__class__, scf.rhf.RHF)
+        self.assertEqual(dft.RKS(h2o).to_uhf().__class__, scf.uhf.UHF)
+        self.assertEqual(dft.RKS(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(dft.RKS(h2o).to_hf() .__class__, scf.rhf.RHF)
+        self.assertEqual(dft.RKS(h2o).to_rks().__class__, dft.rks.RKS)
+        self.assertEqual(dft.RKS(h2o).to_uks().__class__, dft.uks.UKS)
+        self.assertEqual(dft.RKS(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(dft.UKS(h2o).to_rhf().__class__, scf.rhf.RHF)
+        self.assertEqual(dft.UKS(h2o).to_uhf().__class__, scf.uhf.UHF)
+        self.assertEqual(dft.UKS(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(dft.UKS(h2o).to_hf() .__class__, scf.uhf.UHF)
+        self.assertEqual(dft.UKS(h2o).to_rks().__class__, dft.rks.RKS)
+        self.assertEqual(dft.UKS(h2o).to_uks().__class__, dft.uks.UKS)
+        self.assertEqual(dft.UKS(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(dft.GKS(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(dft.GKS(h2o).to_hf() .__class__, scf.ghf.GHF)
+        self.assertEqual(dft.GKS(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(dft.RKS(h2o).density_fit().to_rhf().__class__, scf.rhf.RHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_uhf().__class__, scf.uhf.UHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_hf() .__class__, scf.rhf.RHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_rks().__class__, dft.rks.RKS(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_uks().__class__, dft.uks.UKS(h2o).density_fit().__class__)
+        self.assertEqual(dft.RKS(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
+        self.assertEqual(dft.UKS(h2o).density_fit().to_rhf().__class__, scf.rhf.RHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_uhf().__class__, scf.uhf.UHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_hf() .__class__, scf.uhf.UHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_rks().__class__, dft.rks.RKS(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_uks().__class__, dft.uks.UKS(h2o).density_fit().__class__)
+        self.assertEqual(dft.UKS(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
+        self.assertEqual(dft.GKS(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.GKS(h2o).density_fit().to_hf() .__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(dft.GKS(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
+    def test_to_ks(self):
+        self.assertEqual(scf.RHF(h2o).to_rhf().__class__, scf.rhf.RHF)
+        self.assertEqual(scf.RHF(h2o).to_uhf().__class__, scf.uhf.UHF)
+        self.assertEqual(scf.RHF(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(scf.RHF(h2o).to_ks() .__class__, dft.rks.RKS)
+        self.assertEqual(scf.RHF(h2o).to_rks().__class__, dft.rks.RKS)
+        self.assertEqual(scf.RHF(h2o).to_uks().__class__, dft.uks.UKS)
+        self.assertEqual(scf.RHF(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(scf.UHF(h2o).to_rhf().__class__, scf.rhf.RHF)
+        self.assertEqual(scf.UHF(h2o).to_uhf().__class__, scf.uhf.UHF)
+        self.assertEqual(scf.UHF(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(scf.UHF(h2o).to_ks() .__class__, dft.uks.UKS)
+        self.assertEqual(scf.UHF(h2o).to_rks().__class__, dft.rks.RKS)
+        self.assertEqual(scf.UHF(h2o).to_uks().__class__, dft.uks.UKS)
+        self.assertEqual(scf.UHF(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(scf.GHF(h2o).to_ghf().__class__, scf.ghf.GHF)
+        self.assertEqual(scf.GHF(h2o).to_ks() .__class__, dft.gks.GKS)
+        self.assertEqual(scf.GHF(h2o).to_gks().__class__, dft.gks.GKS)
+
+        self.assertEqual(scf.RHF(h2o).density_fit().to_rhf().__class__, scf.rhf.RHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_uhf().__class__, scf.uhf.UHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_ks() .__class__, dft.rks.RKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_rks().__class__, dft.rks.RKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_uks().__class__, dft.uks.UKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.RHF(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
+        self.assertEqual(scf.UHF(h2o).density_fit().to_rhf().__class__, scf.rhf.RHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_uhf().__class__, scf.uhf.UHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_ks() .__class__, dft.uks.UKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_rks().__class__, dft.rks.RKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_uks().__class__, dft.uks.UKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.UHF(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
+        self.assertEqual(scf.GHF(h2o).density_fit().to_ghf().__class__, scf.ghf.GHF(h2o).density_fit().__class__)
+        self.assertEqual(scf.GHF(h2o).density_fit().to_ks() .__class__, dft.gks.GKS(h2o).density_fit().__class__)
+        self.assertEqual(scf.GHF(h2o).density_fit().to_gks().__class__, dft.gks.GKS(h2o).density_fit().__class__)
+
 if __name__ == "__main__":
     print("Full Tests for H2O")
     unittest.main()