Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7627175
Change the typing spec around string references
davidhalter Jan 4, 2026
d08c226
Improve the wording around string references in the spec
davidhalter Jan 5, 2026
070312d
Remove error types
davidhalter Jan 5, 2026
41fc20c
Update docs/spec/annotations.rst
davidhalter Jan 8, 2026
ea921e8
Merge remote-tracking branch 'origin/main' into string-annotations
davidhalter Jan 8, 2026
caa71f6
Wrap the test in a consistent way
davidhalter Jan 29, 2026
0f56cb9
Small wording change
davidhalter Jan 29, 2026
cc4cec2
Ensure that forward annotations don't depend on the position in the s…
davidhalter Jan 29, 2026
928464d
Merge remote-tracking branch 'origin/main' into string-annotations
davidhalter Jan 29, 2026
d6e0e87
Merge remote-tracking branch 'origin/main' into string-annotations
davidhalter Aug 31, 2026
927aa61
Add notes for the forward reference changes
davidhalter Aug 31, 2026
0f3a654
Update conformance/tests/annotations_forward_refs.py
davidhalter Sep 4, 2026
a687acd
Update conformance/tests/annotations_forward_refs.py
davidhalter Sep 4, 2026
0d117ce
Update conformance/tests/annotations_forward_refs.py
davidhalter Sep 4, 2026
813eaca
Merge remote-tracking branch 'origin/main' into string-annotations
davidhalter Sep 4, 2026
6788f7d
Upgrade results
davidhalter Sep 4, 2026
982907b
Add more cases for forward references
davidhalter Sep 4, 2026
0742fae
Run the latest results
davidhalter Sep 4, 2026
09a4088
Add notes for Zuban
davidhalter Sep 4, 2026
d4f53a0
Try to be more precise with forward reference notes
davidhalter Sep 4, 2026
63bd33a
Add spec definition for: from __future__ import annotations
davidhalter Sep 4, 2026
9b8862e
Update conformance/results/mypy/annotations_forward_refs.toml
davidhalter Sep 4, 2026
09b59c9
Add forward references
davidhalter Sep 4, 2026
18c5636
Latest changes from review
davidhalter Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions conformance/results/mypy/annotations_forward_refs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Incorrectly generates error for quoted type defined in class 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 = """
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]
Expand All @@ -22,17 +29,9 @@ 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]
"""
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]']
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?
"""
17 changes: 11 additions & 6 deletions conformance/results/pycroscope/annotations_forward_refs.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
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
Rejects some valid quoted annotations.
"""
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
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']
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]
Expand Down Expand Up @@ -41,8 +44,10 @@ 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 <module 'types'> [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: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]
./annotations_forward_refs.py:111:16: Any[error] is not equivalent to ./annotations_forward_refs.py.ClassD.ClassInner
"""
20 changes: 12 additions & 8 deletions conformance/results/pyrefly/annotations_forward_refs.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
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 in classes at the point of definition instead of end-of-scope
Fails to resolve a forward reference to a nested class
"""
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 94: Expected 1 errors
Line 96: Expected 1 errors
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]
Expand All @@ -28,8 +30,10 @@ 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: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]
ERROR annotations_forward_refs.py:111:16-45: assert_type(Unknown, ClassD.ClassInner) failed [assert-type]
"""
23 changes: 15 additions & 8 deletions conformance/results/pyright/annotations_forward_refs.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
conformant = "Pass"
conformant = "Partial"
notes = """
Prefers to resolve forward references in classes outside of the class instead of end-of-scope
"""
conformance_automated = "Fail"
errors_diff = """
Line 94: Expected 1 errors
Line 96: Expected 1 errors
Line 103: Expected 1 errors
"""
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)
Expand Down Expand Up @@ -29,11 +38,9 @@ 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)
"""
conformance_automated = "Pass"
errors_diff = """
annotations_forward_refs.py:65:26 - error: "ClassB" is not defined (reportUndefinedVariable)
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)
"""
23 changes: 15 additions & 8 deletions conformance/results/results.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 8 additions & 10 deletions conformance/results/ty/annotations_forward_refs.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
conformance_automated = "Fail"
conformant = "Partial"
notes = """
Resolves references in type annotations as referring to end-of-scope types (<https://discuss.python.org/t/annotation-string-references-in-class-scope-in-conformance-tests/105439>, <https://github.com/python/typing/pull/2144>)
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 94: Expected 1 errors
"""
output = """
annotations_forward_refs.py:22:7: error[unresolved-reference] Name `ClassA` used when not defined
Expand All @@ -28,10 +26,10 @@ 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: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
"""
Loading