From 762717513867e043f40fbfe66a58902ac7407989 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 5 Jan 2026 00:37:12 +0100 Subject: [PATCH 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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? """