From fcc4f54367e4931cfb4e13d96de7d32d7f81219d Mon Sep 17 00:00:00 2001 From: Catherine Date: Tue, 21 Feb 2023 17:58:28 +0000 Subject: [PATCH] lib.data: make Field() immutable. Mutability of Field isn't specified by the RFC and can cause issues if the objects stored in Layout subclasses are mutated. There isn't any reason to do that (the subclasses themselves are mutable and handle that correctly), so disallow it. --- amaranth/lib/data.py | 26 +++++++++----------------- tests/test_lib_data.py | 6 ++++++ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/amaranth/lib/data.py b/amaranth/lib/data.py index 01b77d9..a9dcc6a 100644 --- a/amaranth/lib/data.py +++ b/amaranth/lib/data.py @@ -13,33 +13,25 @@ __all__ = [ class Field: def __init__(self, shape, offset): - self.shape = shape - self.offset = offset - - @property - def shape(self): - return self._shape - - @shape.setter - def shape(self, shape): try: Shape.cast(shape) except TypeError as e: raise TypeError("Field shape must be a shape-castable object, not {!r}" .format(shape)) from e - self._shape = shape + if not isinstance(offset, int) or offset < 0: + raise TypeError("Field offset must be a non-negative integer, not {!r}" + .format(offset)) + self._shape = shape + self._offset = offset + + @property + def shape(self): + return self._shape @property def offset(self): return self._offset - @offset.setter - def offset(self, offset): - if not isinstance(offset, int) or offset < 0: - raise TypeError("Field offset must be a non-negative integer, not {!r}" - .format(offset)) - self._offset = offset - @property def width(self): return Shape.cast(self.shape).width diff --git a/tests/test_lib_data.py b/tests/test_lib_data.py index fbc5b1b..1d5a3cb 100644 --- a/tests/test_lib_data.py +++ b/tests/test_lib_data.py @@ -59,6 +59,12 @@ class FieldTestCase(TestCase): r"^Field offset must be a non-negative integer, not -1$"): Field(unsigned(2), -1) + def test_immutable(self): + with self.assertRaises(AttributeError): + Field(1, 0).shape = unsigned(2) + with self.assertRaises(AttributeError): + Field(1, 0).offset = 1 + class StructLayoutTestCase(TestCase): def test_construct(self):