From 2f678fd9c90698e110a931cd11255de72ea2e55a Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 7 Mar 2026 19:33:48 +0000 Subject: [PATCH 1/3] `directives_type_checking.py`: do not assert that type checkers must ignore all type errors in `if not TYPE_CHECKING` blocks --- conformance/results/results.html | 2 +- .../results/ty/directives_type_checking.toml | 8 +------- conformance/tests/directives_type_checking.py | 14 +++++++------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/conformance/results/results.html b/conformance/results/results.html index 249f6b700..25453296c 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -1176,7 +1176,7 @@

Python Type System Conformance Test Results

Pass Pass Pass -
Partial

Attempts to detect some errors even in blocks it determines to be unreachable, including in `if not TYPE_CHECKING` blocks.

+Pass      directives_type_ignore
Partial

Does not honor "# type: ignore" comment if comment includes additional text.

diff --git a/conformance/results/ty/directives_type_checking.toml b/conformance/results/ty/directives_type_checking.toml index a9ad6809b..cdd4d0cd9 100644 --- a/conformance/results/ty/directives_type_checking.toml +++ b/conformance/results/ty/directives_type_checking.toml @@ -1,11 +1,5 @@ -conformance_automated = "Fail" -conformant = "Partial" -notes = """ -Attempts to detect some errors even in blocks it determines to be unreachable, including in `if not TYPE_CHECKING` blocks. -""" +conformance_automated = "Pass" errors_diff = """ -Line 11: Unexpected errors ['directives_type_checking.py:11:14: error[invalid-assignment] Object of type `Literal[""]` is not assignable to `int`'] """ output = """ -directives_type_checking.py:11:14: error[invalid-assignment] Object of type `Literal[""]` is not assignable to `int` """ diff --git a/conformance/tests/directives_type_checking.py b/conformance/tests/directives_type_checking.py index 55a2d52df..f491560e5 100644 --- a/conformance/tests/directives_type_checking.py +++ b/conformance/tests/directives_type_checking.py @@ -7,12 +7,12 @@ from typing import TYPE_CHECKING, assert_type -if not TYPE_CHECKING: - a: int = "" # This should not generate an error +def foo(x: list[int], y: list[str]) -> None: + z: list[int] | list[str] -if TYPE_CHECKING: - b: list[int] = [1, 2, 3] -else: - b: list[str] = ["a", "b", "c"] + if TYPE_CHECKING: + z = x + else: + z = y -assert_type(b, list[int]) + assert_type(z, list[int]) From c6fd374da4caa7fc55697038357e311aadadce88 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 8 Apr 2026 18:13:59 +0100 Subject: [PATCH 2/3] add an optional `E?` assertion for documentation purposes --- conformance/results/mypy/directives_type_checking.toml | 1 + .../results/pyrefly/directives_type_checking.toml | 1 + .../results/pyright/directives_type_checking.toml | 2 ++ conformance/results/ty/directives_type_checking.toml | 1 + conformance/results/zuban/directives_type_checking.toml | 1 + conformance/tests/directives_type_checking.py | 9 +++++++++ 6 files changed, 15 insertions(+) diff --git a/conformance/results/mypy/directives_type_checking.toml b/conformance/results/mypy/directives_type_checking.toml index 5e485e856..b7d792770 100644 --- a/conformance/results/mypy/directives_type_checking.toml +++ b/conformance/results/mypy/directives_type_checking.toml @@ -1,5 +1,6 @@ conformant = "Pass" output = """ +directives_type_checking.py:22: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyrefly/directives_type_checking.toml b/conformance/results/pyrefly/directives_type_checking.toml index be211bd5b..7d4b89493 100644 --- a/conformance/results/pyrefly/directives_type_checking.toml +++ b/conformance/results/pyrefly/directives_type_checking.toml @@ -3,4 +3,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ +ERROR directives_type_checking.py:22:14-16: `Literal['']` is not assignable to `int` [bad-assignment] """ diff --git a/conformance/results/pyright/directives_type_checking.toml b/conformance/results/pyright/directives_type_checking.toml index 5e485e856..548ee581c 100644 --- a/conformance/results/pyright/directives_type_checking.toml +++ b/conformance/results/pyright/directives_type_checking.toml @@ -1,5 +1,7 @@ conformant = "Pass" output = """ +directives_type_checking.py:22:14 - error: Type "Literal['']" is not assignable to declared type "int" +  "Literal['']" is not assignable to "int" (reportAssignmentType) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/ty/directives_type_checking.toml b/conformance/results/ty/directives_type_checking.toml index cdd4d0cd9..9fdfe0c63 100644 --- a/conformance/results/ty/directives_type_checking.toml +++ b/conformance/results/ty/directives_type_checking.toml @@ -2,4 +2,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ +directives_type_checking.py:22:14: error[invalid-assignment] Object of type `Literal[""]` is not assignable to `int` """ diff --git a/conformance/results/zuban/directives_type_checking.toml b/conformance/results/zuban/directives_type_checking.toml index cdd4d0cd9..ee105133e 100644 --- a/conformance/results/zuban/directives_type_checking.toml +++ b/conformance/results/zuban/directives_type_checking.toml @@ -2,4 +2,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ +directives_type_checking.py:22: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] """ diff --git a/conformance/tests/directives_type_checking.py b/conformance/tests/directives_type_checking.py index f491560e5..83f98e588 100644 --- a/conformance/tests/directives_type_checking.py +++ b/conformance/tests/directives_type_checking.py @@ -16,3 +16,12 @@ def foo(x: list[int], y: list[str]) -> None: z = y assert_type(z, list[int]) + + +if TYPE_CHECKING: + x: int = "" # E: In a `if TYPE_CHECKING` block, type checkers should report all errors as normal +else: + x: int = "" # E? Many type checkers suppress all errors in `else` blocks of `if TYPE_CHECKING`, though this is not currently specified + +if not TYPE_CHECKING: + x: int = "" # E? Many type checkers suppress all errors in `if not TYPE_CHECKING` blocks, though this is not currently specified From d71055946ac66a97ddc1431c1f80ad595ac56804 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 8 Apr 2026 18:22:05 +0100 Subject: [PATCH 3/3] . --- .../results/mypy/directives_type_checking.toml | 2 +- .../pyrefly/directives_type_checking.toml | 2 +- .../pyright/directives_type_checking.toml | 4 ++-- .../results/ty/directives_type_checking.toml | 2 +- .../zuban/directives_type_checking.toml | 2 +- conformance/tests/directives_type_checking.py | 18 +++++++++--------- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/conformance/results/mypy/directives_type_checking.toml b/conformance/results/mypy/directives_type_checking.toml index b7d792770..38420ca99 100644 --- a/conformance/results/mypy/directives_type_checking.toml +++ b/conformance/results/mypy/directives_type_checking.toml @@ -1,6 +1,6 @@ conformant = "Pass" output = """ -directives_type_checking.py:22: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] +directives_type_checking.py:14: error: List item 0 has incompatible type "str"; expected "int" [list-item] """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyrefly/directives_type_checking.toml b/conformance/results/pyrefly/directives_type_checking.toml index 7d4b89493..0c9777d72 100644 --- a/conformance/results/pyrefly/directives_type_checking.toml +++ b/conformance/results/pyrefly/directives_type_checking.toml @@ -3,5 +3,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -ERROR directives_type_checking.py:22:14-16: `Literal['']` is not assignable to `int` [bad-assignment] +ERROR directives_type_checking.py:14:20-27: `list[str]` is not assignable to `list[int]` [bad-assignment] """ diff --git a/conformance/results/pyright/directives_type_checking.toml b/conformance/results/pyright/directives_type_checking.toml index 548ee581c..d5ae85083 100644 --- a/conformance/results/pyright/directives_type_checking.toml +++ b/conformance/results/pyright/directives_type_checking.toml @@ -1,7 +1,7 @@ conformant = "Pass" output = """ -directives_type_checking.py:22:14 - error: Type "Literal['']" is not assignable to declared type "int" -  "Literal['']" is not assignable to "int" (reportAssignmentType) +directives_type_checking.py:14:21 - error: Type "list[str]" is not assignable to declared type "list[int]" +  "Literal['foo']" is not assignable to "int" (reportAssignmentType) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/ty/directives_type_checking.toml b/conformance/results/ty/directives_type_checking.toml index 9fdfe0c63..7c82a4a01 100644 --- a/conformance/results/ty/directives_type_checking.toml +++ b/conformance/results/ty/directives_type_checking.toml @@ -2,5 +2,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -directives_type_checking.py:22:14: error[invalid-assignment] Object of type `Literal[""]` is not assignable to `int` +directives_type_checking.py:14:20: error[invalid-assignment] Object of type `list[int | str]` is not assignable to `list[int]` """ diff --git a/conformance/results/zuban/directives_type_checking.toml b/conformance/results/zuban/directives_type_checking.toml index ee105133e..cb24b659e 100644 --- a/conformance/results/zuban/directives_type_checking.toml +++ b/conformance/results/zuban/directives_type_checking.toml @@ -2,5 +2,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -directives_type_checking.py:22: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] +directives_type_checking.py:14: error: List item 0 has incompatible type "str"; expected "int" [list-item] """ diff --git a/conformance/tests/directives_type_checking.py b/conformance/tests/directives_type_checking.py index 83f98e588..aaaaef52c 100644 --- a/conformance/tests/directives_type_checking.py +++ b/conformance/tests/directives_type_checking.py @@ -7,6 +7,15 @@ from typing import TYPE_CHECKING, assert_type +if not TYPE_CHECKING: + a: int = "" # E? Many type checkers suppress all errors in `if not TYPE_CHECKING` blocks, though this is not currently specified + +if TYPE_CHECKING: + x: list[int] = ["foo"] # E: In a `if TYPE_CHECKING` block, type checkers should report all errors as normal +else: + x: list[str] = [42] # E? Many type checkers suppress all errors in `else` blocks of `if TYPE_CHECKING`, though this is not currently specified + + def foo(x: list[int], y: list[str]) -> None: z: list[int] | list[str] @@ -16,12 +25,3 @@ def foo(x: list[int], y: list[str]) -> None: z = y assert_type(z, list[int]) - - -if TYPE_CHECKING: - x: int = "" # E: In a `if TYPE_CHECKING` block, type checkers should report all errors as normal -else: - x: int = "" # E? Many type checkers suppress all errors in `else` blocks of `if TYPE_CHECKING`, though this is not currently specified - -if not TYPE_CHECKING: - x: int = "" # E? Many type checkers suppress all errors in `if not TYPE_CHECKING` blocks, though this is not currently specified