Repository: amaranth-lang/amaranth (python)
Issue: Make the use of `Elaboratable` for elaboratable objects required
It's always required a warning. Technically it's not a deprecation warning, but it might as well be; none of our other protocol classes (`ValueCastable` for example) are optional, `Elaboratable` shouldn't be either.
Pull request description: hdl._ir: Remove support for non-`Elaboratable` elaboratables.
Fixes #1216.

Patch:
diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py
index aa8f8a7..e02bae2 100644
--- a/amaranth/hdl/_ir.py
+++ b/amaranth/hdl/_ir.py
@@ -45,17 +45,8 @@ class Fragment:
                 UnusedElaboratable._MustUse__silence = False
                 obj._MustUse__used = True
                 new_obj = obj.elaborate(platform)
-            elif hasattr(obj, "elaborate"):
-                warnings.warn(
-                    message="Class {!r} is an elaboratable that does not explicitly inherit from "
-                            "Elaboratable; doing so would improve diagnostics"
-                            .format(type(obj)),
-                    category=RuntimeWarning,
-                    stacklevel=2)
-                code = obj.elaborate.__code__
-                new_obj = obj.elaborate(platform)
             else:
-                raise AttributeError(f"Object {obj!r} cannot be elaborated")
+                raise TypeError(f"Object {obj!r} is not an 'Elaboratable' nor 'Fragment'")
             if new_obj is obj:
                 raise RecursionError(f"Object {obj!r} elaborates to itself")
             if new_obj is None and code is not None:
diff --git a/docs/changes.rst b/docs/changes.rst
index 1ba3761..9cba7a2 100644
--- a/docs/changes.rst
+++ b/docs/changes.rst
@@ -37,6 +37,7 @@ Apply the following changes to code written against Amaranth 0.4 to migrate it t
 * Replace uses of ``amaranth.hdl.Memory`` with ``amaranth.lib.memory.Memory``
 * Replace imports of ``amaranth.asserts.{Assert, Assume, Cover}`` with imports from ``amaranth.hdl``
 * Remove any usage of ``name=`` with assertions, possibly replacing them with custom messages
+* Ensure all elaboratables are subclasses of :class:`Elaboratable`
 
 
 Implemented RFCs
@@ -89,6 +90,7 @@ Language changes
 * Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_)
 * Removed: (deprecated in 0.4) :class:`ast.Sample`, :class:`ast.Past`, :class:`ast.Stable`, :class:`ast.Rose`, :class:`ast.Fell`.
 * Removed: assertion names in :class:`Assert`, :class:`Assume` and :class:`Cover`. (`RFC 50`_)
+* Removed: accepting non-subclasses of :class:`Elaboratable` as elaboratables.
 
 
 Standard library changes


Test patch:
diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py
index d87600e..f968379 100644
--- a/tests/test_hdl_ir.py
+++ b/tests/test_hdl_ir.py
@@ -23,14 +23,14 @@ class ElaboratesToSelf(Elaboratable):
 
 class FragmentGetTestCase(FHDLTestCase):
     def test_get_wrong_none(self):
-        with self.assertRaisesRegex(AttributeError,
-                r"^Object None cannot be elaborated$"):
+        with self.assertRaisesRegex(TypeError,
+                r"^Object None is not an 'Elaboratable' nor 'Fragment'$"):
             Fragment.get(None, platform=None)
 
         with self.assertWarnsRegex(UserWarning,
                 r"^\.elaborate\(\) returned None; missing return statement\?$"):
-            with self.assertRaisesRegex(AttributeError,
-                    r"^Object None cannot be elaborated$"):
+            with self.assertRaisesRegex(TypeError,
+                    r"^Object None is not an 'Elaboratable' nor 'Fragment'$"):
                 Fragment.get(ElaboratesToNone(), platform=None)
 
     def test_get_wrong_self(self):