amaranth-lang / amaranth

A modern hardware definition language and toolchain based on Python
https://amaranth-lang.org/docs/amaranth/
BSD 2-Clause "Simplified" License
1.58k stars 174 forks source link

`AttributeError` caused by `UnusedElaboratable` after an elaboratable has failed its initialization #1382

Open jfng opened 5 months ago

jfng commented 5 months ago

Repro:

from amaranth import *
from amaranth.lib import wiring
from amaranth.hdl import Fragment

class Foo(wiring.Component):
    def __init__(self, arg):
        if not isinstance(arg, int):
            raise TypeError
        self._arg = arg
        super().__init__({})

    def elaborate(self, platform):
        return Module()

    def __repr__(self):
        return f"Foo({self._arg!r})"

Fragment.get(Foo(1), None)
try:
    Foo("fail")
except TypeError:
    pass

Output:

# Exception ignored in: <function MustUse.__del__ at 0x7f8410a2d440>
# Traceback (most recent call last):
#   File ".../python3.12/site-packages/amaranth/_unused.py", line 37, in __del__
#     f"{self!r} created but never used", self._MustUse__warning,
#       ^^^^^^^^
#   File "/tmp/repro.py", line 17, in __repr__
#     return f"Foo({self._arg!r})"
#                   ^^^^^^^^^
# AttributeError: 'Foo' object has no attribute '_arg'
jfng commented 5 months ago

This scenario is likely to only happen in unit tests, which can avoid it with a # amaranth: UnusedElaboratable=no modeline.