blob: 82990e6afd8287ab1c3f3715e8ae8da70005a6d6 [file] [log] [blame]
from __future__ import annotations
import unittest
from mypyc.ir.rtypes import (
RStruct,
bool_rprimitive,
int32_rprimitive,
int64_rprimitive,
int_rprimitive,
object_rprimitive,
)
from mypyc.rt_subtype import is_runtime_subtype
class TestStruct(unittest.TestCase):
def test_struct_offsets(self) -> None:
# test per-member alignment
r = RStruct("", [], [bool_rprimitive, int32_rprimitive, int64_rprimitive])
assert r.size == 16
assert r.offsets == [0, 4, 8]
# test final alignment
r1 = RStruct("", [], [bool_rprimitive, bool_rprimitive])
assert r1.size == 2
assert r1.offsets == [0, 1]
r2 = RStruct("", [], [int32_rprimitive, bool_rprimitive])
r3 = RStruct("", [], [int64_rprimitive, bool_rprimitive])
assert r2.offsets == [0, 4]
assert r3.offsets == [0, 8]
assert r2.size == 8
assert r3.size == 16
r4 = RStruct("", [], [bool_rprimitive, bool_rprimitive, bool_rprimitive, int32_rprimitive])
assert r4.size == 8
assert r4.offsets == [0, 1, 2, 4]
# test nested struct
r5 = RStruct("", [], [bool_rprimitive, r])
assert r5.offsets == [0, 8]
assert r5.size == 24
r6 = RStruct("", [], [int32_rprimitive, r5])
assert r6.offsets == [0, 8]
assert r6.size == 32
# test nested struct with alignment less than 8
r7 = RStruct("", [], [bool_rprimitive, r4])
assert r7.offsets == [0, 4]
assert r7.size == 12
def test_struct_str(self) -> None:
r = RStruct("Foo", ["a", "b"], [bool_rprimitive, object_rprimitive])
assert str(r) == "Foo{a:bool, b:object}"
assert (
repr(r) == "<RStruct Foo{a:<RPrimitive builtins.bool>, "
"b:<RPrimitive builtins.object>}>"
)
r1 = RStruct("Bar", ["c"], [int32_rprimitive])
assert str(r1) == "Bar{c:i32}"
assert repr(r1) == "<RStruct Bar{c:<RPrimitive i32>}>"
r2 = RStruct("Baz", [], [])
assert str(r2) == "Baz{}"
assert repr(r2) == "<RStruct Baz{}>"
def test_runtime_subtype(self) -> None:
# right type to check with
r = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])
# using the exact same fields
r1 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])
# names different
r2 = RStruct("Bar", ["c", "b"], [bool_rprimitive, int_rprimitive])
# name different
r3 = RStruct("Baz", ["a", "b"], [bool_rprimitive, int_rprimitive])
# type different
r4 = RStruct("FooBar", ["a", "b"], [bool_rprimitive, int32_rprimitive])
# number of types different
r5 = RStruct(
"FooBarBaz", ["a", "b", "c"], [bool_rprimitive, int_rprimitive, bool_rprimitive]
)
assert is_runtime_subtype(r1, r) is True
assert is_runtime_subtype(r2, r) is False
assert is_runtime_subtype(r3, r) is False
assert is_runtime_subtype(r4, r) is False
assert is_runtime_subtype(r5, r) is False
def test_eq_and_hash(self) -> None:
r = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])
# using the exact same fields
r1 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])
assert hash(r) == hash(r1)
assert r == r1
# different name
r2 = RStruct("Foq", ["a", "b"], [bool_rprimitive, int_rprimitive])
assert hash(r) != hash(r2)
assert r != r2
# different names
r3 = RStruct("Foo", ["a", "c"], [bool_rprimitive, int_rprimitive])
assert hash(r) != hash(r3)
assert r != r3
# different type
r4 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive, bool_rprimitive])
assert hash(r) != hash(r4)
assert r != r4