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

+ + + Partial + Pass - Pass - Pass + + Partial + + Partial - Pass + + Partial + + Partial + + + Partial + + + + Partial + + + + Partial + - Pass - Pass - Pass Partial + + + Partial + - 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``,