From 8127c5e508c9b42089061f606351400476fba7a8 Mon Sep 17 00:00:00 2001
From: crypt0lith <118923461+crypt0lith@users.noreply.github.com>
Date: Fri, 13 Nov 2026 17:22:39 -0600
Subject: [PATCH 1/2] specialize generic subclass from inherited __init__ self
annotation
---
.../results/mypy/constructors_call_init.toml | 9 +++-
.../pycroscope/constructors_call_init.toml | 15 +++++-
.../pyrefly/constructors_call_init.toml | 4 +-
.../pyright/constructors_call_init.toml | 17 +++++--
conformance/results/results.html | 25 +++++++---
.../results/ty/constructors_call_init.toml | 4 +-
.../results/zuban/constructors_call_init.toml | 4 +-
conformance/tests/constructors_call_init.py | 49 +++++++++++++++++++
docs/spec/constructors.rst | 29 +++++++++--
9 files changed, 138 insertions(+), 18 deletions(-)
diff --git a/conformance/results/mypy/constructors_call_init.toml b/conformance/results/mypy/constructors_call_init.toml
index f2d7df715..9ea5819df 100644
--- a/conformance/results/mypy/constructors_call_init.toml
+++ b/conformance/results/mypy/constructors_call_init.toml
@@ -2,16 +2,23 @@ conformant = "Partial"
notes = """
Does not report errors during binding to self parameter of `__init__` method.
Does not reject use of class-scoped type variables in annotation of self parameter in `__init__` method.
+Does not solve a subclass's type parameters from the self annotation of an inherited `__init__` method.
"""
conformance_automated = "Fail"
errors_diff = """
Line 56: Expected 1 errors
Line 107: Expected 1 errors
+Line 145: Expected 1 errors
+Line 157: Expected 1 errors
Line 73: Unexpected errors ['constructors_call_init.py:73: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]']
+Line 127: Unexpected errors ['constructors_call_init.py:127: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]']
+Line 134: Unexpected errors ['constructors_call_init.py:134: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]']
"""
output = """
constructors_call_init.py:21: error: Argument 1 to "Class1" has incompatible type "float"; expected "int" [arg-type]
constructors_call_init.py:42: error: Argument 1 to "Class3" has incompatible type "Class2[Never]"; expected "Class3 | None" [arg-type]
constructors_call_init.py:73: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]
-constructors_call_init.py:130: error: Too many arguments for "Class11" [call-arg]
+constructors_call_init.py:127: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]
+constructors_call_init.py:134: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]
+constructors_call_init.py:179: error: Too many arguments for "Class11" [call-arg]
"""
diff --git a/conformance/results/pycroscope/constructors_call_init.toml b/conformance/results/pycroscope/constructors_call_init.toml
index da605980b..176d24f13 100644
--- a/conformance/results/pycroscope/constructors_call_init.toml
+++ b/conformance/results/pycroscope/constructors_call_init.toml
@@ -1,10 +1,21 @@
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Does not solve a subclass's type parameters from the self annotation of an inherited `__init__` method.
+Does not report errors during binding to the self parameter of an inherited `__init__` method.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 145: Expected 1 errors
+Line 157: Expected 1 errors
+Line 127: Unexpected errors ['./constructors_call_init.py:127:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]']
+Line 134: Unexpected errors ['./constructors_call_init.py:134:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]']
"""
output = """
./constructors_call_init.py:21:12: Incompatible argument type for x: expected int but got Literal[1.0] [incompatible_argument]
./constructors_call_init.py:42:7: Incompatible argument type for x: expected ./constructors_call_init.py.Class3 | None but got ./constructors_call_init.py.Class2 [incompatible_argument]
./constructors_call_init.py:56:0: Missing required positional argument '%self' [incompatible_call]
./constructors_call_init.py:107:17: Class-scoped type variables are not allowed in __init__ self annotation [invalid_self_usage]
-./constructors_call_init.py:130:0: Takes 0 positional arguments but 1 were given [incompatible_call]
+./constructors_call_init.py:127:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]
+./constructors_call_init.py:134:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]
+./constructors_call_init.py:179:0: Takes 0 positional arguments but 1 were given [incompatible_call]
"""
diff --git a/conformance/results/pyrefly/constructors_call_init.toml b/conformance/results/pyrefly/constructors_call_init.toml
index 05593e0a0..ede5543ca 100644
--- a/conformance/results/pyrefly/constructors_call_init.toml
+++ b/conformance/results/pyrefly/constructors_call_init.toml
@@ -7,5 +7,7 @@ ERROR constructors_call_init.py:21:13-16: Argument `float` is not assignable to
ERROR constructors_call_init.py:42:8-20: Argument `Class2[@_]` is not assignable to parameter `x` with type `Class3 | None` in function `Class2.__init__` [bad-argument-type]
ERROR constructors_call_init.py:56:12-14: Argument `Class4[str]` is not assignable to parameter `self` with type `Class4[int]` in function `Class4.__init__` [bad-argument-type]
ERROR constructors_call_init.py:107:9-17: `__init__` method self type cannot reference class type parameters `T2`, `T1` [invalid-annotation]
-ERROR constructors_call_init.py:130:9-10: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count]
+ERROR constructors_call_init.py:145:8-10: Argument `Class15[@_]` is not assignable to parameter `self` with type `Class12[int, str]` in function `Class12.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:157:9-10: Argument `Literal[1]` is not assignable to parameter `value` with type `str` in function `Class16.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:179:9-10: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count]
"""
diff --git a/conformance/results/pyright/constructors_call_init.toml b/conformance/results/pyright/constructors_call_init.toml
index 4d6672588..2a521455a 100644
--- a/conformance/results/pyright/constructors_call_init.toml
+++ b/conformance/results/pyright/constructors_call_init.toml
@@ -1,6 +1,13 @@
-conformant = "Pass"
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Does not solve a subclass's type parameters from the self annotation of an inherited `__init__` method.
+Does not report an error when a subclass's specialization of a base class is not assignable to the self annotation of an inherited `__init__` method.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 145: Expected 1 errors
+Line 127: Unexpected errors ['constructors_call_init.py:127:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)']
+Line 134: Unexpected errors ['constructors_call_init.py:134:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)']
"""
output = """
constructors_call_init.py:21:13 - error: Argument of type "float" cannot be assigned to parameter "x" of type "int" in function "__init__"
@@ -14,5 +21,9 @@ constructors_call_init.py:56:1 - error:
"Class4[str]" is not assignable to "Class4[int]"
Type parameter "T@Class4" is invariant, but "str" is not the same as "int" (reportGeneralTypeIssues)
constructors_call_init.py:107:24 - warning: Type annotation for "self" parameter of "__init__" method cannot contain class-scoped type variables (reportInvalidTypeVarUse)
-constructors_call_init.py:130:9 - error: Expected 0 positional arguments (reportCallIssue)
+constructors_call_init.py:127:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)
+constructors_call_init.py:134:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)
+constructors_call_init.py:157:9 - error: Argument of type "Literal[1]" cannot be assigned to parameter "value" of type "str" in function "__init__"
+ "Literal[1]" is not assignable to "str" (reportArgumentType)
+constructors_call_init.py:179:9 - error: Expected 0 positional arguments (reportCallIssue)
"""
diff --git a/conformance/results/results.html b/conformance/results/results.html
index 2525a3b81..87833cefe 100644
--- a/conformance/results/results.html
+++ b/conformance/results/results.html
@@ -1503,11 +1503,24 @@
Python Type System Conformance Test Results
- Does not report errors during binding to self parameter of
__init__ method.
- Does not reject use of class-scoped type variables in annotation of self parameter in
__init__ method.
+ - Does not solve a subclass's type parameters from the self annotation of an inherited
__init__ method.
+
+
+
+ Partial
+
+ - Does not solve a subclass's type parameters from the self annotation of an inherited
__init__ method.
+ - Does not report errors during binding to the self parameter of an inherited
__init__ method.
|
Pass |
- Pass |
- Pass |
+
+ Partial
+
+ - Does not solve a subclass's type parameters from the self annotation of an inherited
__init__ method.
+ - Does not report an error when a subclass's specialization of a base class is not assignable to the self annotation of an inherited
__init__ method.
+
+ |
Partial
@@ -1601,9 +1614,9 @@ Python Type System Conformance Test Results
|
3 / 6 • 50.0% |
+ 5.5 / 6 • 91.7% |
6 / 6 • 100.0% |
- 6 / 6 • 100.0% |
- 6 / 6 • 100.0% |
+ 5.5 / 6 • 91.7% |
5 / 6 • 83.3% |
6 / 6 • 100.0% |
@@ -2511,9 +2524,9 @@ Python Type System Conformance Test Results
|
110.5 / 146 • 75.7% |
- 139 / 146 • 95.2% |
+ 138.5 / 146 • 94.9% |
142.5 / 146 • 97.6% |
- 140.5 / 146 • 96.2% |
+ 140 / 146 • 95.9% |
141.5 / 146 • 96.9% |
146 / 146 • 100.0% |
diff --git a/conformance/results/ty/constructors_call_init.toml b/conformance/results/ty/constructors_call_init.toml
index c6b0eb40a..8fa0d4532 100644
--- a/conformance/results/ty/constructors_call_init.toml
+++ b/conformance/results/ty/constructors_call_init.toml
@@ -11,5 +11,7 @@ constructors_call_init.py:21:13: error[invalid-argument-type] Argument to `Class
constructors_call_init.py:56:1: error[invalid-argument-type] Argument to `Class4.__init__` is incorrect: Expected `Class4[int]`, found `Class4[str]`
constructors_call_init.py:107:32: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T2` from an outer scope
constructors_call_init.py:107:36: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T1` from an outer scope
-constructors_call_init.py:130:9: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2
+constructors_call_init.py:145:1: error[invalid-argument-type] Argument to `Class12.__init__` is incorrect: Expected `Class12[int, str]`, found `Class15[str]`
+constructors_call_init.py:157:9: error[invalid-argument-type] Argument to `Class16.__init__` is incorrect: Expected `str`, found `Literal[1]`
+constructors_call_init.py:179:9: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2
"""
diff --git a/conformance/results/zuban/constructors_call_init.toml b/conformance/results/zuban/constructors_call_init.toml
index 6192d7a0d..cd9be46f4 100644
--- a/conformance/results/zuban/constructors_call_init.toml
+++ b/conformance/results/zuban/constructors_call_init.toml
@@ -7,5 +7,7 @@ constructors_call_init.py:42: error: Argument 1 to "Class3" has incompatible typ
constructors_call_init.py:56: error: Invalid self type in __init__ [call-arg]
constructors_call_init.py:107: error: The type of self "T1" has type vars in non standard positions for class "Class8" [misc]
constructors_call_init.py:107: error: The type of self "T2" has type vars in non standard positions for class "Class8" [misc]
-constructors_call_init.py:130: error: Too many arguments for "Class11" [call-arg]
+constructors_call_init.py:145: error: Invalid self type in __init__ [call-arg]
+constructors_call_init.py:157: error: Argument 1 to "Class17" has incompatible type "int"; expected "str" [arg-type]
+constructors_call_init.py:179: error: Too many arguments for "Class11" [call-arg]
"""
diff --git a/conformance/tests/constructors_call_init.py b/conformance/tests/constructors_call_init.py
index c3749634a..0e4c64025 100644
--- a/conformance/tests/constructors_call_init.py
+++ b/conformance/tests/constructors_call_init.py
@@ -108,6 +108,55 @@ def __init__(self: "Class8[T2, T1]") -> None: # E
pass
+# > When the class being constructed is not explicitly specialized and inherits
+# > an __init__ method whose self annotation names a specialization of a base
+# > class, type checkers should solve the type parameters the class passes to
+# > that base class from the annotation.
+
+T3 = TypeVar("T3")
+
+
+class Class12(Generic[T1, T2]):
+ def __init__(self: "Class12[int, str]") -> None: ...
+
+
+class Class13(Class12[T1, T2]):
+ pass
+
+
+assert_type(Class13(), Class13[int, str])
+
+
+class Class14(Class12[T3, T2], Generic[T1, T2, T3]):
+ pass
+
+
+assert_type(Class14(), Class14[Any, str, int])
+
+
+# > If the class's specialization of that base class is not assignable to the
+# > annotation, binding fails.
+
+
+class Class15(Class12[list[T], T]):
+ pass
+
+
+Class15() # E
+
+
+class Class16(Generic[T]):
+ def __init__(self: "Class16[V1]", value: V1) -> None: ...
+
+
+class Class17(Class16[str]):
+ pass
+
+
+Class17("") # OK
+Class17(1) # E
+
+
# > If a class does not define a __new__ method or __init__ method and does
# > not inherit either of these methods from a base class other than object,
# > a type checker should evaluate the argument list using the __new__ and
diff --git a/docs/spec/constructors.rst b/docs/spec/constructors.rst
index c95ecc488..b3319eafb 100644
--- a/docs/spec/constructors.rst
+++ b/docs/spec/constructors.rst
@@ -273,6 +273,29 @@ within a type annotation for the ``self`` parameter in an ``__init__`` method.
# The ``self`` annotation should result in a type error
def __init__(self: "MyClass4[T2, T1]") -> None: ...
+When the class being constructed is not explicitly specialized and inherits an
+``__init__`` method whose ``self`` annotation names a specialization of a base
+class, type checkers should solve the type parameters the class passes to that
+base class from the annotation. If the class's specialization of that base
+class is not assignable to the annotation, binding fails.
+
+ ::
+
+ class MyClass5[T1, T2]:
+ def __init__(self: "MyClass5[int, str]") -> None: ...
+
+ class MyClass6[T1, T2](MyClass5[T1, T2]): ...
+
+ assert_type(MyClass6(), MyClass6[int, str])
+
+ class MyClass7[T1, T2, T3](MyClass5[T3, T2]): ...
+
+ assert_type(MyClass7(), MyClass7[Any, str, int])
+
+ class MyClass8[T](MyClass5[list[T], T]): ...
+
+ MyClass8() # Type error
+
Classes Without ``__new__`` and ``__init__`` Methods
----------------------------------------------------
@@ -284,11 +307,11 @@ does not inherit either of these methods from a base class other than
::
- class MyClass5:
+ class MyClass9:
pass
- MyClass5() # OK
- MyClass5(1) # Type error
+ MyClass9() # OK
+ MyClass9(1) # Type error
Constructor Calls for type[T]
From b6f4cb5b92ad591017ad11a3e31632d38e23acf7 Mon Sep 17 00:00:00 2001
From: crypt0lith <118923461+crypt0lith@users.noreply.github.com>
Date: Fri, 13 Nov 2026 21:15:22 -0600
Subject: [PATCH 2/2] bind after __new__, return subclass from converted
constructor
---
.../results/mypy/constructors_call_init.toml | 29 +++++----
.../results/mypy/constructors_callable.toml | 6 ++
.../pycroscope/constructors_call_init.toml | 29 +++++----
.../pycroscope/constructors_callable.toml | 9 ++-
.../pyrefly/constructors_call_init.toml | 22 ++++---
.../pyrefly/constructors_callable.toml | 9 ++-
.../pyright/constructors_call_init.toml | 28 +++++----
.../pyright/constructors_callable.toml | 9 ++-
conformance/results/results.html | 61 ++++++++++++++-----
.../results/ty/constructors_call_init.toml | 18 +++---
.../results/ty/constructors_callable.toml | 4 ++
.../results/zuban/constructors_call_init.toml | 23 ++++---
.../results/zuban/constructors_callable.toml | 9 ++-
conformance/tests/constructors_call_init.py | 46 +++++++++++---
conformance/tests/constructors_callable.py | 22 +++++++
docs/spec/constructors.rst | 27 +++++---
16 files changed, 255 insertions(+), 96 deletions(-)
diff --git a/conformance/results/mypy/constructors_call_init.toml b/conformance/results/mypy/constructors_call_init.toml
index 9ea5819df..d64e6b248 100644
--- a/conformance/results/mypy/constructors_call_init.toml
+++ b/conformance/results/mypy/constructors_call_init.toml
@@ -6,19 +6,22 @@ Does not solve a subclass's type parameters from the self annotation of an inher
"""
conformance_automated = "Fail"
errors_diff = """
-Line 56: Expected 1 errors
-Line 107: Expected 1 errors
-Line 145: Expected 1 errors
-Line 157: Expected 1 errors
-Line 73: Unexpected errors ['constructors_call_init.py:73: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]']
-Line 127: Unexpected errors ['constructors_call_init.py:127: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]']
-Line 134: Unexpected errors ['constructors_call_init.py:134: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]']
+Line 57: Expected 1 errors
+Line 108: Expected 1 errors
+Line 147: Expected 1 errors
+Line 159: Expected 1 errors
+Line 167: Expected 1 errors
+Line 74: Unexpected errors ['constructors_call_init.py:74: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]']
+Line 129: Unexpected errors ['constructors_call_init.py:129: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]']
+Line 136: Unexpected errors ['constructors_call_init.py:136: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]']
+Line 189: Unexpected errors ['constructors_call_init.py:189: error: Expression is of type "Class20[int]", not "Class20[int | None]" [assert-type]']
"""
output = """
-constructors_call_init.py:21: error: Argument 1 to "Class1" has incompatible type "float"; expected "int" [arg-type]
-constructors_call_init.py:42: error: Argument 1 to "Class3" has incompatible type "Class2[Never]"; expected "Class3 | None" [arg-type]
-constructors_call_init.py:73: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]
-constructors_call_init.py:127: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]
-constructors_call_init.py:134: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]
-constructors_call_init.py:179: error: Too many arguments for "Class11" [call-arg]
+constructors_call_init.py:22: error: Argument 1 to "Class1" has incompatible type "float"; expected "int" [arg-type]
+constructors_call_init.py:43: error: Argument 1 to "Class3" has incompatible type "Class2[Never]"; expected "Class3 | None" [arg-type]
+constructors_call_init.py:74: error: Expression is of type "Class5[list[int]]", not "Class5[int]" [assert-type]
+constructors_call_init.py:129: error: Expression is of type "Class13[Never, Never]", not "Class13[int, str]" [assert-type]
+constructors_call_init.py:136: error: Expression is of type "Class14[Never, Never, Never]", not "Class14[Any, str, int]" [assert-type]
+constructors_call_init.py:189: error: Expression is of type "Class20[int]", not "Class20[int | None]" [assert-type]
+constructors_call_init.py:211: error: Too many arguments for "Class11" [call-arg]
"""
diff --git a/conformance/results/mypy/constructors_callable.toml b/conformance/results/mypy/constructors_callable.toml
index c477fd6b8..f38c520f2 100644
--- a/conformance/results/mypy/constructors_callable.toml
+++ b/conformance/results/mypy/constructors_callable.toml
@@ -3,6 +3,7 @@ notes = """
Does not generate a union type for `__new__` and `__init__` when converting class to callable.
Does not ignore `__init__` based on `__new__` return type when converting class to callable.
Does not support `__new__` return type that is different from class being constructed.
+Does not solve a subclass's type parameters from the self annotation of an inherited `__init__` method when converting class to callable.
"""
conformance_automated = "Fail"
errors_diff = """
@@ -14,6 +15,8 @@ Line 107: Unexpected errors ['constructors_callable.py:107: error: Expression is
Line 118: Unexpected errors ['constructors_callable.py:118: error: Incompatible return type for "__new__" (returns "Class6Proxy", but must return a subtype of "Class6") [misc]']
Line 128: Unexpected errors ['constructors_callable.py:128: error: Expression is of type "Class6", not "Class6Proxy" [assert-type]', 'constructors_callable.py:128: error: Too few arguments [call-arg]']
Line 145: Unexpected errors ['constructors_callable.py:145: error: Expression is of type "Class6Any", not "Any" [assert-type]', 'constructors_callable.py:145: error: Too few arguments [call-arg]']
+Line 219: Unexpected errors ['constructors_callable.py:219: error: Need type annotation for "r11" [var-annotated]']
+Line 221: Unexpected errors ['constructors_callable.py:221: error: Expression is of type "Class11[Any, Any]", not "Class11[int, str]" [assert-type]']
"""
output = """
constructors_callable.py:36: note: Revealed type is "def (x: int) -> constructors_callable.Class1"
@@ -46,4 +49,7 @@ constructors_callable.py:187: error: Cannot infer function type argument [misc]
constructors_callable.py:196: note: Revealed type is "def [T] (x: list[T], y: list[T]) -> constructors_callable.Class9"
constructors_callable.py:197: error: Argument 2 has incompatible type "str"; expected "list[str]" [arg-type]
constructors_callable.py:199: error: Cannot infer function type argument [misc]
+constructors_callable.py:219: error: Need type annotation for "r11" [var-annotated]
+constructors_callable.py:220: note: Revealed type is "def () -> constructors_callable.Class11[Any, Any]"
+constructors_callable.py:221: error: Expression is of type "Class11[Any, Any]", not "Class11[int, str]" [assert-type]
"""
diff --git a/conformance/results/pycroscope/constructors_call_init.toml b/conformance/results/pycroscope/constructors_call_init.toml
index 176d24f13..77cbfee47 100644
--- a/conformance/results/pycroscope/constructors_call_init.toml
+++ b/conformance/results/pycroscope/constructors_call_init.toml
@@ -5,17 +5,24 @@ Does not report errors during binding to the self parameter of an inherited `__i
"""
conformance_automated = "Fail"
errors_diff = """
-Line 145: Expected 1 errors
-Line 157: Expected 1 errors
-Line 127: Unexpected errors ['./constructors_call_init.py:127:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]']
-Line 134: Unexpected errors ['./constructors_call_init.py:134:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]']
+Line 147: Expected 1 errors
+Line 159: Expected 1 errors
+Line 167: Expected 1 errors
+Line 129: Unexpected errors ['./constructors_call_init.py:129:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]']
+Line 136: Unexpected errors ['./constructors_call_init.py:136:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]']
+Line 187: Unexpected errors ['./constructors_call_init.py:187:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int]']
+Line 188: Unexpected errors ['./constructors_call_init.py:188:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int]']
+Line 189: Unexpected errors ['./constructors_call_init.py:189:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int | None]']
"""
output = """
-./constructors_call_init.py:21:12: Incompatible argument type for x: expected int but got Literal[1.0] [incompatible_argument]
-./constructors_call_init.py:42:7: Incompatible argument type for x: expected ./constructors_call_init.py.Class3 | None but got ./constructors_call_init.py.Class2 [incompatible_argument]
-./constructors_call_init.py:56:0: Missing required positional argument '%self' [incompatible_call]
-./constructors_call_init.py:107:17: Class-scoped type variables are not allowed in __init__ self annotation [invalid_self_usage]
-./constructors_call_init.py:127:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]
-./constructors_call_init.py:134:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]
-./constructors_call_init.py:179:0: Takes 0 positional arguments but 1 were given [incompatible_call]
+./constructors_call_init.py:22:12: Incompatible argument type for x: expected int but got Literal[1.0] [incompatible_argument]
+./constructors_call_init.py:43:7: Incompatible argument type for x: expected ./constructors_call_init.py.Class3 | None but got ./constructors_call_init.py.Class2 [incompatible_argument]
+./constructors_call_init.py:57:0: Missing required positional argument '%self' [incompatible_call]
+./constructors_call_init.py:108:17: Class-scoped type variables are not allowed in __init__ self annotation [invalid_self_usage]
+./constructors_call_init.py:129:12: ./constructors_call_init.py.Class13~[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class13[int, str]
+./constructors_call_init.py:136:12: ./constructors_call_init.py.Class14~[Any[generic_argument], Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class14[Any[explicit], str, int]
+./constructors_call_init.py:187:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int]
+./constructors_call_init.py:188:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int]
+./constructors_call_init.py:189:12: ./constructors_call_init.py.Class20~[Any[generic_argument]] is not equivalent to ./constructors_call_init.py.Class20[int | None]
+./constructors_call_init.py:211:0: Takes 0 positional arguments but 1 were given [incompatible_call]
"""
diff --git a/conformance/results/pycroscope/constructors_callable.toml b/conformance/results/pycroscope/constructors_callable.toml
index c9dbd4a39..58c72ec7d 100644
--- a/conformance/results/pycroscope/constructors_callable.toml
+++ b/conformance/results/pycroscope/constructors_callable.toml
@@ -1,5 +1,10 @@
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Does not solve a subclass's type parameters from the self annotation of an inherited `__init__` method when converting class to callable.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 221: Unexpected errors ['./constructors_callable.py:221:12: ./constructors_callable.py.Class11[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_callable.py.Class11[int, str]']
"""
output = """
./constructors_callable.py:36:12: Revealed type is '(x: int) -> ./constructors_callable.py.Class1' [reveal_type]
@@ -26,4 +31,6 @@ output = """
./constructors_callable.py:196:12: Revealed type is '(x: list[~T@./constructors_callable.py.Class9.__init__..__init__], y: list[~T@./constructors_callable.py.Class9.__init__..__init__]) -> ./constructors_callable.py.Class9' [reveal_type]
./constructors_callable.py:197:9: Incompatible argument type for y: expected list[~T@./constructors_callable.py.Class9.__init__..__init__] but got Literal['not a list'] [incompatible_argument]
./constructors_callable.py:199:0: Cannot resolve type variables [incompatible_call]
+./constructors_callable.py:220:12: Revealed type is '() -> ./constructors_callable.py.Class11[~T1@./constructors_callable.py.Class11, ~T2@./constructors_callable.py.Class11]' [reveal_type]
+./constructors_callable.py:221:12: ./constructors_callable.py.Class11[Any[generic_argument], Any[generic_argument]] is not equivalent to ./constructors_callable.py.Class11[int, str]
"""
diff --git a/conformance/results/pyrefly/constructors_call_init.toml b/conformance/results/pyrefly/constructors_call_init.toml
index ede5543ca..fca07cf10 100644
--- a/conformance/results/pyrefly/constructors_call_init.toml
+++ b/conformance/results/pyrefly/constructors_call_init.toml
@@ -1,13 +1,17 @@
-conformant = "Pass"
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Does not report errors during binding to the self parameter of an inherited `__init__` method when the class is specialized via the `__new__` method return type.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 167: Expected 1 errors
"""
output = """
-ERROR constructors_call_init.py:21:13-16: Argument `float` is not assignable to parameter `x` with type `int` in function `Class1.__init__` [bad-argument-type]
-ERROR constructors_call_init.py:42:8-20: Argument `Class2[@_]` is not assignable to parameter `x` with type `Class3 | None` in function `Class2.__init__` [bad-argument-type]
-ERROR constructors_call_init.py:56:12-14: Argument `Class4[str]` is not assignable to parameter `self` with type `Class4[int]` in function `Class4.__init__` [bad-argument-type]
-ERROR constructors_call_init.py:107:9-17: `__init__` method self type cannot reference class type parameters `T2`, `T1` [invalid-annotation]
-ERROR constructors_call_init.py:145:8-10: Argument `Class15[@_]` is not assignable to parameter `self` with type `Class12[int, str]` in function `Class12.__init__` [bad-argument-type]
-ERROR constructors_call_init.py:157:9-10: Argument `Literal[1]` is not assignable to parameter `value` with type `str` in function `Class16.__init__` [bad-argument-type]
-ERROR constructors_call_init.py:179:9-10: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count]
+ERROR constructors_call_init.py:22:13-16: Argument `float` is not assignable to parameter `x` with type `int` in function `Class1.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:43:8-20: Argument `Class2[@_]` is not assignable to parameter `x` with type `Class3 | None` in function `Class2.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:57:12-14: Argument `Class4[str]` is not assignable to parameter `self` with type `Class4[int]` in function `Class4.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:108:9-17: `__init__` method self type cannot reference class type parameters `T2`, `T1` [invalid-annotation]
+ERROR constructors_call_init.py:147:8-10: Argument `Class15[@_]` is not assignable to parameter `self` with type `Class12[int, str]` in function `Class12.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:159:9-10: Argument `Literal[1]` is not assignable to parameter `value` with type `str` in function `Class16.__init__` [bad-argument-type]
+ERROR constructors_call_init.py:211:9-10: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count]
"""
diff --git a/conformance/results/pyrefly/constructors_callable.toml b/conformance/results/pyrefly/constructors_callable.toml
index e89288ee3..86615c2d4 100644
--- a/conformance/results/pyrefly/constructors_callable.toml
+++ b/conformance/results/pyrefly/constructors_callable.toml
@@ -1,6 +1,10 @@
-conformant = "Pass"
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Returns the base class from the self annotation of an inherited `__init__` method when converting class to callable.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 221: Unexpected errors ['assert_type(Class10[int, str], Class11[int, str]) failed [assert-type]']
"""
output = """
ERROR constructors_callable.py:38:3-5: Missing argument `x` [missing-argument]
@@ -20,4 +24,5 @@ ERROR constructors_callable.py:185:10-22: Argument `Literal['not a list']` is no
ERROR constructors_callable.py:187:9-13: Argument `list[str]` is not assignable to parameter `y` with type `list[int]` [bad-argument-type]
ERROR constructors_callable.py:197:10-22: Argument `Literal['not a list']` is not assignable to parameter `y` with type `list[str]` [bad-argument-type]
ERROR constructors_callable.py:199:9-13: Argument `list[str]` is not assignable to parameter `y` with type `list[int]` [bad-argument-type]
+ERROR constructors_callable.py:221:12-38: assert_type(Class10[int, str], Class11[int, str]) failed [assert-type]
"""
diff --git a/conformance/results/pyright/constructors_call_init.toml b/conformance/results/pyright/constructors_call_init.toml
index 2a521455a..7f9fc261d 100644
--- a/conformance/results/pyright/constructors_call_init.toml
+++ b/conformance/results/pyright/constructors_call_init.toml
@@ -5,25 +5,31 @@ Does not report an error when a subclass's specialization of a base class is not
"""
conformance_automated = "Fail"
errors_diff = """
-Line 145: Expected 1 errors
-Line 127: Unexpected errors ['constructors_call_init.py:127:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)']
-Line 134: Unexpected errors ['constructors_call_init.py:134:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)']
+Line 147: Expected 1 errors
+Line 129: Unexpected errors ['constructors_call_init.py:129:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)']
+Line 136: Unexpected errors ['constructors_call_init.py:136:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)']
+Line 189: Unexpected errors ['constructors_call_init.py:189:13 - error: "assert_type" mismatch: expected "Class20[int | None]" but received "Class20[int]" (reportAssertTypeFailure)']
"""
output = """
-constructors_call_init.py:21:13 - error: Argument of type "float" cannot be assigned to parameter "x" of type "int" in function "__init__"
+constructors_call_init.py:22:13 - error: Argument of type "float" cannot be assigned to parameter "x" of type "int" in function "__init__"
"float" is not assignable to "int" (reportArgumentType)
-constructors_call_init.py:42:8 - error: Argument of type "Class2[Unknown]" cannot be assigned to parameter "x" of type "Class3 | None" in function "__init__"
+constructors_call_init.py:43:8 - error: Argument of type "Class2[Unknown]" cannot be assigned to parameter "x" of type "Class3 | None" in function "__init__"
Type "Class2[Unknown]" is not assignable to type "Class3 | None"
"Class2[Unknown]" is not assignable to "Class3"
"Class2[Unknown]" is not assignable to "None" (reportArgumentType)
-constructors_call_init.py:56:1 - error:
+constructors_call_init.py:57:1 - error:
Could not bind method "__init__" because "Class4[str]" is not assignable to parameter "self"
"Class4[str]" is not assignable to "Class4[int]"
Type parameter "T@Class4" is invariant, but "str" is not the same as "int" (reportGeneralTypeIssues)
-constructors_call_init.py:107:24 - warning: Type annotation for "self" parameter of "__init__" method cannot contain class-scoped type variables (reportInvalidTypeVarUse)
-constructors_call_init.py:127:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)
-constructors_call_init.py:134:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)
-constructors_call_init.py:157:9 - error: Argument of type "Literal[1]" cannot be assigned to parameter "value" of type "str" in function "__init__"
+constructors_call_init.py:108:24 - warning: Type annotation for "self" parameter of "__init__" method cannot contain class-scoped type variables (reportInvalidTypeVarUse)
+constructors_call_init.py:129:13 - error: "assert_type" mismatch: expected "Class13[int, str]" but received "Class13[Unknown, Unknown]" (reportAssertTypeFailure)
+constructors_call_init.py:136:13 - error: "assert_type" mismatch: expected "Class14[Any, str, int]" but received "Class14[Unknown, Unknown, Unknown]" (reportAssertTypeFailure)
+constructors_call_init.py:159:9 - error: Argument of type "Literal[1]" cannot be assigned to parameter "value" of type "str" in function "__init__"
"Literal[1]" is not assignable to "str" (reportArgumentType)
-constructors_call_init.py:179:9 - error: Expected 0 positional arguments (reportCallIssue)
+constructors_call_init.py:167:1 - error:
+ Could not bind method "__init__" because "Class18[str, str]" is not assignable to parameter "self"
+ "Class18[str, str]" is not assignable to "Class12[int, str]"
+ Type parameter "T1@Class12" is invariant, but "str" is not the same as "int" (reportGeneralTypeIssues)
+constructors_call_init.py:189:13 - error: "assert_type" mismatch: expected "Class20[int | None]" but received "Class20[int]" (reportAssertTypeFailure)
+constructors_call_init.py:211:9 - error: Expected 0 positional arguments (reportCallIssue)
"""
diff --git a/conformance/results/pyright/constructors_callable.toml b/conformance/results/pyright/constructors_callable.toml
index 901fe77b0..422234efa 100644
--- a/conformance/results/pyright/constructors_callable.toml
+++ b/conformance/results/pyright/constructors_callable.toml
@@ -1,5 +1,10 @@
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Returns the base class from the self annotation of an inherited `__init__` method when converting class to callable.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 221: Unexpected errors ['constructors_callable.py:221:13 - error: "assert_type" mismatch: expected "Class11[int, str]" but received "Class10[int, str]" (reportAssertTypeFailure)']
"""
output = """
constructors_callable.py:36:13 - information: Type of "r1" is "(x: int) -> Class1"
@@ -33,4 +38,6 @@ constructors_callable.py:197:10 - error: Argument of type "Literal['not a list']
"Literal['not a list']" is not assignable to "list[str]" (reportArgumentType)
constructors_callable.py:199:10 - error: Argument of type "list[str]" cannot be assigned to parameter "y" of type "list[T@__init__]"
"Literal['']" is not assignable to "int" (reportArgumentType)
+constructors_callable.py:220:13 - information: Type of "r11" is "() -> Class10[int, str]"
+constructors_callable.py:221:13 - error: "assert_type" mismatch: expected "Class11[int, str]" but received "Class10[int, str]" (reportAssertTypeFailure)
"""
diff --git a/conformance/results/results.html b/conformance/results/results.html
index 87833cefe..c1902a67f 100644
--- a/conformance/results/results.html
+++ b/conformance/results/results.html
@@ -1513,7 +1513,12 @@ Python Type System Conformance Test Results
- Does not report errors during binding to the self parameter of an inherited
__init__ method.
|
- Pass |
+
+ Partial
+
+ - Does not report errors during binding to the self parameter of an inherited
__init__ method when the class is specialized via the __new__ method return type.
+
+ |
Partial
@@ -1525,9 +1530,15 @@ Python Type System Conformance Test Results
Partial
- Does not reject invalid argument types to an inherited constructor in a specialized subclass of a generic superclass.
+ - Does not report errors during binding to the self parameter of an inherited
__init__ method when the class is specialized via the __new__ method return type.
+
+ |
+
+ Partial
+
+ - Does not report errors during binding to the self parameter of an inherited
__init__ method when the class is specialized via the __new__ method return type.
|
- Pass |
| constructors_call_metaclass |
@@ -1582,20 +1593,42 @@ Python Type System Conformance Test Results
Does not generate a union type for __new__ and __init__ when converting class to callable.
Does not ignore __init__ based on __new__ return type when converting class to callable.
Does not support __new__ return type that is different from class being constructed.
+ Does not solve a subclass's type parameters from the self annotation of an inherited __init__ method when converting class to callable.
+
+
+
+ Partial
+
+ - Does not solve a subclass's type parameters from the self annotation of an inherited
__init__ method when converting class to callable.
+
+ |
+
+ Partial
+
+ - Returns the base class from the self annotation of an inherited
__init__ method when converting class to callable.
+
+ |
+
+ Partial
+
+ - Returns the base class from the self annotation of an inherited
__init__ method when converting class to callable.
|
- Pass |
- Pass |
- Pass |
Partial
- Does not include
__init__ when __new__ returns Self.
- Does not ignore
__init__ when __new__ returns Any.
- Unions overload return types.
+ - Returns the base class from the self annotation of an inherited
__init__ method when converting class to callable.
+
+ |
+
+ Partial
+
+ - Returns the base class from the self annotation of an inherited
__init__ method when converting class to callable.
|
- Pass |
| constructors_consistency |
@@ -1614,11 +1647,11 @@ Python Type System Conformance Test Results
|
3 / 6 • 50.0% |
- 5.5 / 6 • 91.7% |
- 6 / 6 • 100.0% |
- 5.5 / 6 • 91.7% |
5 / 6 • 83.3% |
- 6 / 6 • 100.0% |
+ 5 / 6 • 83.3% |
+ 5 / 6 • 83.3% |
+ 5 / 6 • 83.3% |
+ 5 / 6 • 83.3% |
@@ -2524,11 +2557,11 @@ Python Type System Conformance Test Results
|
110.5 / 146 • 75.7% |
- 138.5 / 146 • 94.9% |
- 142.5 / 146 • 97.6% |
- 140 / 146 • 95.9% |
+ 138 / 146 • 94.5% |
+ 141.5 / 146 • 96.9% |
+ 139.5 / 146 • 95.5% |
141.5 / 146 • 96.9% |
- 146 / 146 • 100.0% |
+ 145 / 146 • 99.3% |
diff --git a/conformance/results/ty/constructors_call_init.toml b/conformance/results/ty/constructors_call_init.toml
index 8fa0d4532..1fc1dd20d 100644
--- a/conformance/results/ty/constructors_call_init.toml
+++ b/conformance/results/ty/constructors_call_init.toml
@@ -2,16 +2,18 @@ conformance_automated = "Fail"
conformant = "Partial"
notes = """
Does not reject invalid argument types to an inherited constructor in a specialized subclass of a generic superclass.
+Does not report errors during binding to the self parameter of an inherited `__init__` method when the class is specialized via the `__new__` method return type.
"""
errors_diff = """
-Line 42: Expected 1 errors
+Line 43: Expected 1 errors
+Line 167: Expected 1 errors
"""
output = """
-constructors_call_init.py:21:13: error[invalid-argument-type] Argument to `Class1.__init__` is incorrect: Expected `int`, found `float*`
-constructors_call_init.py:56:1: error[invalid-argument-type] Argument to `Class4.__init__` is incorrect: Expected `Class4[int]`, found `Class4[str]`
-constructors_call_init.py:107:32: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T2` from an outer scope
-constructors_call_init.py:107:36: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T1` from an outer scope
-constructors_call_init.py:145:1: error[invalid-argument-type] Argument to `Class12.__init__` is incorrect: Expected `Class12[int, str]`, found `Class15[str]`
-constructors_call_init.py:157:9: error[invalid-argument-type] Argument to `Class16.__init__` is incorrect: Expected `str`, found `Literal[1]`
-constructors_call_init.py:179:9: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2
+constructors_call_init.py:22:13: error[invalid-argument-type] Argument to `Class1.__init__` is incorrect: Expected `int`, found `float*`
+constructors_call_init.py:57:1: error[invalid-argument-type] Argument to `Class4.__init__` is incorrect: Expected `Class4[int]`, found `Class4[str]`
+constructors_call_init.py:108:32: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T2` from an outer scope
+constructors_call_init.py:108:36: error[invalid-init-type-variable] First parameter of `__init__` cannot use type variable `T1` from an outer scope
+constructors_call_init.py:147:1: error[invalid-argument-type] Argument to `Class12.__init__` is incorrect: Expected `Class12[int, str]`, found `Class15[str]`
+constructors_call_init.py:159:9: error[invalid-argument-type] Argument to `Class16.__init__` is incorrect: Expected `str`, found `Literal[1]`
+constructors_call_init.py:211:9: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2
"""
diff --git a/conformance/results/ty/constructors_callable.toml b/conformance/results/ty/constructors_callable.toml
index 7f22bcaae..c3e7d204a 100644
--- a/conformance/results/ty/constructors_callable.toml
+++ b/conformance/results/ty/constructors_callable.toml
@@ -4,6 +4,7 @@ notes = """
Does not include `__init__` when `__new__` returns `Self`.
Does not ignore `__init__` when `__new__` returns `Any`.
Unions overload return types.
+Returns the base class from the self annotation of an inherited `__init__` method when converting class to callable.
"""
errors_diff = """
Line 66: Expected 1 errors
@@ -13,6 +14,7 @@ Line 143: Unexpected errors ["constructors_callable.py:143:27: error[invalid-arg
Line 145: Unexpected errors ['constructors_callable.py:145:1: error[type-assertion-failure] Type `Any | Class6Any` does not match asserted type `Any`']
Line 166: Unexpected errors ['constructors_callable.py:166:1: error[type-assertion-failure] Type `Class7[int] | Class7[str]` does not match asserted type `Class7[int]`']
Line 167: Unexpected errors ['constructors_callable.py:167:1: error[type-assertion-failure] Type `Class7[int] | Class7[str]` does not match asserted type `Class7[str]`']
+Line 221: Unexpected errors ['constructors_callable.py:221:1: error[type-assertion-failure] Type `Class10[int, str]` does not match asserted type `Class11[int, str]`']
"""
output = """
constructors_callable.py:36:13: info[revealed-type] Revealed type: `(x: int) -> Class1`
@@ -40,4 +42,6 @@ constructors_callable.py:184:13: info[revealed-type] Revealed type: `[T](x: list
constructors_callable.py:185:10: error[invalid-argument-type] Argument is incorrect: Expected `list[str]`, found `Literal["not a list"]`
constructors_callable.py:196:13: info[revealed-type] Revealed type: `[T](x: list[T], y: list[T]) -> Class9`
constructors_callable.py:197:10: error[invalid-argument-type] Argument is incorrect: Expected `list[str]`, found `Literal["not a list"]`
+constructors_callable.py:220:13: info[revealed-type] Revealed type: `[T1, T2]() -> Class10[int, str]`
+constructors_callable.py:221:1: error[type-assertion-failure] Type `Class10[int, str]` does not match asserted type `Class11[int, str]`
"""
diff --git a/conformance/results/zuban/constructors_call_init.toml b/conformance/results/zuban/constructors_call_init.toml
index cd9be46f4..90d0f26fe 100644
--- a/conformance/results/zuban/constructors_call_init.toml
+++ b/conformance/results/zuban/constructors_call_init.toml
@@ -1,13 +1,18 @@
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Does not report errors during binding to the self parameter of an inherited `__init__` method when the class is specialized via the `__new__` method return type.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 167: Expected 1 errors
"""
output = """
-constructors_call_init.py:21: error: Argument 1 to "Class1" has incompatible type "float"; expected "int" [arg-type]
-constructors_call_init.py:42: error: Argument 1 to "Class3" has incompatible type "Class2[int]"; expected "Self | None" [arg-type]
-constructors_call_init.py:56: error: Invalid self type in __init__ [call-arg]
-constructors_call_init.py:107: error: The type of self "T1" has type vars in non standard positions for class "Class8" [misc]
-constructors_call_init.py:107: error: The type of self "T2" has type vars in non standard positions for class "Class8" [misc]
-constructors_call_init.py:145: error: Invalid self type in __init__ [call-arg]
-constructors_call_init.py:157: error: Argument 1 to "Class17" has incompatible type "int"; expected "str" [arg-type]
-constructors_call_init.py:179: error: Too many arguments for "Class11" [call-arg]
+constructors_call_init.py:22: error: Argument 1 to "Class1" has incompatible type "float"; expected "int" [arg-type]
+constructors_call_init.py:43: error: Argument 1 to "Class3" has incompatible type "Class2[int]"; expected "Self | None" [arg-type]
+constructors_call_init.py:57: error: Invalid self type in __init__ [call-arg]
+constructors_call_init.py:108: error: The type of self "T1" has type vars in non standard positions for class "Class8" [misc]
+constructors_call_init.py:108: error: The type of self "T2" has type vars in non standard positions for class "Class8" [misc]
+constructors_call_init.py:147: error: Invalid self type in __init__ [call-arg]
+constructors_call_init.py:159: error: Argument 1 to "Class17" has incompatible type "int"; expected "str" [arg-type]
+constructors_call_init.py:211: error: Too many arguments for "Class11" [call-arg]
"""
diff --git a/conformance/results/zuban/constructors_callable.toml b/conformance/results/zuban/constructors_callable.toml
index 569f40b9a..79afc2297 100644
--- a/conformance/results/zuban/constructors_callable.toml
+++ b/conformance/results/zuban/constructors_callable.toml
@@ -1,5 +1,10 @@
-conformance_automated = "Pass"
+conformant = "Partial"
+notes = """
+Returns the base class from the self annotation of an inherited `__init__` method when converting class to callable.
+"""
+conformance_automated = "Fail"
errors_diff = """
+Line 221: Unexpected errors ['constructors_callable.py:221: error: Expression is of type "Class10[int, str]", not "Class11[int, str]" [misc]']
"""
output = """
constructors_callable.py:36: note: Revealed type is "def (x: builtins.int) -> tests.constructors_callable.Class1"
@@ -26,4 +31,6 @@ constructors_callable.py:187: error: List item 0 has incompatible type "str"; ex
constructors_callable.py:196: note: Revealed type is "def [T] (x: builtins.list[T], y: builtins.list[T]) -> tests.constructors_callable.Class9"
constructors_callable.py:197: error: Argument 2 has incompatible type "str"; expected "list[str]" [arg-type]
constructors_callable.py:199: error: List item 0 has incompatible type "str"; expected "int" [list-item]
+constructors_callable.py:220: note: Revealed type is "def () -> tests.constructors_callable.Class10[builtins.int, builtins.str]"
+constructors_callable.py:221: error: Expression is of type "Class10[int, str]", not "Class11[int, str]" [misc]
"""
diff --git a/conformance/tests/constructors_call_init.py b/conformance/tests/constructors_call_init.py
index 0e4c64025..dcbe2bf69 100644
--- a/conformance/tests/constructors_call_init.py
+++ b/conformance/tests/constructors_call_init.py
@@ -5,7 +5,8 @@
# Specification: https://typing.readthedocs.io/en/latest/spec/constructors.html#init-method
-from typing import Any, Generic, Self, TypeVar, assert_type, overload
+from typing import Any, Generic, Literal, Self, assert_type, overload
+from typing_extensions import TypeVar
T = TypeVar("T")
@@ -108,10 +109,11 @@ def __init__(self: "Class8[T2, T1]") -> None: # E
pass
-# > When the class being constructed is not explicitly specialized and inherits
-# > an __init__ method whose self annotation names a specialization of a base
-# > class, type checkers should solve the type parameters the class passes to
-# > that base class from the annotation.
+# > When the class being constructed inherits an __init__ method whose self
+# > annotation names a specialization of a base class, a type checker should
+# > bind the class's specialization of that base class to the annotation.
+# > Type parameters of the class that are not specialized explicitly or via
+# > the __new__ method return type should be solved from the annotation.
T3 = TypeVar("T3")
@@ -134,8 +136,8 @@ class Class14(Class12[T3, T2], Generic[T1, T2, T3]):
assert_type(Class14(), Class14[Any, str, int])
-# > If the class's specialization of that base class is not assignable to the
-# > annotation, binding fails.
+# > If the resulting specialization is not assignable to the annotation,
+# > binding fails.
class Class15(Class12[list[T], T]):
@@ -157,6 +159,36 @@ class Class17(Class16[str]):
Class17(1) # E
+class Class18(Class12[T1, T2]):
+ def __new__(cls) -> "Class18[str, str]":
+ raise NotImplementedError
+
+
+Class18() # E
+
+
+# Only the selected __init__ overload solves the subclass's type parameters.
+
+T4 = TypeVar("T4", default=int)
+
+
+class Class19(Generic[T]):
+ @overload
+ def __init__(self, *, null: Literal[False] = ...) -> None: ...
+ @overload
+ def __init__(self: "Class19[int | None]", *, null: Literal[True]) -> None: ...
+ def __init__(self, *, null: bool = False) -> None: ...
+
+
+class Class20(Class19[T4]):
+ pass
+
+
+assert_type(Class20(), Class20[int])
+assert_type(Class20(null=False), Class20[int])
+assert_type(Class20(null=True), Class20[int | None])
+
+
# > If a class does not define a __new__ method or __init__ method and does
# > not inherit either of these methods from a base class other than object,
# > a type checker should evaluate the argument list using the __new__ and
diff --git a/conformance/tests/constructors_callable.py b/conformance/tests/constructors_callable.py
index 0ec091e2d..99f32f331 100644
--- a/conformance/tests/constructors_callable.py
+++ b/conformance/tests/constructors_callable.py
@@ -197,3 +197,25 @@ def __init__(self, x: list[T], y: list[T]) -> None:
r9([""], "not a list") # E: no assignment of T makes the second argument valid
assert_type(r9([""], [""]), Class9)
r9([1], [""]) # E?: T = int | str is a potential solution
+
+
+# > If the __init__ method is inherited and its self annotation names a
+# > specialization of a base class, the return type is the class being
+# > constructed, specialized with the type arguments solved from that
+# > annotation, not the base class.
+
+T1 = TypeVar("T1")
+T2 = TypeVar("T2")
+
+
+class Class10(Generic[T1, T2]):
+ def __init__(self: "Class10[int, str]") -> None: ...
+
+
+class Class11(Class10[T1, T2]):
+ pass
+
+
+r11 = accepts_callable(Class11)
+reveal_type(r11) # `def () -> Class11[int, str]`
+assert_type(r11(), Class11[int, str])
diff --git a/docs/spec/constructors.rst b/docs/spec/constructors.rst
index b3319eafb..980382405 100644
--- a/docs/spec/constructors.rst
+++ b/docs/spec/constructors.rst
@@ -273,11 +273,12 @@ within a type annotation for the ``self`` parameter in an ``__init__`` method.
# The ``self`` annotation should result in a type error
def __init__(self: "MyClass4[T2, T1]") -> None: ...
-When the class being constructed is not explicitly specialized and inherits an
-``__init__`` method whose ``self`` annotation names a specialization of a base
-class, type checkers should solve the type parameters the class passes to that
-base class from the annotation. If the class's specialization of that base
-class is not assignable to the annotation, binding fails.
+When the class being constructed inherits an ``__init__`` method whose
+``self`` annotation names a specialization of a base class, a type checker
+should bind the class's specialization of that base class to the annotation.
+Type parameters of the class that are not specialized explicitly or via the
+``__new__`` method return type should be solved from the annotation. If the
+resulting specialization is not assignable to the annotation, binding fails.
::
@@ -296,6 +297,11 @@ class is not assignable to the annotation, binding fails.
MyClass8() # Type error
+ class MyClass9[T1, T2](MyClass5[T1, T2]):
+ def __new__(cls) -> "MyClass9[str, str]": ...
+
+ MyClass9() # Type error
+
Classes Without ``__new__`` and ``__init__`` Methods
----------------------------------------------------
@@ -307,11 +313,11 @@ does not inherit either of these methods from a base class other than
::
- class MyClass9:
+ class MyClass10:
pass
- MyClass9() # OK
- MyClass9(1) # Type error
+ MyClass10() # OK
+ MyClass10(1) # Type error
Constructor Calls for type[T]
@@ -423,7 +429,10 @@ constructor calls:
from a base class other than ``object``, a callable type should be synthesized
from the parameters of the ``__init__`` method after it is bound to the class
instance resulting from step 2. The return type of this synthesized callable
- should be the concrete value of ``Self``.
+ should be the concrete value of ``Self``. If the ``__init__`` method is
+ inherited and its ``self`` annotation names a specialization of a base
+ class, the return type is the class being constructed, specialized with the
+ type arguments solved from that annotation, not the base class.
5. If step 2 and 4 both produce no result because the class does not define or
inherit a ``__new__`` or ``__init__`` method from a class other than ``object``,