From 762717513867e043f40fbfe66a58902ac7407989 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 5 Jan 2026 00:37:12 +0100 Subject: [PATCH 01/20] Change the typing spec around string references --- conformance/tests/annotations_forward_refs.py | 14 +++++++------- docs/spec/annotations.rst | 3 +-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 70c644700..7233fa2ce 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -7,7 +7,7 @@ import types -from typing import assert_type +from typing import assert_type, Any def func1( @@ -59,7 +59,7 @@ def invalid_annotations( # > It should evaluate without errors once the module has been fully loaded. # > The local and global namespace in which it is evaluated should be the same -# > namespaces in which default arguments to the same function would be evaluated. +# > namespaces in which normal non-string types would be evaluated. class ClassB: @@ -79,21 +79,21 @@ class ClassD: ClassF: "ClassF" # E: circular reference - str: "str" = "" # OK + str: "str" = "" # E: circular reference def int(self) -> None: # OK ... - x: "int" = 0 # OK - y: int = 0 # E: Refers to local int, which isn't a legal type expression + x: "int" = 0 # # E: Refers to a local int as well + def __init__(self) -> None: self.ClassC = ClassC() -assert_type(ClassD.str, str) -assert_type(ClassD.x, int) +assert_type(ClassD.str, Any) +assert_type(ClassD.x, Any) # > If a triple quote is used, the string should be parsed as though it is implicitly diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 9ef5bfe57..62358d331 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -243,8 +243,7 @@ The string literal should contain a valid Python expression (i.e., ``compile(lit, '', 'eval')`` should be a valid code object) and it should evaluate without errors once the module has been fully loaded. The local and global namespace in which it is evaluated should be the -same namespaces in which default arguments to the same function would -be evaluated. +same namespaces in which normal non-string types would be evaluated. Moreover, the expression should be parseable as a valid type hint, i.e., it is constrained by the rules from :ref:`the expression grammar `. From d08c226aa8aa0bde47935b58218dfc319c347a77 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 5 Jan 2026 11:17:57 +0100 Subject: [PATCH 02/20] Improve the wording around string references in the spec --- conformance/tests/annotations_forward_refs.py | 7 ++-- docs/spec/annotations.rst | 33 +++++-------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 7233fa2ce..688aa4ba6 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -57,10 +57,9 @@ def invalid_annotations( pass -# > It should evaluate without errors once the module has been fully loaded. -# > The local and global namespace in which it is evaluated should be the same -# > namespaces in which normal non-string types would be evaluated. - +# > Names within the expression are looked up in the same way as they would be +# > looked up at runtime in Python 3.14 and higher if the annotation was not +# > enclosed in a string literal. class ClassB: def method1(self) -> ClassB: # E?: Runtime error prior to 3.14 diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 62358d331..5992f3a32 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -222,31 +222,14 @@ String annotations When a type hint cannot be evaluated at runtime, that definition may be expressed as a string literal, to be resolved later. -A situation where this occurs commonly is the definition of a -container class, where the class being defined occurs in the signature -of some of the methods. For example, the following code (the start of -a simple binary tree implementation) does not work:: - - class Tree: - def __init__(self, left: Tree, right: Tree): - self.left = left - self.right = right - -To address this, we write:: - - class Tree: - def __init__(self, left: 'Tree', right: 'Tree'): - self.left = left - self.right = right - -The string literal should contain a valid Python expression (i.e., -``compile(lit, '', 'eval')`` should be a valid code object) and it -should evaluate without errors once the module has been fully loaded. -The local and global namespace in which it is evaluated should be the -same namespaces in which normal non-string types would be evaluated. - -Moreover, the expression should be parseable as a valid type hint, i.e., -it is constrained by the rules from :ref:`the expression grammar `. +The string literal should contain a syntactically valid Python expression +(i.e., ``compile(lit, '', 'eval')`` should succeed) that evaluates to a valid +:term:`annotation expression`. Names within the expression are looked up in the +same way as they would be looked up at runtime in Python 3.14 and higher if the +annotation was not enclosed in a string literal. Thus, name lookup follows +general rules (e.g., the current function, class, or module scope first, and +the builtin scope last), but names defined later within the same scope can be +used in an earlier annotation. If a triple quote is used, the string should be parsed as though it is implicitly surrounded by parentheses. This allows newline characters to be From 070312df7d477bf14557b1ed7756466b7af494de Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 5 Jan 2026 22:38:39 +0100 Subject: [PATCH 03/20] Remove error types --- conformance/tests/annotations_forward_refs.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 688aa4ba6..7b6153d5f 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -91,10 +91,6 @@ def __init__(self) -> None: self.ClassC = ClassC() -assert_type(ClassD.str, Any) -assert_type(ClassD.x, Any) - - # > If a triple quote is used, the string should be parsed as though it is implicitly # > surrounded by parentheses. This allows newline characters to be # > used within the string literal. From 41fc20c93acbef9b339cb755495bb4139599ba4a Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 8 Jan 2026 09:35:41 +0000 Subject: [PATCH 04/20] Update docs/spec/annotations.rst Co-authored-by: Jelle Zijlstra --- docs/spec/annotations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 5992f3a32..28a5dd6d4 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -224,7 +224,7 @@ definition may be expressed as a string literal, to be resolved later. The string literal should contain a syntactically valid Python expression (i.e., ``compile(lit, '', 'eval')`` should succeed) that evaluates to a valid -:term:`annotation expression`. Names within the expression are looked up in the +:term:`annotation expression`. Regardless of the Python version used, names within the expression are looked up in the same way as they would be looked up at runtime in Python 3.14 and higher if the annotation was not enclosed in a string literal. Thus, name lookup follows general rules (e.g., the current function, class, or module scope first, and From caa71f6ee1c8cb690307f8a00612e1fd08aeddd9 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 29 Jan 2026 22:12:40 +0100 Subject: [PATCH 05/20] Wrap the test in a consistent way --- docs/spec/annotations.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 28a5dd6d4..045c05f12 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -224,12 +224,12 @@ definition may be expressed as a string literal, to be resolved later. The string literal should contain a syntactically valid Python expression (i.e., ``compile(lit, '', 'eval')`` should succeed) that evaluates to a valid -:term:`annotation expression`. Regardless of the Python version used, names within the expression are looked up in the -same way as they would be looked up at runtime in Python 3.14 and higher if the -annotation was not enclosed in a string literal. Thus, name lookup follows -general rules (e.g., the current function, class, or module scope first, and -the builtin scope last), but names defined later within the same scope can be -used in an earlier annotation. +:term:`annotation expression`. Regardless of the Python version used, names +within the expression are looked up in the same way as they would be looked up +at runtime in Python 3.14 and higher if the annotation was not enclosed in a +string literal. Thus, name lookup follows general rules (e.g., the current +function, class, or module scope first, and the builtin scope last), but names +defined later within the same scope can be used in an earlier annotation. If a triple quote is used, the string should be parsed as though it is implicitly surrounded by parentheses. This allows newline characters to be From 0f56cb9600e8a518e9b8eecc427639bfe37dfb49 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 29 Jan 2026 22:13:57 +0100 Subject: [PATCH 06/20] Small wording change --- docs/spec/annotations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 045c05f12..382ec2a98 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -223,7 +223,7 @@ When a type hint cannot be evaluated at runtime, that definition may be expressed as a string literal, to be resolved later. The string literal should contain a syntactically valid Python expression -(i.e., ``compile(lit, '', 'eval')`` should succeed) that evaluates to a valid +(i.e., ``compile(lit, '', 'eval')`` should succeed) that is a valid :term:`annotation expression`. Regardless of the Python version used, names within the expression are looked up in the same way as they would be looked up at runtime in Python 3.14 and higher if the annotation was not enclosed in a From cc4cec26b2fa3ddf3fa285553f9e980dd52f5354 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 29 Jan 2026 22:19:32 +0100 Subject: [PATCH 07/20] Ensure that forward annotations don't depend on the position in the scope This fix was proposed by Carl --- conformance/tests/annotations_forward_refs.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 7b6153d5f..cdc92a2f4 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -80,12 +80,14 @@ class ClassD: str: "str" = "" # E: circular reference + z: "int" = 0 # E: Refers to the local int function + def int(self) -> None: # OK ... - y: int = 0 # E: Refers to local int, which isn't a legal type expression + y: int = 0 # E: Refers to the local int function, which isn't a legal type expression - x: "int" = 0 # # E: Refers to a local int as well + x: "int" = 0 # E: Refers to a local int function def __init__(self) -> None: self.ClassC = ClassC() From 927aa6112761d1a4772e41de8b4ef4289fd2df79 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 31 Aug 2026 22:01:39 +0200 Subject: [PATCH 08/20] Add notes for the forward reference changes --- .../mypy/annotations_forward_refs.toml | 17 ++++++------ .../pycroscope/annotations_forward_refs.toml | 12 ++++----- .../pyrefly/annotations_forward_refs.toml | 14 +++++----- .../pyright/annotations_forward_refs.toml | 18 ++++++++----- conformance/results/results.html | 18 ++++++------- .../results/ty/annotations_forward_refs.toml | 17 +++++------- .../zuban/annotations_forward_refs.toml | 26 +++++++------------ 7 files changed, 57 insertions(+), 65 deletions(-) diff --git a/conformance/results/mypy/annotations_forward_refs.toml b/conformance/results/mypy/annotations_forward_refs.toml index 15211054e..17c700e57 100644 --- a/conformance/results/mypy/annotations_forward_refs.toml +++ b/conformance/results/mypy/annotations_forward_refs.toml @@ -2,7 +2,7 @@ conformant = "Partial" notes = """ Does not report error for a forward reference that is not enclosed in quotes. Does not report error for use of quoted type with `|` operator (runtime error). -Incorrectly generates error for quoted type defined in class scope. +Resolves forward references in type annotations at the point of definition instead of end-of-scope """ output = """ annotations_forward_refs.py:41: error: Invalid type comment or annotation [valid-type] @@ -22,17 +22,16 @@ annotations_forward_refs.py:53: error: Invalid type comment or annotation [vali annotations_forward_refs.py:54: error: Invalid type comment or annotation [valid-type] annotations_forward_refs.py:55: error: Module "types" is not valid as a type [valid-type] annotations_forward_refs.py:55: note: Perhaps you meant to use a protocol matching the module structure? -annotations_forward_refs.py:80: error: Name "ClassF" is not defined; did you mean "ClassA", "ClassB", or "ClassC"? [name-defined] -annotations_forward_refs.py:87: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:87: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:89: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:89: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:96: error: Expression is of type int?, not "int" [assert-type] +annotations_forward_refs.py:79: error: Name "ClassF" is not defined; did you mean "ClassA", "ClassB", or "ClassC"? [name-defined] +annotations_forward_refs.py:88: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:88: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:90: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:90: note: Perhaps you need "Callable[...]" or a callback protocol? """ conformance_automated = "Fail" errors_diff = """ Line 24: Expected 1 errors Line 25: Expected 1 errors -Line 87: Unexpected errors ['annotations_forward_refs.py:87: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type]'] -Line 96: Unexpected errors ['annotations_forward_refs.py:96: error: Expression is of type int?, not "int" [assert-type]'] +Line 81: Expected 1 errors +Line 83: Expected 1 errors """ diff --git a/conformance/results/pycroscope/annotations_forward_refs.toml b/conformance/results/pycroscope/annotations_forward_refs.toml index 63fbfc009..3be8a3b07 100644 --- a/conformance/results/pycroscope/annotations_forward_refs.toml +++ b/conformance/results/pycroscope/annotations_forward_refs.toml @@ -1,19 +1,20 @@ conformant = "Partial" notes = """ Fails to reject `"x" | int` annotations that fail at runtime. +Resolves forward references in type annotations at the point of definition instead of end-of-scope Rejects some valid quoted annotations. """ conformance_automated = "Fail" errors_diff = """ Line 24: Expected 1 errors Line 25: Expected 1 errors +Line 81: Expected 1 errors +Line 83: Expected 1 errors Line 14: Unexpected errors ['./annotations_forward_refs.py:14:8: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:22: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:42: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:62: Undefined name: ClassA [undefined_name]'] Line 16: Unexpected errors ['./annotations_forward_refs.py:16:16: Any[error] is not equivalent to ./annotations_forward_refs.py.ClassA'] Line 17: Unexpected errors ['./annotations_forward_refs.py:17:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 18: Unexpected errors ['./annotations_forward_refs.py:18:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 19: Unexpected errors ['./annotations_forward_refs.py:19:16: list[int | Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA | int]'] -Line 87: Unexpected errors ['./annotations_forward_refs.py:87:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation]'] -Line 96: Unexpected errors ['./annotations_forward_refs.py:96:12: Any[error] is not equivalent to int'] """ output = """ ./annotations_forward_refs.py:14:8: Undefined name: ClassA [undefined_name] @@ -41,8 +42,7 @@ output = """ ./annotations_forward_refs.py:53:0: Invalid type annotation [invalid_annotation] ./annotations_forward_refs.py:54:0: Invalid type annotation [invalid_annotation] ./annotations_forward_refs.py:55:9: Invalid type annotation [invalid_annotation] -./annotations_forward_refs.py:80:12: Undefined name: ClassF [undefined_name] -./annotations_forward_refs.py:87:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] -./annotations_forward_refs.py:89:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] -./annotations_forward_refs.py:96:12: Any[error] is not equivalent to int +./annotations_forward_refs.py:79:12: Undefined name: ClassF [undefined_name] +./annotations_forward_refs.py:88:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] +./annotations_forward_refs.py:90:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] """ diff --git a/conformance/results/pyrefly/annotations_forward_refs.toml b/conformance/results/pyrefly/annotations_forward_refs.toml index 8807cb346..3f380851b 100644 --- a/conformance/results/pyrefly/annotations_forward_refs.toml +++ b/conformance/results/pyrefly/annotations_forward_refs.toml @@ -1,12 +1,11 @@ conformant = "Partial" notes = """ -Types in quotes incorrectly refer to shadowing class member. -Does not reject some type forms that require quotes. +Resolves forward references in type annotations at the point of definition instead of end-of-scope """ conformance_automated = "Fail" errors_diff = """ -Line 87: Unexpected errors ['Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type]'] -Line 96: Unexpected errors ['assert_type(Unknown, int) failed [assert-type]'] +Line 81: Expected 1 errors +Line 83: Expected 1 errors """ output = """ ERROR annotations_forward_refs.py:23:12-18: `ClassA` is uninitialized [unbound-name] @@ -28,8 +27,7 @@ ERROR annotations_forward_refs.py:52:11-13: Unary operation cannot be used in an ERROR annotations_forward_refs.py:53:11-21: Boolean operation cannot be used in annotations [invalid-annotation] ERROR annotations_forward_refs.py:54:11-17: F-string cannot be used in annotations [invalid-annotation] ERROR annotations_forward_refs.py:55:11-16: Expected a type form, got instance of `Module[types]` [not-a-type] -ERROR annotations_forward_refs.py:80:14-20: Could not find name `ClassF` [unknown-name] -ERROR annotations_forward_refs.py:87:9-12: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] -ERROR annotations_forward_refs.py:89:8-11: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] -ERROR annotations_forward_refs.py:96:12-27: assert_type(Unknown, int) failed [assert-type] +ERROR annotations_forward_refs.py:79:14-20: Could not find name `ClassF` [unknown-name] +ERROR annotations_forward_refs.py:88:8-11: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] +ERROR annotations_forward_refs.py:90:9-12: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] """ diff --git a/conformance/results/pyright/annotations_forward_refs.toml b/conformance/results/pyright/annotations_forward_refs.toml index ca35b5bb1..35e57ca5e 100644 --- a/conformance/results/pyright/annotations_forward_refs.toml +++ b/conformance/results/pyright/annotations_forward_refs.toml @@ -1,4 +1,7 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Resolves forward references in type annotations at the point of definition instead of end-of-scope +""" output = """ annotations_forward_refs.py:22:7 - error: "ClassA" is not defined (reportUndefinedVariable) annotations_forward_refs.py:23:12 - error: "ClassA" is not defined (reportUndefinedVariable) @@ -29,11 +32,14 @@ annotations_forward_refs.py:52:11 - error: Unary operator not allowed in type ex annotations_forward_refs.py:53:11 - error: Binary operator not allowed in type expression (reportInvalidTypeForm) annotations_forward_refs.py:54:11 - error: Type expressions cannot use format string literals (f-strings) (reportGeneralTypeIssues) annotations_forward_refs.py:55:10 - error: Module cannot be used as a type (reportGeneralTypeIssues) -annotations_forward_refs.py:66:26 - error: "ClassB" is not defined (reportUndefinedVariable) -annotations_forward_refs.py:80:14 - error: Type of "ClassF" could not be determined because it refers to itself (reportGeneralTypeIssues) -annotations_forward_refs.py:80:14 - error: Variable not allowed in type expression (reportInvalidTypeForm) -annotations_forward_refs.py:89:8 - error: Expected class but received "(self: Self@ClassD) -> None" (reportGeneralTypeIssues) +annotations_forward_refs.py:65:26 - error: "ClassB" is not defined (reportUndefinedVariable) +annotations_forward_refs.py:79:14 - error: Type of "ClassF" could not be determined because it refers to itself (reportGeneralTypeIssues) +annotations_forward_refs.py:79:14 - error: Variable not allowed in type expression (reportInvalidTypeForm) +annotations_forward_refs.py:88:8 - error: Expected class but received "(self: Self@ClassD) -> None" (reportGeneralTypeIssues) """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 81: Expected 1 errors +Line 83: Expected 1 errors +Line 90: Expected 1 errors """ diff --git a/conformance/results/results.html b/conformance/results/results.html index 7915147fd..53d1756cf 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -294,36 +294,36 @@

Python Type System Conformance Test Results

  • Does not report error for a forward reference that is not enclosed in quotes.
  • Does not report error for use of quoted type with | operator (runtime error).
  • -
  • Incorrectly generates error for quoted type defined in class scope.
  • +
  • Resolves forward references in type annotations at the point of definition instead of end-of-scope
Partial
  • Fails to reject "x" | int annotations that fail at runtime.
  • +
  • Resolves forward references in type annotations at the point of definition instead of end-of-scope
  • Rejects some valid quoted annotations.
Partial
    -
  • Types in quotes incorrectly refer to shadowing class member.
  • -
  • Does not reject some type forms that require quotes.
  • +
  • Resolves forward references in type annotations at the point of definition instead of end-of-scope
- Pass Partial Partial
    -
  • Incorrectly generates error for quoted type defined in class scope.
  • +
  • Fails to reject str: "str" forward references
+ Pass annotations_generators @@ -377,9 +377,9 @@

Python Type System Conformance Test Results

4 / 5 • 80.0% 4 / 5 • 80.0% 4.5 / 5 • 90.0% - 5 / 5 • 100.0% 4.5 / 5 • 90.0% 4.5 / 5 • 90.0% + 5 / 5 • 100.0% @@ -2610,9 +2610,9 @@

Python Type System Conformance Test Results

108.5 / 145 • 74.8% 138 / 145 • 95.2% 140.5 / 145 • 96.9% - 135.5 / 145 • 93.4% + 135 / 145 • 93.1% 132 / 145 • 91.0% - 144.5 / 145 • 99.7% + 145 / 145 • 100.0% diff --git a/conformance/results/ty/annotations_forward_refs.toml b/conformance/results/ty/annotations_forward_refs.toml index d176548df..f5d5cbb1a 100644 --- a/conformance/results/ty/annotations_forward_refs.toml +++ b/conformance/results/ty/annotations_forward_refs.toml @@ -1,12 +1,10 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ -Resolves references in type annotations as referring to end-of-scope types (, ) +Fails to reject `str: "str"` forward references """ errors_diff = """ -Line 87: Unexpected errors ['annotations_forward_refs.py:87:9: error[invalid-type-form] Function `int` is not valid in a type expression'] -Line 95: Unexpected errors ['annotations_forward_refs.py:95:1: error[type-assertion-failure] Type `Divergent` does not match asserted type `str`'] -Line 96: Unexpected errors ['annotations_forward_refs.py:96:1: error[type-assertion-failure] Type `Unknown` does not match asserted type `int`'] +Line 81: Expected 1 errors """ output = """ annotations_forward_refs.py:22:7: error[unresolved-reference] Name `ClassA` used when not defined @@ -28,10 +26,9 @@ annotations_forward_refs.py:52:11: error[invalid-type-form] Unary operations are annotations_forward_refs.py:53:11: error[invalid-type-form] Boolean operations are not allowed in parameter annotations annotations_forward_refs.py:54:11: error[invalid-type-form] F-strings are not allowed in parameter annotations annotations_forward_refs.py:55:11: error[invalid-type-form] Module `types` is not valid in a parameter annotation -annotations_forward_refs.py:66:26: error[unresolved-reference] Name `ClassB` used when not defined -annotations_forward_refs.py:80:14: error[unresolved-reference] Name `ClassF` used when not defined -annotations_forward_refs.py:87:9: error[invalid-type-form] Function `int` is not valid in a type expression -annotations_forward_refs.py:89:8: error[invalid-type-form] Function `int` is not valid in a type expression -annotations_forward_refs.py:95:1: error[type-assertion-failure] Type `Divergent` does not match asserted type `str` -annotations_forward_refs.py:96:1: error[type-assertion-failure] Type `Unknown` does not match asserted type `int` +annotations_forward_refs.py:65:26: error[unresolved-reference] Name `ClassB` used when not defined +annotations_forward_refs.py:79:14: error[unresolved-reference] Name `ClassF` used when not defined +annotations_forward_refs.py:83:9: error[invalid-type-form] Function `int` is not valid in a type expression +annotations_forward_refs.py:88:8: error[invalid-type-form] Function `int` is not valid in a type expression +annotations_forward_refs.py:90:9: error[invalid-type-form] Function `int` is not valid in a type expression """ diff --git a/conformance/results/zuban/annotations_forward_refs.toml b/conformance/results/zuban/annotations_forward_refs.toml index 9dce37fac..6d77f1a34 100644 --- a/conformance/results/zuban/annotations_forward_refs.toml +++ b/conformance/results/zuban/annotations_forward_refs.toml @@ -1,13 +1,5 @@ -conformant = "Partial" -notes = """ -Incorrectly generates error for quoted type defined in class scope. -""" -conformance_automated = "Fail" +conformance_automated = "Pass" errors_diff = """ -Line 82: Unexpected errors ['annotations_forward_refs.py:82: error: Name "str" is not defined [name-defined]'] -Line 87: Unexpected errors ['annotations_forward_refs.py:87: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type]'] -Line 95: Unexpected errors ['annotations_forward_refs.py:95: error: Expression is of type "Any", not "str" [misc]'] -Line 96: Unexpected errors ['annotations_forward_refs.py:96: error: Expression is of type "Any", not "int" [misc]'] """ output = """ annotations_forward_refs.py:24: error: Forward reference unions cause runtime errors, consider wrapping the whole annotation with a string [misc] @@ -31,12 +23,12 @@ annotations_forward_refs.py:53: error: Invalid type comment or annotation [vali annotations_forward_refs.py:54: error: Invalid type comment or annotation [valid-type] annotations_forward_refs.py:55: error: Module "types" is not valid as a type [valid-type] annotations_forward_refs.py:55: note: Perhaps you meant to use a protocol matching the module structure? -annotations_forward_refs.py:80: error: Name "ClassF" is not defined [name-defined] -annotations_forward_refs.py:82: error: Name "str" is not defined [name-defined] -annotations_forward_refs.py:87: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:87: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:89: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:89: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:95: error: Expression is of type "Any", not "str" [misc] -annotations_forward_refs.py:96: error: Expression is of type "Any", not "int" [misc] +annotations_forward_refs.py:79: error: Name "ClassF" is not defined [name-defined] +annotations_forward_refs.py:81: error: Name "str" is not defined [name-defined] +annotations_forward_refs.py:83: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:83: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:88: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:88: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:90: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:90: note: Perhaps you need "Callable[...]" or a callback protocol? """ From 0f3a6543000a2b4720fc122b9fc101bc88c6a64c Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 06:50:27 +0000 Subject: [PATCH 09/20] Update conformance/tests/annotations_forward_refs.py Co-authored-by: Carl Meyer --- conformance/tests/annotations_forward_refs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index cdc92a2f4..862d4aedf 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -85,7 +85,7 @@ class ClassD: def int(self) -> None: # OK ... - y: int = 0 # E: Refers to the local int function, which isn't a legal type expression + y: int = 0 # E: Refers to the local int function, which isn't a valid type x: "int" = 0 # E: Refers to a local int function From a687acdce853e15e02afaa9681b9987f535be124 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 06:50:49 +0000 Subject: [PATCH 10/20] Update conformance/tests/annotations_forward_refs.py Co-authored-by: Carl Meyer --- conformance/tests/annotations_forward_refs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 862d4aedf..8f0527b74 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -87,7 +87,7 @@ def int(self) -> None: # OK y: int = 0 # E: Refers to the local int function, which isn't a valid type - x: "int" = 0 # E: Refers to a local int function + x: "int" = 0 # E: Refers to the local int function, which isn't a valid type def __init__(self) -> None: self.ClassC = ClassC() From 0d117cead7c3ca2be3c32edec5c88f9b3ba47b81 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 06:51:07 +0000 Subject: [PATCH 11/20] Update conformance/tests/annotations_forward_refs.py Co-authored-by: Carl Meyer --- conformance/tests/annotations_forward_refs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index 8f0527b74..dba1c7f62 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -80,7 +80,7 @@ class ClassD: str: "str" = "" # E: circular reference - z: "int" = 0 # E: Refers to the local int function + z: "int" = 0 # E: Refers to the local int function, which isn't a valid type def int(self) -> None: # OK ... From 6788f7d5c174a6b9d738ba0e924a1c5a36f094d7 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 09:23:59 +0200 Subject: [PATCH 12/20] Upgrade results --- conformance/results/results.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conformance/results/results.html b/conformance/results/results.html index 4bbabb805..f82ca4cdb 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -2571,9 +2571,9 @@

Python Type System Conformance Test Results

108.5 / 145 • 74.8% 138 / 145 • 95.2% 140.5 / 145 • 96.9% + 135 / 145 • 93.1% 135.5 / 145 • 93.4% - 135.5 / 145 • 93.4% - 144.5 / 145 • 99.7% + 145 / 145 • 100.0% From 982907befb5d02a3482f0a346fe0718f9f9e1539 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 09:54:43 +0200 Subject: [PATCH 13/20] Add more cases for forward references --- conformance/tests/annotations_forward_refs.py | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index dba1c7f62..be6e4a345 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -74,7 +74,17 @@ class ClassC: class ClassD: - ClassC: "ClassC" # OK + # OK + simple_attr: ClassA + ClassB: ClassB + ClassC: "ClassC" + bytes_direct: bytes + bytes: "bytes" + inner1: ClassInner + inner2: "ClassInner" + + class ClassInner: + ... ClassF: "ClassF" # E: circular reference @@ -93,6 +103,22 @@ def __init__(self) -> None: self.ClassC = ClassC() +class T: + ... + + +class ClassE[T]: + def identity1(self, value: T) -> T: + return value + + def identity2(self, value: "T") -> "T": + return value + + +assert_type(ClassE[int]().identity1(1), int) +assert_type(ClassE[int]().identity2(1), int) + + # > If a triple quote is used, the string should be parsed as though it is implicitly # > surrounded by parentheses. This allows newline characters to be # > used within the string literal. From 0742fae468b657f22eba3aa5ce202ec026bf5d51 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 10:07:01 +0200 Subject: [PATCH 14/20] Run the latest results --- .../mypy/annotations_forward_refs.toml | 14 +++++------ .../pycroscope/annotations_forward_refs.toml | 14 +++++++---- .../pyrefly/annotations_forward_refs.toml | 14 +++++++---- .../pyright/annotations_forward_refs.toml | 14 ++++++----- conformance/results/results.html | 6 ++--- .../results/ty/annotations_forward_refs.toml | 12 ++++++---- .../zuban/annotations_forward_refs.toml | 23 +++++++++++-------- conformance/tests/annotations_forward_refs.py | 3 +++ 8 files changed, 60 insertions(+), 40 deletions(-) diff --git a/conformance/results/mypy/annotations_forward_refs.toml b/conformance/results/mypy/annotations_forward_refs.toml index 17c700e57..0428ce5c0 100644 --- a/conformance/results/mypy/annotations_forward_refs.toml +++ b/conformance/results/mypy/annotations_forward_refs.toml @@ -22,16 +22,16 @@ annotations_forward_refs.py:53: error: Invalid type comment or annotation [vali annotations_forward_refs.py:54: error: Invalid type comment or annotation [valid-type] annotations_forward_refs.py:55: error: Module "types" is not valid as a type [valid-type] annotations_forward_refs.py:55: note: Perhaps you meant to use a protocol matching the module structure? -annotations_forward_refs.py:79: error: Name "ClassF" is not defined; did you mean "ClassA", "ClassB", or "ClassC"? [name-defined] -annotations_forward_refs.py:88: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:88: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:90: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:90: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:92: error: Name "ClassF" is not defined; did you mean "ClassA", "ClassB", or "ClassC"? [name-defined] +annotations_forward_refs.py:101: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:101: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:103: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:103: note: Perhaps you need "Callable[...]" or a callback protocol? """ conformance_automated = "Fail" errors_diff = """ Line 24: Expected 1 errors Line 25: Expected 1 errors -Line 81: Expected 1 errors -Line 83: Expected 1 errors +Line 94: Expected 1 errors +Line 96: Expected 1 errors """ diff --git a/conformance/results/pycroscope/annotations_forward_refs.toml b/conformance/results/pycroscope/annotations_forward_refs.toml index 3be8a3b07..4abb8d18a 100644 --- a/conformance/results/pycroscope/annotations_forward_refs.toml +++ b/conformance/results/pycroscope/annotations_forward_refs.toml @@ -8,13 +8,15 @@ conformance_automated = "Fail" errors_diff = """ Line 24: Expected 1 errors Line 25: Expected 1 errors -Line 81: Expected 1 errors -Line 83: Expected 1 errors +Line 94: Expected 1 errors +Line 96: Expected 1 errors Line 14: Unexpected errors ['./annotations_forward_refs.py:14:8: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:22: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:42: Undefined name: ClassA [undefined_name]', './annotations_forward_refs.py:14:62: Undefined name: ClassA [undefined_name]'] Line 16: Unexpected errors ['./annotations_forward_refs.py:16:16: Any[error] is not equivalent to ./annotations_forward_refs.py.ClassA'] Line 17: Unexpected errors ['./annotations_forward_refs.py:17:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 18: Unexpected errors ['./annotations_forward_refs.py:18:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 19: Unexpected errors ['./annotations_forward_refs.py:19:16: list[int | Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA | int]'] +Line 83: Unexpected errors ['./annotations_forward_refs.py:83:12: Undefined name: ClassInner [undefined_name]'] +Line 84: Unexpected errors ['./annotations_forward_refs.py:84:12: Undefined name: ClassInner [undefined_name]'] """ output = """ ./annotations_forward_refs.py:14:8: Undefined name: ClassA [undefined_name] @@ -42,7 +44,9 @@ output = """ ./annotations_forward_refs.py:53:0: Invalid type annotation [invalid_annotation] ./annotations_forward_refs.py:54:0: Invalid type annotation [invalid_annotation] ./annotations_forward_refs.py:55:9: Invalid type annotation [invalid_annotation] -./annotations_forward_refs.py:79:12: Undefined name: ClassF [undefined_name] -./annotations_forward_refs.py:88:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] -./annotations_forward_refs.py:90:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] +./annotations_forward_refs.py:83:12: Undefined name: ClassInner [undefined_name] +./annotations_forward_refs.py:84:12: Undefined name: ClassInner [undefined_name] +./annotations_forward_refs.py:92:12: Undefined name: ClassF [undefined_name] +./annotations_forward_refs.py:101:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] +./annotations_forward_refs.py:103:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] """ diff --git a/conformance/results/pyrefly/annotations_forward_refs.toml b/conformance/results/pyrefly/annotations_forward_refs.toml index 3f380851b..e95b9403b 100644 --- a/conformance/results/pyrefly/annotations_forward_refs.toml +++ b/conformance/results/pyrefly/annotations_forward_refs.toml @@ -4,8 +4,10 @@ Resolves forward references in type annotations at the point of definition inste """ conformance_automated = "Fail" errors_diff = """ -Line 81: Expected 1 errors -Line 83: Expected 1 errors +Line 94: Expected 1 errors +Line 96: Expected 1 errors +Line 83: Unexpected errors ['Could not find name `ClassInner` [unknown-name]'] +Line 84: Unexpected errors ['Could not find name `ClassInner` [unknown-name]'] """ output = """ ERROR annotations_forward_refs.py:23:12-18: `ClassA` is uninitialized [unbound-name] @@ -27,7 +29,9 @@ ERROR annotations_forward_refs.py:52:11-13: Unary operation cannot be used in an ERROR annotations_forward_refs.py:53:11-21: Boolean operation cannot be used in annotations [invalid-annotation] ERROR annotations_forward_refs.py:54:11-17: F-string cannot be used in annotations [invalid-annotation] ERROR annotations_forward_refs.py:55:11-16: Expected a type form, got instance of `Module[types]` [not-a-type] -ERROR annotations_forward_refs.py:79:14-20: Could not find name `ClassF` [unknown-name] -ERROR annotations_forward_refs.py:88:8-11: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] -ERROR annotations_forward_refs.py:90:9-12: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] +ERROR annotations_forward_refs.py:83:13-23: Could not find name `ClassInner` [unknown-name] +ERROR annotations_forward_refs.py:84:14-24: Could not find name `ClassInner` [unknown-name] +ERROR annotations_forward_refs.py:92:14-20: Could not find name `ClassF` [unknown-name] +ERROR annotations_forward_refs.py:101:8-11: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] +ERROR annotations_forward_refs.py:103:9-12: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] """ diff --git a/conformance/results/pyright/annotations_forward_refs.toml b/conformance/results/pyright/annotations_forward_refs.toml index 35e57ca5e..9fb2428dd 100644 --- a/conformance/results/pyright/annotations_forward_refs.toml +++ b/conformance/results/pyright/annotations_forward_refs.toml @@ -33,13 +33,15 @@ annotations_forward_refs.py:53:11 - error: Binary operator not allowed in type e annotations_forward_refs.py:54:11 - error: Type expressions cannot use format string literals (f-strings) (reportGeneralTypeIssues) annotations_forward_refs.py:55:10 - error: Module cannot be used as a type (reportGeneralTypeIssues) annotations_forward_refs.py:65:26 - error: "ClassB" is not defined (reportUndefinedVariable) -annotations_forward_refs.py:79:14 - error: Type of "ClassF" could not be determined because it refers to itself (reportGeneralTypeIssues) -annotations_forward_refs.py:79:14 - error: Variable not allowed in type expression (reportInvalidTypeForm) -annotations_forward_refs.py:88:8 - error: Expected class but received "(self: Self@ClassD) -> None" (reportGeneralTypeIssues) +annotations_forward_refs.py:83:13 - error: "ClassInner" is not defined (reportUndefinedVariable) +annotations_forward_refs.py:92:14 - error: Type of "ClassF" could not be determined because it refers to itself (reportGeneralTypeIssues) +annotations_forward_refs.py:92:14 - error: Variable not allowed in type expression (reportInvalidTypeForm) +annotations_forward_refs.py:101:8 - error: Expected class but received "(self: Self@ClassD) -> None" (reportGeneralTypeIssues) """ conformance_automated = "Fail" errors_diff = """ -Line 81: Expected 1 errors -Line 83: Expected 1 errors -Line 90: Expected 1 errors +Line 94: Expected 1 errors +Line 96: Expected 1 errors +Line 103: Expected 1 errors +Line 83: Unexpected errors ['annotations_forward_refs.py:83:13 - error: "ClassInner" is not defined (reportUndefinedVariable)'] """ diff --git a/conformance/results/results.html b/conformance/results/results.html index f82ca4cdb..93c7399c4 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -323,7 +323,7 @@

Python Type System Conformance Test Results

  • Fails to reject str: "str" forward references
  • - Pass + Unknown annotations_generators @@ -379,7 +379,7 @@

    Python Type System Conformance Test Results

    4.5 / 5 • 90.0% 4.5 / 5 • 90.0% 4.5 / 5 • 90.0% - 5 / 5 • 100.0% + 4 / 5 • 80.0% @@ -2573,7 +2573,7 @@

    Python Type System Conformance Test Results

    140.5 / 145 • 96.9% 135 / 145 • 93.1% 135.5 / 145 • 93.4% - 145 / 145 • 100.0% + 144 / 145 • 99.3% diff --git a/conformance/results/ty/annotations_forward_refs.toml b/conformance/results/ty/annotations_forward_refs.toml index f5d5cbb1a..60dba8d2e 100644 --- a/conformance/results/ty/annotations_forward_refs.toml +++ b/conformance/results/ty/annotations_forward_refs.toml @@ -4,7 +4,8 @@ notes = """ Fails to reject `str: "str"` forward references """ errors_diff = """ -Line 81: Expected 1 errors +Line 94: Expected 1 errors +Line 83: Unexpected errors ['annotations_forward_refs.py:83:13: error[unresolved-reference] Name `ClassInner` used when not defined'] """ output = """ annotations_forward_refs.py:22:7: error[unresolved-reference] Name `ClassA` used when not defined @@ -27,8 +28,9 @@ annotations_forward_refs.py:53:11: error[invalid-type-form] Boolean operations a annotations_forward_refs.py:54:11: error[invalid-type-form] F-strings are not allowed in parameter annotations annotations_forward_refs.py:55:11: error[invalid-type-form] Module `types` is not valid in a parameter annotation annotations_forward_refs.py:65:26: error[unresolved-reference] Name `ClassB` used when not defined -annotations_forward_refs.py:79:14: error[unresolved-reference] Name `ClassF` used when not defined -annotations_forward_refs.py:83:9: error[invalid-type-form] Function `int` is not valid in a type expression -annotations_forward_refs.py:88:8: error[invalid-type-form] Function `int` is not valid in a type expression -annotations_forward_refs.py:90:9: error[invalid-type-form] Function `int` is not valid in a type expression +annotations_forward_refs.py:83:13: error[unresolved-reference] Name `ClassInner` used when not defined +annotations_forward_refs.py:92:14: error[unresolved-reference] Name `ClassF` used when not defined +annotations_forward_refs.py:96:9: error[invalid-type-form] Function `int` is not valid in a type expression +annotations_forward_refs.py:101:8: error[invalid-type-form] Function `int` is not valid in a type expression +annotations_forward_refs.py:103:9: error[invalid-type-form] Function `int` is not valid in a type expression """ diff --git a/conformance/results/zuban/annotations_forward_refs.toml b/conformance/results/zuban/annotations_forward_refs.toml index 6d77f1a34..2d2813064 100644 --- a/conformance/results/zuban/annotations_forward_refs.toml +++ b/conformance/results/zuban/annotations_forward_refs.toml @@ -1,5 +1,7 @@ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 82: Unexpected errors ['annotations_forward_refs.py:82: error: Name "bytes" is not defined [name-defined]'] +Line 122: Unexpected errors ['annotations_forward_refs.py:122: error: Expression is of type "T", not "int" [misc]', 'annotations_forward_refs.py:122: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type]'] """ output = """ annotations_forward_refs.py:24: error: Forward reference unions cause runtime errors, consider wrapping the whole annotation with a string [misc] @@ -23,12 +25,15 @@ annotations_forward_refs.py:53: error: Invalid type comment or annotation [vali annotations_forward_refs.py:54: error: Invalid type comment or annotation [valid-type] annotations_forward_refs.py:55: error: Module "types" is not valid as a type [valid-type] annotations_forward_refs.py:55: note: Perhaps you meant to use a protocol matching the module structure? -annotations_forward_refs.py:79: error: Name "ClassF" is not defined [name-defined] -annotations_forward_refs.py:81: error: Name "str" is not defined [name-defined] -annotations_forward_refs.py:83: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:83: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:88: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:88: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:90: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] -annotations_forward_refs.py:90: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:82: error: Name "bytes" is not defined [name-defined] +annotations_forward_refs.py:92: error: Name "ClassF" is not defined [name-defined] +annotations_forward_refs.py:94: error: Name "str" is not defined [name-defined] +annotations_forward_refs.py:96: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:96: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:101: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:101: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:103: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] +annotations_forward_refs.py:103: note: Perhaps you need "Callable[...]" or a callback protocol? +annotations_forward_refs.py:122: error: Expression is of type "T", not "int" [misc] +annotations_forward_refs.py:122: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type] """ diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index be6e4a345..fc9e02d72 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -86,6 +86,9 @@ class ClassD: class ClassInner: ... + inner_after1: ClassInner + inner_after2: "ClassInner" + ClassF: "ClassF" # E: circular reference str: "str" = "" # E: circular reference From 09a408847ad7f7add6bba04614d4ff21158601fe Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 10:11:43 +0200 Subject: [PATCH 15/20] Add notes for Zuban --- conformance/results/zuban/annotations_forward_refs.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conformance/results/zuban/annotations_forward_refs.toml b/conformance/results/zuban/annotations_forward_refs.toml index 2d2813064..b9fedae58 100644 --- a/conformance/results/zuban/annotations_forward_refs.toml +++ b/conformance/results/zuban/annotations_forward_refs.toml @@ -1,3 +1,8 @@ +conformant = "Partial" +notes = """ +Fails to resolve forward references in classes from builtins +Incorrectly resolves type parameter syntax names in forward references +""" conformance_automated = "Fail" errors_diff = """ Line 82: Unexpected errors ['annotations_forward_refs.py:82: error: Name "bytes" is not defined [name-defined]'] From d4f53a0a905e0c7b21a044b3c4214c0195ef289b Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 11:07:16 +0200 Subject: [PATCH 16/20] Try to be more precise with forward reference notes --- .../mypy/annotations_forward_refs.toml | 16 ++++++------ .../pycroscope/annotations_forward_refs.toml | 3 ++- .../pyrefly/annotations_forward_refs.toml | 4 ++- .../pyright/annotations_forward_refs.toml | 17 +++++++------ conformance/results/results.html | 25 +++++++++++++------ .../results/ty/annotations_forward_refs.toml | 1 + 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/conformance/results/mypy/annotations_forward_refs.toml b/conformance/results/mypy/annotations_forward_refs.toml index 0428ce5c0..072d6c850 100644 --- a/conformance/results/mypy/annotations_forward_refs.toml +++ b/conformance/results/mypy/annotations_forward_refs.toml @@ -2,7 +2,14 @@ conformant = "Partial" notes = """ Does not report error for a forward reference that is not enclosed in quotes. Does not report error for use of quoted type with `|` operator (runtime error). -Resolves forward references in type annotations at the point of definition instead of end-of-scope +Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope +""" +conformance_automated = "Fail" +errors_diff = """ +Line 24: Expected 1 errors +Line 25: Expected 1 errors +Line 94: Expected 1 errors +Line 96: Expected 1 errors """ output = """ annotations_forward_refs.py:41: error: Invalid type comment or annotation [valid-type] @@ -28,10 +35,3 @@ annotations_forward_refs.py:101: note: Perhaps you need "Callable[...]" or a cal annotations_forward_refs.py:103: error: Function "annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] annotations_forward_refs.py:103: note: Perhaps you need "Callable[...]" or a callback protocol? """ -conformance_automated = "Fail" -errors_diff = """ -Line 24: Expected 1 errors -Line 25: Expected 1 errors -Line 94: Expected 1 errors -Line 96: Expected 1 errors -""" diff --git a/conformance/results/pycroscope/annotations_forward_refs.toml b/conformance/results/pycroscope/annotations_forward_refs.toml index 4abb8d18a..accc33ba5 100644 --- a/conformance/results/pycroscope/annotations_forward_refs.toml +++ b/conformance/results/pycroscope/annotations_forward_refs.toml @@ -1,7 +1,8 @@ conformant = "Partial" notes = """ Fails to reject `"x" | int` annotations that fail at runtime. -Resolves forward references in type annotations at the point of definition instead of end-of-scope +Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope +Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ Rejects some valid quoted annotations. """ conformance_automated = "Fail" diff --git a/conformance/results/pyrefly/annotations_forward_refs.toml b/conformance/results/pyrefly/annotations_forward_refs.toml index e95b9403b..5210d71f9 100644 --- a/conformance/results/pyrefly/annotations_forward_refs.toml +++ b/conformance/results/pyrefly/annotations_forward_refs.toml @@ -1,6 +1,8 @@ conformant = "Partial" notes = """ -Resolves forward references in type annotations at the point of definition instead of end-of-scope +Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope +Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ +Fails to resolve a forward reference to a nested class """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyright/annotations_forward_refs.toml b/conformance/results/pyright/annotations_forward_refs.toml index 9fb2428dd..9a9362900 100644 --- a/conformance/results/pyright/annotations_forward_refs.toml +++ b/conformance/results/pyright/annotations_forward_refs.toml @@ -1,6 +1,14 @@ conformant = "Partial" notes = """ -Resolves forward references in type annotations at the point of definition instead of end-of-scope +Prefers to resolve forward references in classes outside of the class instead of end-of-scope +Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ +""" +conformance_automated = "Fail" +errors_diff = """ +Line 94: Expected 1 errors +Line 96: Expected 1 errors +Line 103: Expected 1 errors +Line 83: Unexpected errors ['annotations_forward_refs.py:83:13 - error: "ClassInner" is not defined (reportUndefinedVariable)'] """ output = """ annotations_forward_refs.py:22:7 - error: "ClassA" is not defined (reportUndefinedVariable) @@ -38,10 +46,3 @@ annotations_forward_refs.py:92:14 - error: Type of "ClassF" could not be determi annotations_forward_refs.py:92:14 - error: Variable not allowed in type expression (reportInvalidTypeForm) annotations_forward_refs.py:101:8 - error: Expected class but received "(self: Self@ClassD) -> None" (reportGeneralTypeIssues) """ -conformance_automated = "Fail" -errors_diff = """ -Line 94: Expected 1 errors -Line 96: Expected 1 errors -Line 103: Expected 1 errors -Line 83: Unexpected errors ['annotations_forward_refs.py:83:13 - error: "ClassInner" is not defined (reportUndefinedVariable)'] -""" diff --git a/conformance/results/results.html b/conformance/results/results.html index 93c7399c4..51abc7a60 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -294,36 +294,47 @@

    Python Type System Conformance Test Results

    • Does not report error for a forward reference that is not enclosed in quotes.
    • Does not report error for use of quoted type with | operator (runtime error).
    • -
    • Resolves forward references in type annotations at the point of definition instead of end-of-scope
    • +
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    Partial
    • Fails to reject "x" | int annotations that fail at runtime.
    • -
    • Resolves forward references in type annotations at the point of definition instead of end-of-scope
    • +
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    • +
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    • Rejects some valid quoted annotations.
    Partial
      -
    • Resolves forward references in type annotations at the point of definition instead of end-of-scope
    • +
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    • +
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    • +
    • Fails to resolve a forward reference to a nested class
    Partial
      -
    • Resolves forward references in type annotations at the point of definition instead of end-of-scope
    • +
    • Prefers to resolve forward references in classes outside of the class instead of end-of-scope
    • +
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    Partial
    • Fails to reject str: "str" forward references
    • +
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    • +
    + + + Partial +
      +
    • Fails to resolve forward references in classes from builtins
    • +
    • Incorrectly resolves type parameter syntax names in forward references
    - Unknown annotations_generators @@ -379,7 +390,7 @@

    Python Type System Conformance Test Results

    4.5 / 5 • 90.0% 4.5 / 5 • 90.0% 4.5 / 5 • 90.0% - 4 / 5 • 80.0% + 4.5 / 5 • 90.0% @@ -2573,7 +2584,7 @@

    Python Type System Conformance Test Results

    140.5 / 145 • 96.9% 135 / 145 • 93.1% 135.5 / 145 • 93.4% - 144 / 145 • 99.3% + 144.5 / 145 • 99.7% diff --git a/conformance/results/ty/annotations_forward_refs.toml b/conformance/results/ty/annotations_forward_refs.toml index 60dba8d2e..e5183743d 100644 --- a/conformance/results/ty/annotations_forward_refs.toml +++ b/conformance/results/ty/annotations_forward_refs.toml @@ -2,6 +2,7 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ Fails to reject `str: "str"` forward references +Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ """ errors_diff = """ Line 94: Expected 1 errors From 63bd33a88b94e3a40d0cc2e7e42b50f24a62bfc4 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 11:23:09 +0200 Subject: [PATCH 17/20] Add spec definition for: from __future__ import annotations --- docs/spec/annotations.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 7ff8e0f70..f422af186 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -290,6 +290,14 @@ _module_._class_ name:: from models.a import A from models.b import B +from __future__ import annotations +---------------------------------- + +The presence of the import `from __future__ import annotations` must not +influence type checking. Annotations must be resolved in the exact same way as +if the import was not present. + + Annotating generator functions and coroutines --------------------------------------------- From 9b8862e378e9c09056de32c13c3e91ba52af55c6 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 19:24:54 +0000 Subject: [PATCH 18/20] Update conformance/results/mypy/annotations_forward_refs.toml Co-authored-by: Carl Meyer --- conformance/results/mypy/annotations_forward_refs.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/results/mypy/annotations_forward_refs.toml b/conformance/results/mypy/annotations_forward_refs.toml index 072d6c850..b74ef2246 100644 --- a/conformance/results/mypy/annotations_forward_refs.toml +++ b/conformance/results/mypy/annotations_forward_refs.toml @@ -2,7 +2,7 @@ conformant = "Partial" notes = """ Does not report error for a forward reference that is not enclosed in quotes. Does not report error for use of quoted type with `|` operator (runtime error). -Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope +Resolves some forward references in type annotations in classes at the point of definition instead of end-of-scope """ conformance_automated = "Fail" errors_diff = """ From 09b59c902edeefda8898aa848be93ac64edcbb5c Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 21:36:40 +0200 Subject: [PATCH 19/20] Add forward references --- conformance/tests/annotations_forward_refs.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index fc9e02d72..ca3e0bd9d 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -106,6 +106,12 @@ def __init__(self) -> None: self.ClassC = ClassC() +def check_valid_attributes(d: ClassD) -> None: + assert_type(d.bytes, bytes) + assert_type(d.inner2, ClassD.ClassInner) + assert_type(d.inner_after2, ClassD.ClassInner) + + class T: ... From 18c5636d9991ee05c2a9bb56d36e51d6f5bb6677 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 4 Sep 2026 21:41:53 +0200 Subject: [PATCH 20/20] Latest changes from review --- .../results/pycroscope/annotations_forward_refs.toml | 4 ++-- conformance/results/pyrefly/annotations_forward_refs.toml | 4 ++-- conformance/results/pyright/annotations_forward_refs.toml | 2 -- conformance/results/results.html | 6 +----- conformance/results/ty/annotations_forward_refs.toml | 2 -- conformance/results/zuban/annotations_forward_refs.toml | 8 +++++--- conformance/tests/annotations_forward_refs.py | 2 +- 7 files changed, 11 insertions(+), 17 deletions(-) diff --git a/conformance/results/pycroscope/annotations_forward_refs.toml b/conformance/results/pycroscope/annotations_forward_refs.toml index accc33ba5..1ae6c941a 100644 --- a/conformance/results/pycroscope/annotations_forward_refs.toml +++ b/conformance/results/pycroscope/annotations_forward_refs.toml @@ -2,7 +2,6 @@ conformant = "Partial" notes = """ Fails to reject `"x" | int` annotations that fail at runtime. Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope -Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ Rejects some valid quoted annotations. """ conformance_automated = "Fail" @@ -16,8 +15,8 @@ Line 16: Unexpected errors ['./annotations_forward_refs.py:16:16: Any[error] i Line 17: Unexpected errors ['./annotations_forward_refs.py:17:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 18: Unexpected errors ['./annotations_forward_refs.py:18:16: list[Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA]'] Line 19: Unexpected errors ['./annotations_forward_refs.py:19:16: list[int | Any[error]] is not equivalent to list[./annotations_forward_refs.py.ClassA | int]'] -Line 83: Unexpected errors ['./annotations_forward_refs.py:83:12: Undefined name: ClassInner [undefined_name]'] Line 84: Unexpected errors ['./annotations_forward_refs.py:84:12: Undefined name: ClassInner [undefined_name]'] +Line 111: Unexpected errors ['./annotations_forward_refs.py:111:16: Any[error] is not equivalent to ./annotations_forward_refs.py.ClassD.ClassInner'] """ output = """ ./annotations_forward_refs.py:14:8: Undefined name: ClassA [undefined_name] @@ -50,4 +49,5 @@ output = """ ./annotations_forward_refs.py:92:12: Undefined name: ClassF [undefined_name] ./annotations_forward_refs.py:101:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] ./annotations_forward_refs.py:103:7: Unrecognized annotation (self: ./annotations_forward_refs.py.ClassD) -> None [invalid_annotation] +./annotations_forward_refs.py:111:16: Any[error] is not equivalent to ./annotations_forward_refs.py.ClassD.ClassInner """ diff --git a/conformance/results/pyrefly/annotations_forward_refs.toml b/conformance/results/pyrefly/annotations_forward_refs.toml index 5210d71f9..83f996a3e 100644 --- a/conformance/results/pyrefly/annotations_forward_refs.toml +++ b/conformance/results/pyrefly/annotations_forward_refs.toml @@ -1,15 +1,14 @@ conformant = "Partial" notes = """ Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope -Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ Fails to resolve a forward reference to a nested class """ conformance_automated = "Fail" errors_diff = """ Line 94: Expected 1 errors Line 96: Expected 1 errors -Line 83: Unexpected errors ['Could not find name `ClassInner` [unknown-name]'] Line 84: Unexpected errors ['Could not find name `ClassInner` [unknown-name]'] +Line 111: Unexpected errors ['assert_type(Unknown, ClassD.ClassInner) failed [assert-type]'] """ output = """ ERROR annotations_forward_refs.py:23:12-18: `ClassA` is uninitialized [unbound-name] @@ -36,4 +35,5 @@ ERROR annotations_forward_refs.py:84:14-24: Could not find name `ClassInner` [un ERROR annotations_forward_refs.py:92:14-20: Could not find name `ClassF` [unknown-name] ERROR annotations_forward_refs.py:101:8-11: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] ERROR annotations_forward_refs.py:103:9-12: Expected a type form, got instance of `(self: Self@ClassD) -> None` [not-a-type] +ERROR annotations_forward_refs.py:111:16-45: assert_type(Unknown, ClassD.ClassInner) failed [assert-type] """ diff --git a/conformance/results/pyright/annotations_forward_refs.toml b/conformance/results/pyright/annotations_forward_refs.toml index 9a9362900..b28b77967 100644 --- a/conformance/results/pyright/annotations_forward_refs.toml +++ b/conformance/results/pyright/annotations_forward_refs.toml @@ -1,14 +1,12 @@ conformant = "Partial" notes = """ Prefers to resolve forward references in classes outside of the class instead of end-of-scope -Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ """ conformance_automated = "Fail" errors_diff = """ Line 94: Expected 1 errors Line 96: Expected 1 errors Line 103: Expected 1 errors -Line 83: Unexpected errors ['annotations_forward_refs.py:83:13 - error: "ClassInner" is not defined (reportUndefinedVariable)'] """ output = """ annotations_forward_refs.py:22:7 - error: "ClassA" is not defined (reportUndefinedVariable) diff --git a/conformance/results/results.html b/conformance/results/results.html index 51abc7a60..8f43170ee 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -294,7 +294,7 @@

    Python Type System Conformance Test Results

    • Does not report error for a forward reference that is not enclosed in quotes.
    • Does not report error for use of quoted type with | operator (runtime error).
    • -
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    • +
    • Resolves some forward references in type annotations in classes at the point of definition instead of end-of-scope
    @@ -302,7 +302,6 @@

    Python Type System Conformance Test Results

    • Fails to reject "x" | int annotations that fail at runtime.
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    • -
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    • Rejects some valid quoted annotations.
    @@ -310,7 +309,6 @@

    Python Type System Conformance Test Results

    Partial
    • Resolves forward references in type annotations in classes at the point of definition instead of end-of-scope
    • -
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    • Fails to resolve a forward reference to a nested class
    @@ -318,14 +316,12 @@

    Python Type System Conformance Test Results

    Partial
    • Prefers to resolve forward references in classes outside of the class instead of end-of-scope
    • -
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    Partial
    • Fails to reject str: "str" forward references
    • -
    • Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+
    diff --git a/conformance/results/ty/annotations_forward_refs.toml b/conformance/results/ty/annotations_forward_refs.toml index e5183743d..84c1c29e3 100644 --- a/conformance/results/ty/annotations_forward_refs.toml +++ b/conformance/results/ty/annotations_forward_refs.toml @@ -2,11 +2,9 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ Fails to reject `str: "str"` forward references -Adds an error for symbols in annotations that are defined later than the annotation, which is now possible in Python 3.14+ """ errors_diff = """ Line 94: Expected 1 errors -Line 83: Unexpected errors ['annotations_forward_refs.py:83:13: error[unresolved-reference] Name `ClassInner` used when not defined'] """ output = """ annotations_forward_refs.py:22:7: error[unresolved-reference] Name `ClassA` used when not defined diff --git a/conformance/results/zuban/annotations_forward_refs.toml b/conformance/results/zuban/annotations_forward_refs.toml index b9fedae58..26dfc7e66 100644 --- a/conformance/results/zuban/annotations_forward_refs.toml +++ b/conformance/results/zuban/annotations_forward_refs.toml @@ -6,7 +6,8 @@ Incorrectly resolves type parameter syntax names in forward references conformance_automated = "Fail" errors_diff = """ Line 82: Unexpected errors ['annotations_forward_refs.py:82: error: Name "bytes" is not defined [name-defined]'] -Line 122: Unexpected errors ['annotations_forward_refs.py:122: error: Expression is of type "T", not "int" [misc]', 'annotations_forward_refs.py:122: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type]'] +Line 110: Unexpected errors ['annotations_forward_refs.py:110: error: Expression is of type "Any", not "bytes" [misc]'] +Line 128: Unexpected errors ['annotations_forward_refs.py:128: error: Expression is of type "T", not "int" [misc]', 'annotations_forward_refs.py:128: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type]'] """ output = """ annotations_forward_refs.py:24: error: Forward reference unions cause runtime errors, consider wrapping the whole annotation with a string [misc] @@ -39,6 +40,7 @@ annotations_forward_refs.py:101: error: Function "tests.annotations_forward_refs annotations_forward_refs.py:101: note: Perhaps you need "Callable[...]" or a callback protocol? annotations_forward_refs.py:103: error: Function "tests.annotations_forward_refs.ClassD.int" is not valid as a type [valid-type] annotations_forward_refs.py:103: note: Perhaps you need "Callable[...]" or a callback protocol? -annotations_forward_refs.py:122: error: Expression is of type "T", not "int" [misc] -annotations_forward_refs.py:122: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type] +annotations_forward_refs.py:110: error: Expression is of type "Any", not "bytes" [misc] +annotations_forward_refs.py:128: error: Expression is of type "T", not "int" [misc] +annotations_forward_refs.py:128: error: Argument 1 to "identity2" of "ClassE" has incompatible type "int"; expected "T" [arg-type] """ diff --git a/conformance/tests/annotations_forward_refs.py b/conformance/tests/annotations_forward_refs.py index ca3e0bd9d..6262aa4da 100644 --- a/conformance/tests/annotations_forward_refs.py +++ b/conformance/tests/annotations_forward_refs.py @@ -80,7 +80,7 @@ class ClassD: ClassC: "ClassC" bytes_direct: bytes bytes: "bytes" - inner1: ClassInner + inner1: ClassInner # E?: Runtime error prior to 3.14: requires quotes inner2: "ClassInner" class ClassInner: