amaranth/amaranth/_unused.py
Catherine a6d67f7477 hdl.ir: use additional heuristic for silencing warning.
Using `sys.excepthook` to silence the must-use warning has some false
negatives: applications may catch the exception and then quit
normally, e.g. becaue the error is well known and does not require
a traceback to be shown (which would be noisy). The current
implementation prints even more noise in that case.

In addition to the existing heuristic, silence the warning if
*nothing* has been elaborated, which is almost always a reliable
sign. It doesn't work if multiple designs are independently created
in the application and some of them are dropped without being used,
but this is unavoidable as it is not distinguishable from the mistake
this warning is attempting to prevent.

Fixes #848.
2023-07-23 04:12:22 +00:00

48 lines
1.4 KiB
Python

import sys
import warnings
from ._utils import get_linter_option
__all__ = ["UnusedMustUse", "MustUse"]
class UnusedMustUse(Warning):
pass
class MustUse:
_MustUse__silence = False
_MustUse__warning = UnusedMustUse
def __new__(cls, *args, src_loc_at=0, **kwargs):
frame = sys._getframe(1 + src_loc_at)
self = super().__new__(cls)
self._MustUse__used = False
self._MustUse__context = dict(
filename=frame.f_code.co_filename,
lineno=frame.f_lineno,
source=self)
return self
def __del__(self):
if self._MustUse__silence:
return
if getattr(self._MustUse__warning, "_MustUse__silence", False):
return
if hasattr(self, "_MustUse__used") and not self._MustUse__used:
if get_linter_option(self._MustUse__context["filename"],
self._MustUse__warning.__name__, bool, True):
warnings.warn_explicit(
"{!r} created but never used".format(self), self._MustUse__warning,
**self._MustUse__context)
_old_excepthook = sys.excepthook
def _silence_elaboratable(type, value, traceback):
# Don't show anything if the interpreter crashed; that'd just obscure the exception
# traceback instead of helping.
MustUse._MustUse__silence = True
_old_excepthook(type, value, traceback)
sys.excepthook = _silence_elaboratable