Skip to content

Add the Zuban Type Checker #2067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion conformance/results/mypy/overloads_definitions_stub.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Allows @override to appear in a stub file not on the first overload.
"""
conformance_automated = "Fail"
errors_diff = """
Lines 143, 147, 149: Expected error (tag 'override_impl')
Lines 143, 146, 147, 149: Expected error (tag 'override_impl')
"""
output = """
overloads_definitions_stub.pyi:13: error: Single overload definition, multiple required [misc]
Expand Down
3 changes: 0 additions & 3 deletions conformance/results/mypy/qualifiers_annotated.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ qualifiers_annotated.py:91: error: "<typing special form>" not callable [operat
qualifiers_annotated.py:92: error: "<typing special form>" not callable [operator]
qualifiers_annotated.py:98: error: Invalid type: ClassVar nested inside other type [valid-type]
qualifiers_annotated.py:100: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]
qualifiers_annotated.py:119: error: Cannot redefine "T" as a type variable [misc]
qualifiers_annotated.py:119: error: Invalid assignment target [misc]
"""
conformance_automated = "Fail"
errors_diff = """
Expand All @@ -38,5 +36,4 @@ Line 85: Expected 1 errors
Line 93: Expected 1 errors
Line 98: Unexpected errors ['qualifiers_annotated.py:98: error: Invalid type: ClassVar nested inside other type [valid-type]']
Line 100: Unexpected errors ['qualifiers_annotated.py:100: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]']
Line 119: Unexpected errors ['qualifiers_annotated.py:119: error: Cannot redefine "T" as a type variable [misc]', 'qualifiers_annotated.py:119: error: Invalid assignment target [misc]']
"""
2 changes: 1 addition & 1 deletion conformance/results/mypy/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "mypy 1.17.1"
test_duration = 2.8
test_duration = 2.96
1 change: 0 additions & 1 deletion conformance/results/pyre/classes_classvar.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,5 @@ Line 70: Expected 1 errors
Line 73: Expected 1 errors
Line 77: Expected 1 errors
Line 78: Expected 1 errors
Line 66: Unexpected errors ['classes_classvar.py:66:4 Uninitialized attribute [13]: Attribute `good5` is declared in class `ClassA` to have type `typing.Any` but is never initialized.']
Line 74: Unexpected errors ['classes_classvar.py:74:8 Incompatible return type [7]: Expected `CV[int]` but got `int`.']
"""
4 changes: 2 additions & 2 deletions conformance/results/pyre/overloads_definitions_stub.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Expects @final and @override to be present on all overloads, not just first.
"""
conformance_automated = "Fail"
errors_diff = """
Lines 67, 69, 71, 73: Expected error (tag 'invalid_final')
Lines 80, 82, 84, 86: Expected error (tag 'invalid_final_2')
Lines 67, 69, 71, 72, 73: Expected error (tag 'invalid_final')
Lines 80, 82, 84, 85, 86: Expected error (tag 'invalid_final_2')
Lines 102, 107, 108, 111, 113: Expected error (tag 'override-final')
Line 63: Unexpected errors ['overloads_definitions_stub.pyi:63:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 76: Unexpected errors ['overloads_definitions_stub.pyi:76:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Expand Down
1 change: 0 additions & 1 deletion conformance/results/pyre/typeddicts_alt_syntax.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ errors_diff = """
Line 27: Expected 1 errors
Line 31: Expected 1 errors
Line 35: Expected 1 errors
Line 45: Expected 1 errors
Line 43: Unexpected errors ['typeddicts_alt_syntax.py:43:8 Undefined or invalid type [11]: Annotation `Movie2` is not defined as a type.']
"""
2 changes: 1 addition & 1 deletion conformance/results/pyre/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyre 0.9.25"
test_duration = 5.4
test_duration = 5.93
2 changes: 1 addition & 1 deletion conformance/results/pyright/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyright 1.1.403"
test_duration = 4.3
test_duration = 3.15
186 changes: 163 additions & 23 deletions conformance/results/results.html

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions conformance/results/zuban/aliases_explicit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_explicit.py:67: error: Bad number of arguments for type alias, expected 0, given 1
aliases_explicit.py:68: error: Bad number of arguments for type alias, expected 0, given 1
aliases_explicit.py:69: error: Bad number of arguments for type alias, expected 1, given 2
aliases_explicit.py:70: error: Bad number of arguments for type alias, expected 1, given 2
aliases_explicit.py:71: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "int"
aliases_explicit.py:79: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:80: error: Bracketed expression "[...]" is not valid as a type
aliases_explicit.py:80: note: Did you mean "List[...]"?
aliases_explicit.py:81: error: Syntax error in type annotation
aliases_explicit.py:81: note: Suggestion: Is there a spurious trailing comma?
aliases_explicit.py:82: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:83: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:84: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:85: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:86: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:87: error: Variable "aliases_explicit.var1" is not valid as a type
aliases_explicit.py:87: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_explicit.py:88: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:89: error: Invalid type: try using Literal[1] instead?
aliases_explicit.py:90: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:91: error: Invalid type alias: expression is not a valid type
aliases_explicit.py:100: error: Bad number of arguments for type alias, expected 0, given 1
aliases_explicit.py:101: error: "<typing special form>" not callable
aliases_explicit.py:102: error: Bad number of arguments for type alias, expected 0, given 1
"""
41 changes: 41 additions & 0 deletions conformance/results/zuban/aliases_implicit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_implicit.py:76: error: Bad number of arguments for type alias, expected 0, given 1
aliases_implicit.py:77: error: Bad number of arguments for type alias, expected 0, given 1
aliases_implicit.py:78: error: Bad number of arguments for type alias, expected 1, given 2
aliases_implicit.py:79: error: Bad number of arguments for type alias, expected 1, given 2
aliases_implicit.py:80: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "int"
aliases_implicit.py:81: error: Type argument "str" of "GoodTypeAlias12" must be a subtype of "float"
aliases_implicit.py:106: error: Variable "aliases_implicit.BadTypeAlias1" is not valid as a type
aliases_implicit.py:106: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:107: error: Variable "aliases_implicit.BadTypeAlias2" is not valid as a type
aliases_implicit.py:107: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:108: error: Variable "aliases_implicit.BadTypeAlias3" is not valid as a type
aliases_implicit.py:108: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:109: error: Variable "aliases_implicit.BadTypeAlias4" is not valid as a type
aliases_implicit.py:109: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:110: error: Variable "aliases_implicit.BadTypeAlias5" is not valid as a type
aliases_implicit.py:110: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:111: error: Variable "aliases_implicit.BadTypeAlias6" is not valid as a type
aliases_implicit.py:111: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:112: error: Variable "aliases_implicit.BadTypeAlias7" is not valid as a type
aliases_implicit.py:112: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:113: error: Variable "aliases_implicit.BadTypeAlias8" is not valid as a type
aliases_implicit.py:113: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:114: error: Variable "aliases_implicit.var1" is not valid as a type
aliases_implicit.py:114: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:115: error: Variable "aliases_implicit.BadTypeAlias10" is not valid as a type
aliases_implicit.py:115: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:116: error: Variable "aliases_implicit.BadTypeAlias11" is not valid as a type
aliases_implicit.py:116: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:117: error: Variable "aliases_implicit.BadTypeAlias12" is not valid as a type
aliases_implicit.py:117: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:118: error: Variable "aliases_implicit.BadTypeAlias13" is not valid as a type
aliases_implicit.py:118: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:119: error: Variable "aliases_implicit.BadTypeAlias14" is not valid as a type
aliases_implicit.py:119: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_implicit.py:133: error: "UnionType" not callable
aliases_implicit.py:135: error: Bad number of arguments for type alias, expected 0, given 1
"""
21 changes: 21 additions & 0 deletions conformance/results/zuban/aliases_newtype.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_newtype.py:11: error: Argument 1 to "UserId" has incompatible type "str"; expected "int"
aliases_newtype.py:12: error: Incompatible types in assignment (expression has type "int", variable has type "UserId")
aliases_newtype.py:18: error: Incompatible types in assignment (expression has type "Type[UserId]", variable has type "Type[Any]")
aliases_newtype.py:23: error: Cannot use isinstance() with NewType type
aliases_newtype.py:26: error: Cannot subclass "NewType"
aliases_newtype.py:35: error: String argument 1 "BadName" to NewType(...) does not match variable name "GoodName"
aliases_newtype.py:41: error: Bad number of arguments for type alias, expected 0, given 1
aliases_newtype.py:47: error: Argument 2 to NewType(...) must be subclassable (got "int | str")
aliases_newtype.py:50: error: Type variable "aliases_newtype.T" is unbound
aliases_newtype.py:50: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class)
aliases_newtype.py:50: note: (Hint: Use "T" in function signature to bind "T" inside a function)
aliases_newtype.py:52: error: NewType cannot be used with protocol classes
aliases_newtype.py:54: error: Argument 2 to NewType(...) must be subclassable (got "Literal[7]")
aliases_newtype.py:61: error: Argument 2 to NewType(...) must be subclassable (got "TD1")
aliases_newtype.py:63: error: NewType(...) expects exactly two positional arguments
aliases_newtype.py:65: error: Argument 2 to NewType(...) must be subclassable (got "Any")
"""
17 changes: 17 additions & 0 deletions conformance/results/zuban/aliases_recursive.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_recursive.py:19: error: Dict entry 1 has incompatible type "str": "complex"; expected "str": "None | int | str | float | list[Json] | dict[str, Json]"
aliases_recursive.py:20: error: List item 1 has incompatible type "complex"; expected "None | int | str | float | list[Json] | dict[str, Json]"
aliases_recursive.py:38: error: Incompatible types in assignment (expression has type "tuple[int, tuple[str, int], tuple[int, tuple[int, list[int]]]]", variable has type "str | int | tuple[RecursiveTuple, ...]")
aliases_recursive.py:39: error: Name "t6" already defined on line 38
aliases_recursive.py:39: error: Incompatible types in assignment (expression has type "tuple[int, list[int]]", variable has type "str | int | tuple[RecursiveTuple, ...]")
aliases_recursive.py:50: error: Dict entry 0 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, str | int | Mapping[str, RecursiveMapping]]"
aliases_recursive.py:51: error: Dict entry 2 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, str | int | Mapping[str, RecursiveMapping]]"
aliases_recursive.py:52: error: Dict entry 2 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, str | int | Mapping[str, RecursiveMapping]]"
aliases_recursive.py:63: error: List item 0 has incompatible type "float"; expected "GenericTypeAlias1[str] | str"
aliases_recursive.py:69: error: List item 0 has incompatible type "float"; expected "GenericTypeAlias2[str, int] | str | int"
aliases_recursive.py:72: error: Invalid recursive alias: a union item of itself
aliases_recursive.py:75: error: Invalid recursive alias: a union item of itself
"""
35 changes: 35 additions & 0 deletions conformance/results/zuban/aliases_type_statement.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_type_statement.py:17: error: "TypeAliasType" has no attribute "bit_count"
aliases_type_statement.py:19: error: "TypeAliasType" not callable
aliases_type_statement.py:23: error: "TypeAliasType" has no attribute "other_attrib"
aliases_type_statement.py:26: error: Type alias defined using "type" statement not valid as base class
aliases_type_statement.py:31: error: Argument 2 to "isinstance" has incompatible type "TypeAliasType"; expected "Type[Any] | UnionType | tuple[_ClassInfo, ...]"
aliases_type_statement.py:37: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:38: error: Bracketed expression "[...]" is not valid as a type
aliases_type_statement.py:38: note: Did you mean "List[...]"?
aliases_type_statement.py:39: error: Syntax error in type annotation
aliases_type_statement.py:39: note: Suggestion: Is there a spurious trailing comma?
aliases_type_statement.py:40: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:41: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:42: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:43: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:44: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:45: error: Variable "aliases_type_statement.var1" is not valid as a type
aliases_type_statement.py:45: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_type_statement.py:46: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:47: error: Invalid type: try using Literal[1] instead?
aliases_type_statement.py:48: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:49: error: Invalid type alias: expression is not a valid type
aliases_type_statement.py:52: error: Name "BadTypeAlias14" already defined on line 51
aliases_type_statement.py:56: error: Type alias not allowed in function
aliases_type_statement.py:62: error: All type parameters should be declared ("V" not declared)
aliases_type_statement.py:67: error: All type parameters should be declared ("T1" not declared)
aliases_type_statement.py:77: error: Type argument "str" of "RecursiveTypeAlias2" must be a subtype of "int"
aliases_type_statement.py:79: error: Type argument "int" of "RecursiveTypeAlias2" must be a subtype of "str"
aliases_type_statement.py:82: error: Invalid recursive alias: a union item of itself
aliases_type_statement.py:84: error: Invalid recursive alias: a union item of itself
aliases_type_statement.py:88: error: Invalid recursive alias: a union item of itself
"""
38 changes: 38 additions & 0 deletions conformance/results/zuban/aliases_typealiastype.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
conformant = "Partial"
notes = """
Incorrectly rejects the use of a class-scoped TypeVar in a TypeAliasType definition.
Incorrectly allows type_params= to be an arbitrary tuple.
"""
conformance_automated = "Fail"
errors_diff = """
Line 45: Expected 1 errors
Line 27: Unexpected errors ['aliases_typealiastype.py:27: error: Can\\'t use bound type variable "T" to define generic alias']
"""
output = """
aliases_typealiastype.py:27: error: Can't use bound type variable "T" to define generic alias
aliases_typealiastype.py:32: error: "TypeAliasType" has no attribute "other_attrib"
aliases_typealiastype.py:40: error: Type argument "int" of "GoodAlias5" must be a subtype of "str"
aliases_typealiastype.py:43: error: All type parameters should be declared ("S" not declared)
aliases_typealiastype.py:44: error: All type parameters should be declared ("S" not declared)
aliases_typealiastype.py:46: error: Invalid recursive alias: a union item of itself
aliases_typealiastype.py:47: error: Invalid recursive alias: a union item of itself
aliases_typealiastype.py:48: error: Variable "aliases_typealiastype.BadAlias7" is not valid as a type
aliases_typealiastype.py:48: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_typealiastype.py:52: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:53: error: Bracketed expression "[...]" is not valid as a type
aliases_typealiastype.py:53: note: Did you mean "List[...]"?
aliases_typealiastype.py:54: error: Syntax error in type annotation
aliases_typealiastype.py:54: note: Suggestion: Is there a spurious trailing comma?
aliases_typealiastype.py:55: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:56: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:57: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:58: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:59: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:60: error: Variable "aliases_typealiastype.var1" is not valid as a type
aliases_typealiastype.py:60: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
aliases_typealiastype.py:61: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:62: error: Invalid type: try using Literal[1] instead?
aliases_typealiastype.py:63: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:64: error: Invalid type alias: expression is not a valid type
aliases_typealiastype.py:66: error: Name "BadAlias21" is used before definition
"""
9 changes: 9 additions & 0 deletions conformance/results/zuban/aliases_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
aliases_variance.py:24: error: Variance of TypeVar "T_co" incompatible with variance in parent type
aliases_variance.py:28: error: Variance of TypeVar "T_co" incompatible with variance in parent type
aliases_variance.py:32: error: Variance of TypeVar "T_co" incompatible with variance in parent type
aliases_variance.py:44: error: Variance of TypeVar "T_contra" incompatible with variance in parent type
"""
5 changes: 5 additions & 0 deletions conformance/results/zuban/annotations_coroutines.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
conformance_automated = "Pass"
errors_diff = """
"""
output = """
"""
Loading