-
Notifications
You must be signed in to change notification settings - Fork 249
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add conformance tests for basic generic spec (#1553)
- Loading branch information
1 parent
0665b39
commit 3c02f03
Showing
11 changed files
with
453 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_basic.py:36: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:37: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:44: error: TypeVar cannot have only a single constraint [misc] | ||
generics_basic.py:48: error: Type variable "generics_basic.T" is unbound [valid-type] | ||
generics_basic.py:48: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_basic.py:48: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_basic.py:59: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:107: error: Duplicate type variables in Generic[...] or Protocol[...] [misc] | ||
generics_basic.py:140: error: Invalid index type "int" for "MyMap1[str, int]"; expected type "str" [index] | ||
generics_basic.py:141: error: Invalid index type "int" for "MyMap2[int, str]"; expected type "str" [index] | ||
generics_basic.py:167: error: Dynamic metaclass not supported for "GenericMetaInstance" [misc] | ||
generics_basic.py:167: error: Type variable "generics_basic.T" is unbound [valid-type] | ||
generics_basic.py:167: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_basic.py:167: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False negative on generic class nested within generic class with same type variable. | ||
""" | ||
output = """ | ||
generics_scoping.py:25: error: Argument 1 to "meth_2" of "MyClass" has incompatible type "str"; expected "int" [arg-type] | ||
generics_scoping.py:46: error: Type variable "generics_scoping.S" is unbound [valid-type] | ||
generics_scoping.py:46: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) | ||
generics_scoping.py:46: note: (Hint: Use "S" in function signature to bind "S" inside a function) | ||
generics_scoping.py:50: error: Type variable "generics_scoping.S" is unbound [valid-type] | ||
generics_scoping.py:50: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) | ||
generics_scoping.py:50: note: (Hint: Use "S" in function signature to bind "S" inside a function) | ||
generics_scoping.py:61: error: Free type variable expected in Generic[...] [misc] | ||
generics_scoping.py:74: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:74: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:74: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:80: error: Can't use bound type variable "T" to define generic alias [valid-type] | ||
generics_scoping.py:84: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:84: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:84: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:85: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:85: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:85: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:86: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:86: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:86: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False positives in examples using constrained type variables. | ||
False negative in custom map example. | ||
False positive using `iter`. | ||
False negative for generic metaclass. | ||
""" | ||
output = """ | ||
generics_basic.py:31:4 Incompatible return type [7]: Expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:31:15 Incompatible parameter type [6]: In call `bytes.__add__`, for 1st positional argument, expected `Union[array[typing.Any], bytearray, bytes, _CData, memoryview, mmap, PickleBuffer]` but got `Variable[AnyStr <: [str, bytes]]`. | ||
generics_basic.py:36:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:37:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `str`. | ||
generics_basic.py:44:0 Invalid type [31]: TypeVar can't have a single explicit constraint. Did you mean `bound=str`? | ||
generics_basic.py:48:0 Invalid type [31]: Expression `Variable[BadConstraint2 <: [str, Variable[generics_basic.T]]]` is not a valid type. Type variables cannot contain other type variables in their constraints. | ||
generics_basic.py:59:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:107:0 Duplicate type variables [59]: Duplicate type variable `T` in Generic[...]. | ||
generics_basic.py:161:25 Undefined attribute [16]: `typing.Iterator` has no attribute `__getitem__`. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False negative on generic class nested within generic function with same type variable. | ||
False negative on generic class nested within generic class with same type variable. | ||
""" | ||
output = """ | ||
generics_scoping.py:25:9 Incompatible parameter type [6]: In call `MyClass.meth_2`, for 1st positional argument, expected `int` but got `str`. | ||
generics_scoping.py:46:7 Invalid type variable [34]: The type variable `Variable[S]` isn't present in the function's parameters. | ||
generics_scoping.py:50:13 Invalid type variable [34]: The current class isn't generic with respect to the type variable `Variable[S]`. To reference the type variable, you can modify the class to inherit from `typing.Generic[S]`. | ||
generics_scoping.py:70:0 Uninitialized attribute [13]: Attribute `attr` is declared in class `Outer` to have type `Outer.Inner[Variable[T]]` but is never initialized. | ||
generics_scoping.py:73:4 Uninitialized attribute [13]: Attribute `x` is declared in class `Outer.AlsoBad` to have type `typing.List[Variable[T]]` but is never initialized. | ||
generics_scoping.py:74:11 Invalid type variable [34]: The current class isn't generic with respect to the type variable `Variable[T]`. To reference the type variable, you can modify the class to inherit from `typing.Generic[T]`. | ||
generics_scoping.py:80:4 Incompatible attribute type [8]: Attribute `alias` declared in class `Outer` has type `TypeAlias` but is used as type `Type[List[Variable[_T]]]`. | ||
generics_scoping.py:80:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. | ||
generics_scoping.py:84:13 Invalid type variable [34]: The type variable `Variable[T]` can only be used to annotate generic classes or functions. | ||
generics_scoping.py:85:13 Invalid type variable [34]: The type variable `Variable[T]` can only be used to annotate generic classes or functions. | ||
generics_scoping.py:86:5 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_basic.py:36:15 - error: Argument of type "bytes" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"bytes" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:37:15 - error: Argument of type "str" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"str" is incompatible with "bytes" (reportGeneralTypeIssues) | ||
generics_basic.py:44:44 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues) | ||
generics_basic.py:48:49 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_basic.py:48:49 - error: TypeVar constraint type cannot be generic | ||
generics_basic.py:59:15 - error: Argument of type "bytes" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"bytes" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:107:24 - error: Type arguments for "Generic" must be unique | ||
generics_basic.py:140:5 - error: Argument of type "Literal[0]" cannot be assigned to parameter "__key" of type "str" in function "__getitem__" | ||
"Literal[0]" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:141:5 - error: Argument of type "Literal[0]" cannot be assigned to parameter "__key" of type "str" in function "__getitem__" | ||
"Literal[0]" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:167:37 - error: Metaclass cannot be generic (reportGeneralTypeIssues) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_scoping.py:25:10 - error: Argument of type "Literal['a']" cannot be assigned to parameter "x" of type "int" in function "meth_2" | ||
"Literal['a']" is incompatible with "int" (reportGeneralTypeIssues) | ||
generics_scoping.py:46:13 - error: Type variable "S" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:50:19 - error: Type variable "S" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:61:29 - error: TypeVar "T" is already in use by an outer scope (reportGeneralTypeIssues) | ||
generics_scoping.py:71:24 - error: TypeVar "T" is already in use by an outer scope (reportGeneralTypeIssues) | ||
generics_scoping.py:74:17 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:80:5 - error: Generic type alias within class cannot use bound type variables T | ||
generics_scoping.py:84:14 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:85:19 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:86:6 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False positives in examples using constrained type variables. | ||
False negative for generic metaclass. | ||
""" | ||
output = """ | ||
File "generics_basic.py", line 31, in concat: bad return type [bad-return-type] | ||
Expected: MyStr | ||
Actually returned: str | ||
Called from (traceback): | ||
line 57, in test_concat_subtype | ||
File "generics_basic.py", line 36, in test_concat: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: str) | ||
Actually passed: (x, y: bytes) | ||
File "generics_basic.py", line 37, in test_concat: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: bytes) | ||
Actually passed: (x, y: str) | ||
File "generics_basic.py", line 44, in <module>: Invalid TypeVar: the number of constraints must be 0 or more than 1 [invalid-typevar] | ||
File "generics_basic.py", line 48, in <module>: Invalid TypeVar: constraint cannot contain TypeVars [invalid-typevar] | ||
File "generics_basic.py", line 57, in test_concat_subtype: MyStr [assert-type] | ||
Expected: str | ||
Actual: MyStr | ||
File "generics_basic.py", line 58, in test_concat_subtype: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: MyStr) | ||
Actually passed: (x, y: str) | ||
File "generics_basic.py", line 58, in test_concat_subtype: Any [assert-type] | ||
Expected: str | ||
Actual: Any | ||
File "generics_basic.py", line 59, in test_concat_subtype: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: MyStr) | ||
Actually passed: (x, y: bytes) | ||
File "generics_basic.py", line 107, in <module>: Invalid type annotation 'Generic' [invalid-annotation] | ||
Parameters to Generic[...] must all be unique | ||
File "generics_basic.py", line 140, in test_my_map: unsupported operand type(s) for item retrieval: MyMap1[str, int] and int [unsupported-operands] | ||
Function __getitem__ on MyMap1[str, int] expects str | ||
File "generics_basic.py", line 141, in test_my_map: unsupported operand type(s) for item retrieval: MyMap2[int, str] and int [unsupported-operands] | ||
Function __getitem__ on MyMap2[int, str] expects str | ||
File "generics_basic.py", line 161, in test_my_iterable_any: Iterator[nothing] [assert-type] | ||
Expected: Iterator | ||
Actual: Iterator[nothing] | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
conformant = "Pass" | ||
output = """ | ||
File "generics_scoping.py", line 9, in fun_1: bad return type [bad-return-type] | ||
Expected: int | ||
Actually returned: None | ||
Called from (traceback): | ||
line 12, in current file | ||
File "generics_scoping.py", line 10, in fun_2: bad return type [bad-return-type] | ||
Expected: str | ||
Actually returned: None | ||
Called from (traceback): | ||
line 13, in current file | ||
File "generics_scoping.py", line 20, in meth_1: bad return type [bad-return-type] | ||
Expected: int | ||
Actually returned: None | ||
Called from (traceback): | ||
line 24, in current file | ||
File "generics_scoping.py", line 25, in <module>: Function MyClass.meth_2 was called with the wrong arguments [wrong-arg-types] | ||
Expected: (self, x: int) | ||
Actually passed: (self, x: str) | ||
File "generics_scoping.py", line 35, in method: bad return type [bad-return-type] | ||
Expected: str | ||
Actually returned: None | ||
Called from (traceback): | ||
line 38, in current file | ||
File "generics_scoping.py", line 35, in method: bad return type [bad-return-type] | ||
Expected: bytes | ||
Actually returned: None | ||
Called from (traceback): | ||
line 39, in current file | ||
File "generics_scoping.py", line 46, in fun_3: Invalid type annotation 'List[S]' for z [invalid-annotation] | ||
TypeVar(s) 'S' not in scope for method 'fun_3' | ||
File "generics_scoping.py", line 50, in Bar: Invalid type annotation 'List[S]' for an_attr [invalid-annotation] | ||
TypeVar(s) 'S' not in scope for class 'Bar' | ||
File "generics_scoping.py", line 59, in fun_4: Invalid type annotation 'T' [invalid-annotation] | ||
Function [fun_4] and its nested generic class [MyGeneric] cannot use the same type variable T | ||
File "generics_scoping.py", line 70, in <module>: Invalid type annotation 'Outer' [invalid-annotation] | ||
Generic class [Outer] and its nested generic class [Bad] cannot use the same type variable T. | ||
File "generics_scoping.py", line 74, in AlsoBad: Invalid type annotation 'List[T]' for x [invalid-annotation] | ||
TypeVar(s) 'T' not in scope for class 'Outer.AlsoBad' | ||
File "generics_scoping.py", line 84, in <module>: Invalid type annotation 'T' for global_var1 [invalid-annotation] | ||
TypeVar(s) 'T' not in scope | ||
File "generics_scoping.py", line 85, in <module>: Invalid type annotation 'List[T]' for global_var2 [invalid-annotation] | ||
TypeVar(s) 'T' not in scope | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
""" | ||
Tests for basic usage of generics. | ||
""" | ||
|
||
# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#introduction | ||
|
||
from __future__ import annotations | ||
|
||
from collections.abc import Sequence | ||
from typing import Any, Generic, TypeVar, assert_type | ||
|
||
T = TypeVar('T') | ||
|
||
# > Generics can be parameterized by using a factory available in | ||
# > ``typing`` called ``TypeVar``. | ||
|
||
def first(l: Sequence[T]) -> T: | ||
return l[0] | ||
|
||
|
||
def test_first(seq_int: Sequence[int], seq_str: Sequence[str]) -> None: | ||
assert_type(first(seq_int), int) | ||
assert_type(first(seq_str), str) | ||
|
||
# > ``TypeVar`` supports constraining parametric types to a fixed set of | ||
# > possible types | ||
|
||
AnyStr = TypeVar('AnyStr', str, bytes) | ||
|
||
def concat(x: AnyStr, y: AnyStr) -> AnyStr: | ||
return x + y | ||
|
||
def test_concat(s: str, b: bytes, a: Any) -> None: | ||
concat(s, s) # OK | ||
concat(b, b) # OK | ||
concat(s, b) # Type error | ||
concat(b, s) # Type error | ||
|
||
concat(s, a) # OK | ||
concat(a, b) # OK | ||
|
||
# > Specifying a single constraint is disallowed. | ||
|
||
BadConstraint1 = TypeVar('BadConstraint1', str) # Type error | ||
|
||
# > Note: those types cannot be parameterized by type variables | ||
|
||
BadConstraint2 = TypeVar('BadConstraint2', str, T) # Type error | ||
|
||
# > Subtypes of types constrained by a type variable should be treated | ||
# > as their respective explicitly listed base types in the context of the | ||
# > type variable. | ||
|
||
class MyStr(str): ... | ||
|
||
def test_concat_subtype(s: str, b: bytes, a: Any, m: MyStr) -> None: | ||
assert_type(concat(m, m), str) | ||
assert_type(concat(m, s), str) | ||
concat(m, b) # Type error | ||
|
||
# TODO: should these be str or Any? | ||
# reveal_type(concat(m, a)) | ||
# reveal_type(concat(a, m)) | ||
|
||
# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#user-defined-generic-classes | ||
|
||
# > You can include a ``Generic`` base class to define a user-defined class | ||
# > as generic. | ||
|
||
from logging import Logger | ||
from collections.abc import Iterable | ||
|
||
class LoggedVar(Generic[T]): | ||
def __init__(self, value: T, name: str, logger: Logger) -> None: | ||
self.name = name | ||
self.logger = logger | ||
self.value = value | ||
|
||
def set(self, new: T) -> None: | ||
self.log('Set ' + repr(self.value)) | ||
self.value = new | ||
|
||
def get(self) -> T: | ||
self.log('Get ' + repr(self.value)) | ||
return self.value | ||
|
||
def log(self, message: str) -> None: | ||
self.logger.info('{}: {}'.format(self.name, message)) | ||
|
||
|
||
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: | ||
for var in vars: | ||
var.set(0) | ||
assert_type(var.get(), int) | ||
|
||
|
||
# > A generic type can have any number of type variables, and type variables | ||
# > may be constrained. | ||
|
||
S = TypeVar('S') | ||
|
||
class Pair1(Generic[T, S]): | ||
... | ||
|
||
# > Each type variable argument to ``Generic`` must be distinct. | ||
|
||
class Pair2(Generic[T, T]): # Type error | ||
... | ||
|
||
# > The ``Generic[T]`` base class is redundant in simple cases where you | ||
# > subclass some other generic class and specify type variables for its | ||
# > parameters. | ||
|
||
from collections.abc import Iterator, Mapping | ||
|
||
class MyIter1(Iterator[T]): | ||
... | ||
|
||
class MyIter2(Iterator[T], Generic[T]): | ||
... | ||
|
||
def test_my_iter(m1: MyIter1[int], m2: MyIter2[int]): | ||
assert_type(next(m1), int) | ||
assert_type(next(m2), int) | ||
|
||
|
||
K = TypeVar("K") | ||
V = TypeVar("V") | ||
|
||
class MyMap1(Mapping[K, V], Generic[K, V]): | ||
... | ||
|
||
class MyMap2(Mapping[K, V], Generic[V, K]): | ||
... | ||
|
||
def test_my_map(m1: MyMap1[str, int], m2: MyMap2[int, str]): | ||
assert_type(m1["key"], int) | ||
assert_type(m2["key"], int) | ||
|
||
m1[0] # Type error | ||
m2[0] # Type error | ||
|
||
# > You can use multiple inheritance with ``Generic`` | ||
|
||
from collections.abc import Sized, Container | ||
|
||
class LinkedList(Sized, Generic[T]): | ||
... | ||
|
||
class MyMapping(Iterable[tuple[K, V]], Container[tuple[K, V]], Generic[K, V]): | ||
... | ||
|
||
# > Subclassing a generic class without specifying type parameters assumes | ||
# > ``Any`` for each position. In the following example, ``MyIterable`` | ||
# > is not generic but implicitly inherits from ``Iterable[Any]``:: | ||
|
||
class MyIterableAny(Iterable): # Same as Iterable[Any] | ||
... | ||
|
||
def test_my_iterable_any(m: MyIterableAny): | ||
assert_type(iter(m), Iterator[Any]) | ||
|
||
# > Generic metaclasses are not supported | ||
|
||
class GenericMeta(type, Generic[T]): ... | ||
|
||
class GenericMetaInstance(metaclass=GenericMeta[T]): # Type error | ||
... |
Oops, something went wrong.