diff --git a/mypyc/test-data/irbuild-valuetype.test b/mypyc/test-data/irbuild-valuetype.test new file mode 100644 index 000000000000..7a41049f1073 --- /dev/null +++ b/mypyc/test-data/irbuild-valuetype.test @@ -0,0 +1,62 @@ +[case testValueTypeBasic] +from typing import final, Final +from mypy_extensions import mypyc_attr, i32 + +@final +@mypyc_attr(value_type=True) +class Vector2I: + def __init__(self, x: i32) -> None: + self.x: Final = x + +@final +class Vector2Ir: + def __init__(self, x: i32) -> None: + self.x: Final = x + +def test_rt() -> None: + l1 = [Vector2I(1), Vector2I(1)] # require boxing + l2 = [Vector2Ir(1), Vector2Ir(1)] # do NOT require boxing + +[out] +def Vector2I.__init__(self, x): + self :: __main__.Vector2I + x :: i32 +L0: + self.x = x + return 1 +def Vector2Ir.__init__(self, x): + self :: __main__.Vector2Ir + x :: i32 +L0: + self.x = x + return 1 +def test_rt(): + r0, r1 :: __main__.Vector2I + r2 :: list + r3, r4 :: object + r5 :: ptr + l1 :: list + r6, r7 :: __main__.Vector2Ir + r8 :: list + r9 :: ptr + l2 :: list +L0: + r0 = Vector2I(1) + r1 = Vector2I(1) + r2 = PyList_New(2) + r3 = box(__main__.Vector2I, r0) + r4 = box(__main__.Vector2I, r1) + r5 = list_items r2 + buf_init_item r5, 0, r3 + buf_init_item r5, 1, r4 + keep_alive r2 + l1 = r2 + r6 = Vector2Ir(1) + r7 = Vector2Ir(1) + r8 = PyList_New(2) + r9 = list_items r8 + buf_init_item r9, 0, r6 + buf_init_item r9, 1, r7 + keep_alive r8 + l2 = r8 + return 1 diff --git a/mypyc/test-data/valuetype-errors.test b/mypyc/test-data/valuetype-errors.test new file mode 100644 index 000000000000..651076b9c721 --- /dev/null +++ b/mypyc/test-data/valuetype-errors.test @@ -0,0 +1,35 @@ +[case testValueTypeNotFinal] +from mypy_extensions import mypyc_attr + +@mypyc_attr(value_type=True) +class A: + pass + +[out] +main:4: error: Value types must be immutable and final + +[case testValueTypeHasNotParent] +from mypy_extensions import mypyc_attr +from typing import final + +class A: pass + +@final +@mypyc_attr(value_type=True) +class B(A): pass + +[out] +main:8: error: Value types must not inherit from other types + +[case testValueTypeForbiddenMethods] +from typing import final +from mypy_extensions import mypyc_attr + +@final +@mypyc_attr(value_type=True) +class A: + def __iter__(self) -> None: + pass + +[out] +main:7: error: Value types must not define method '__iter__' diff --git a/mypyc/test/test_irbuild.py b/mypyc/test/test_irbuild.py index 5b3f678d8f17..1f2400095fa7 100644 --- a/mypyc/test/test_irbuild.py +++ b/mypyc/test/test_irbuild.py @@ -44,6 +44,7 @@ "irbuild-i32.test", "irbuild-i16.test", "irbuild-u8.test", + "irbuild-valuetype.test", "irbuild-vectorcall.test", "irbuild-unreachable.test", "irbuild-isinstance.test", @@ -69,6 +70,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: if options is None: # Skipped test case return + assert options.experimental_value_types with use_custom_builtins(os.path.join(self.data_prefix, ICODE_GEN_BUILTINS), testcase): expected_output = remove_comment_lines(testcase.output) expected_output = replace_word_size(expected_output) diff --git a/mypyc/test/test_valuetype.py b/mypyc/test/test_valuetype.py new file mode 100644 index 000000000000..ba03246b740e --- /dev/null +++ b/mypyc/test/test_valuetype.py @@ -0,0 +1,38 @@ +"""Test runner for value type test cases.""" + +from __future__ import annotations + +from mypy.errors import CompileError +from mypy.test.config import test_temp_dir +from mypy.test.data import DataDrivenTestCase +from mypyc.test.testutil import ( + MypycDataSuite, + build_ir_for_single_file, + infer_ir_build_options_from_test_name, +) + +files = ["valuetype-errors.test"] + + +class TestValueTypeCompileErrors(MypycDataSuite): + """Negative cases which emit error on compile.""" + + files = files + base_path = test_temp_dir + + def run_case(self, testcase: DataDrivenTestCase) -> None: + """Perform a runtime checking transformation test case.""" + options = infer_ir_build_options_from_test_name(testcase.name) + if options is None: + # Skipped test case + return + + assert options.experimental_value_types + try: + build_ir_for_single_file(testcase.input, options) + except CompileError as e: + actual = "\n".join(e.messages).strip() + expected = "\n".join(testcase.output).strip() + assert actual == expected + else: + assert False, "Expected CompileError"