diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 6f4de4a060ea..f6ca5e861768 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1372,8 +1372,8 @@ def visit_reveal_type_expr(self, expr: RevealTypeExpr) -> Type: def visit_type_application(self, tapp: TypeApplication) -> Type: """Type check a type application (expr[type, ...]).""" - self.chk.fail(messages.GENERIC_TYPE_NOT_VALID_AS_EXPRESSION, tapp) - return AnyType() + tp = cast(CallableType, self.accept(tapp.expr)) + return self.apply_generic_arguments(tp, tapp.types, tapp) def visit_type_alias_expr(self, alias: TypeAliasExpr) -> Type: return AnyType() diff --git a/mypy/messages.py b/mypy/messages.py index e39a424fbf40..9e764203d51e 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -78,8 +78,6 @@ 'Read-only property cannot override read-write property' INSTANCE_LAYOUT_CONFLICT = 'Instance layout conflict in multiple inheritance' FORMAT_REQUIRES_MAPPING = 'Format requires a mapping' -GENERIC_TYPE_NOT_VALID_AS_EXPRESSION = \ - "Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment)" RETURN_TYPE_CANNOT_BE_CONTRAVARIANT = "Cannot use a contravariant type variable as return type" FUNCTION_PARAMETER_CANNOT_BE_COVARIANT = "Cannot use a covariant type variable as a parameter" INCOMPATIBLE_IMPORT_OF = "Incompatible import of" @@ -677,7 +675,7 @@ def incompatible_type_application(self, expected_arg_count: int, actual_arg_count: int, context: Context) -> None: if expected_arg_count == 0: - self.fail('Type application targets a non-generic function', + self.fail('Type application targets a non-generic function or class', context) elif actual_arg_count > expected_arg_count: self.fail('Type application has too many types ({} expected)' diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index f9d0e831f671..1189bc4c6126 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -422,33 +422,83 @@ main: note: In member "f" of class "A": -- ---------------------------- -[case testInvalidTypeApplicationTarget] +[case testTypeApplicationArgs] from typing import TypeVar, Generic T = TypeVar('T') -class A(Generic[T]): pass -A[A]() # E: Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment) -A[int, str]() # E: Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment) +class Node(Generic[T]): + def __init__(self, x: T) -> None: + ... +Node[int]() # E: Too few arguments for "Node" +Node[int](1, 1, 1) # E: Too many arguments for "Node" [out] -[case testInvalidTypeApplicationTarget2] +[case testTypeApplicationTvars] from typing import TypeVar, Generic T = TypeVar('T') S = TypeVar('S') class A(Generic[T, S]): pass -A[int, str]() # E: Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment) -A[int]() # E: Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment) +A[int]() # E: Type application has too few types (2 expected) +A[int, str, int]() # E: Type application has too many types (2 expected) [out] -[case testInvalidTypeApplicationTarget3] - +[case testInvalidTypeApplicationType] a = None # type: A class A: pass -a[A]() # Fail -A[A]() # Fail +a[A]() # E: Value of type "A" is not indexable +A[A]() # E: Type application targets a non-generic function or class [out] -main:4: error: Value of type "A" is not indexable -main:5: error: Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment) +[case testTypeApplicationArgTypes] +from typing import TypeVar, Generic +T = TypeVar('T') +class Node(Generic[T]): + def __init__(self, x: T) -> None: + ... + +Node[int](1) +Node[int]('a') # E: Argument 1 to "Node" has incompatible type "str"; expected "int" + +class Dummy(Generic[T]): + def meth(self, x: T) -> None: + ... + def methout(self) -> T: + ... + +Dummy[int]().meth(1) +Dummy[int]().meth('a') # E: Argument 1 to "meth" of "Dummy" has incompatible type "str"; expected "int" +reveal_type(Dummy[int]()) # E: Revealed type is '__main__.Dummy[builtins.int*]' +reveal_type(Dummy[int]().methout()) # E: Revealed type is 'builtins.int*' +[out] + +[case testTypeApplicationArgTypesSubclasses] +from typing import TypeVar, Generic +T = TypeVar('T') +S = TypeVar('S') +class C(Generic[T, S]): + def __init__(self, x: T, y: S) -> None: + ... + +class D(C[int, T], Generic[T]): ... + +D[str](1, 'a') +D[str](1, 1) # E: Argument 2 to "D" has incompatible type "int"; expected "str" + +class E(D[str]): ... +E(1, 'a') +E(1, 1) # E: Argument 2 to "E" has incompatible type "int"; expected "str" +[out] + +[case testTypeApplicationAlias] +from typing import TypeVar, Generic +T = TypeVar('T') +class Node(Generic[T]): + def __init__(self, x: T) -> None: + ... + +Alias = Node +Alias[int](1) +Alias[int]("a") # E: Argument 1 to "Node" has incompatible type "str"; expected "int" +[out] -- Multiple assignment with lists -- ------------------------------