diff --git a/amaranth/lib/data.py b/amaranth/lib/data.py index ae518eb..e0dda08 100644 --- a/amaranth/lib/data.py +++ b/amaranth/lib/data.py @@ -1,5 +1,6 @@ from abc import ABCMeta, abstractmethod, abstractproperty from collections.abc import Mapping, Sequence +import warnings from amaranth.hdl import * from amaranth.hdl.ast import ShapeCastable, ValueCastable @@ -599,6 +600,12 @@ class View(ValueCastable): raise ValueError("View target is {} bit(s) wide, which is not compatible with " "the {} bit(s) wide view layout" .format(len(cast_target), cast_layout.size)) + for name, field in cast_layout: + if isinstance(name, str) and name[0] != "_" and hasattr(type(self), name): + warnings.warn("View layout includes a field {!r} that will be shadowed by " + "the view attribute '{}.{}.{}'" + .format(name, type(self).__module__, type(self).__qualname__, name), + SyntaxWarning, stacklevel=1) self.__orig_layout = layout self.__layout = cast_layout self.__target = cast_target diff --git a/tests/test_lib_data.py b/tests/test_lib_data.py index e4b5cf5..5ce1120 100644 --- a/tests/test_lib_data.py +++ b/tests/test_lib_data.py @@ -465,6 +465,22 @@ class ViewTestCase(FHDLTestCase): r"^View layout must be a layout, not <.+?>$"): View(object(), Signal(1)) + def test_layout_conflict_with_attr(self): + with self.assertWarnsRegex(SyntaxWarning, + r"^View layout includes a field 'as_value' that will be shadowed by the view " + r"attribute 'amaranth\.lib\.data\.View\.as_value'$"): + View(StructLayout({"as_value": unsigned(1)}), Signal(1)) + + def test_layout_conflict_with_attr_derived(self): + class DerivedView(View): + def foo(self): + pass + with self.assertWarnsRegex(SyntaxWarning, + r"^View layout includes a field 'foo' that will be shadowed by the view " + r"attribute 'tests\.test_lib_data\.ViewTestCase\." + r"test_layout_conflict_with_attr_derived\..DerivedView\.foo'$"): + DerivedView(StructLayout({"foo": unsigned(1)}), Signal(1)) + def test_target_wrong_type(self): with self.assertRaisesRegex(TypeError, r"^View target must be a value-castable object, not <.+?>$"):