From e1afe4b06d1359678934387a9639e3fa4bfc46be Mon Sep 17 00:00:00 2001 From: Catherine Date: Wed, 5 Mar 2025 00:25:30 +0000 Subject: [PATCH] hdl.ir: improve error raised when returning None from `elaborate`. Fixes #1569. --- amaranth/hdl/_ir.py | 14 +++++--------- tests/test_hdl_ir.py | 10 ++++------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py index 0bdbb97e6..1370bdea4 100644 --- a/amaranth/hdl/_ir.py +++ b/amaranth/hdl/_ir.py @@ -49,8 +49,8 @@ class DomainRequirementFailed(Exception): class Fragment: @staticmethod def get(obj, platform): - code = None origins = [] + returned_by = "" while True: if isinstance(obj, Fragment): if hasattr(obj, "origins"): @@ -58,19 +58,15 @@ def get(obj, platform): return obj elif isinstance(obj, Elaboratable): code = obj.elaborate.__code__ + returned_by = f", returned by {code.co_filename}:{code.co_firstlineno}" UnusedElaboratable._MustUse__silence = False obj._MustUse__used = True new_obj = obj.elaborate(platform) else: - raise TypeError(f"Object {obj!r} is not an 'Elaboratable' nor 'Fragment'") + raise TypeError( + f"Object {obj!r} is not an 'Elaboratable' nor 'Fragment'{returned_by}") if new_obj is obj: - raise RecursionError(f"Object {obj!r} elaborates to itself") - if new_obj is None and code is not None: - warnings.warn_explicit( - message=".elaborate() returned None; missing return statement?", - category=UserWarning, - filename=code.co_filename, - lineno=code.co_firstlineno) + raise RecursionError(f"Object {obj!r} elaborates to itself{returned_by}") origins.append(obj) obj = new_obj diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py index bbfc86ce3..c017f38e9 100644 --- a/tests/test_hdl_ir.py +++ b/tests/test_hdl_ir.py @@ -31,15 +31,13 @@ def test_get_wrong_none(self): 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(TypeError, - r"^Object None is not an 'Elaboratable' nor 'Fragment'$"): - Fragment.get(ElaboratesToNone(), platform=None) + with self.assertRaisesRegex(TypeError, + r"^Object None is not an 'Elaboratable' nor 'Fragment', returned by .+?:19$"): + Fragment.get(ElaboratesToNone(), platform=None) def test_get_wrong_self(self): with self.assertRaisesRegex(RecursionError, - r"^Object <.+?ElaboratesToSelf.+?> elaborates to itself$"): + r"^Object <.+?ElaboratesToSelf.+?> elaborates to itself, returned by .+?:24$"): Fragment.get(ElaboratesToSelf(), platform=None)