diff --git a/mypy/checker.py b/mypy/checker.py index fc9733117a0a..1da1966a00ef 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4704,7 +4704,7 @@ def type_requires_usage(self, typ: Type) -> tuple[str, ErrorCode] | None: if isinstance(proper_type, Instance): # We use different error codes for generic awaitable vs coroutine. # Coroutines are on by default, whereas generic awaitables are not. - if proper_type.type.fullname == "typing.Coroutine": + if proper_type.type.fullname == "types.CoroutineType": return ("Are you missing an await?", UNUSED_COROUTINE) if proper_type.type.get("__await__") is not None: return ("Are you missing an await?", UNUSED_AWAITABLE) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index edc3ac70fa54..571e5763dc86 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -6336,7 +6336,7 @@ def is_async_def(t: Type) -> bool: and len(t.args) >= 4 ): t = get_proper_type(t.args[3]) - return isinstance(t, Instance) and t.type.fullname == "typing.Coroutine" + return isinstance(t, Instance) and t.type.fullname == "types.CoroutineType" def is_non_empty_tuple(t: Type) -> bool: diff --git a/mypy/messages.py b/mypy/messages.py index 46ade80df61d..29b6c5d57c38 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1336,7 +1336,7 @@ def return_type_incompatible_with_supertype( isinstance(original, Instance) and isinstance(override, Instance) and override.type.fullname == "typing.AsyncIterator" - and original.type.fullname == "typing.Coroutine" + and original.type.fullname == "types.CoroutineType" and len(original.args) == 3 and original.args[2] == override ): diff --git a/mypy/semanal.py b/mypy/semanal.py index d70abe911fea..2d16f99e30c0 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1029,12 +1029,11 @@ def analyze_func_def(self, defn: FuncDef) -> None: pass else: # A coroutine defined as `async def foo(...) -> T: ...` - # has external return type `Coroutine[Any, Any, T]`. + # has external return type `CoroutineType[Any, Any, T]`. any_type = AnyType(TypeOfAny.special_form) - ret_type = self.named_type_or_none( - "typing.Coroutine", [any_type, any_type, defn.type.ret_type] + ret_type = self.named_type( + "types.CoroutineType", [any_type, any_type, defn.type.ret_type] ) - assert ret_type is not None, "Internal error: typing.Coroutine not found" defn.type = defn.type.copy_modified(ret_type=ret_type) self.wrapped_coro_return_types[defn] = defn.type diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 7925f2a6bd3e..7ac70d8953da 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -157,6 +157,17 @@ def __invert__(self: _T) -> _T: pass __rxor__ = __xor__ """ +stubtest_types_stub = """ +from typing import Coroutine, TypeVar + +_T = TypeVar('_T') +_U = TypeVar('_U') +_V = TypeVar('_V') + +class CoroutineType(Coroutine[_T, _U, _V]): + pass +""" + def run_stubtest_with_stderr( stub: str, runtime: str, options: list[str], config_file: str | None = None @@ -168,6 +179,8 @@ def run_stubtest_with_stderr( f.write(stubtest_typing_stub) with open("enum.pyi", "w") as f: f.write(stubtest_enum_stub) + with open("types.pyi", "w") as f: + f.write(stubtest_types_stub) with open(f"{TEST_MODULE_NAME}.pyi", "w") as f: f.write(stub) with open(f"{TEST_MODULE_NAME}.py", "w") as f: @@ -292,6 +305,7 @@ class X: @collect_cases def test_coroutines(self) -> Iterator[Case]: + yield Case(stub="import types", runtime="import types", error=None) yield Case(stub="def bar() -> int: ...", runtime="async def bar(): return 5", error="bar") # Don't error for this one -- we get false positives otherwise yield Case(stub="async def foo() -> int: ...", runtime="def foo(): return 5", error=None) diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 979da62aca92..0d6d45a46a64 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -12,7 +12,7 @@ async def f() -> int: async def f() -> int: return 0 -_ = reveal_type(f()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" +_ = reveal_type(f()) # N: Revealed type is "types.CoroutineType[Any, Any, builtins.int]" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -53,6 +53,7 @@ async def f(x: T) -> T: y = await f(x) reveal_type(y) return y +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] main:6: note: Revealed type is "T`-1" @@ -65,6 +66,7 @@ async def f(x: T) -> T: y = await f(x) # type: Any reveal_type(y) return y +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] main:6: note: Revealed type is "Any" @@ -77,6 +79,7 @@ async def f(x: T) -> T: y = await f(x) # type: int reveal_type(y) return x +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] main:5: error: Argument 1 to "f" has incompatible type "T"; expected "int" @@ -92,6 +95,7 @@ async def f() -> int: x = await g() return x [typing fixtures/typing-async.pyi] +[builtins fixtures/async_await.pyi] [out] main:7: error: Incompatible types in "await" (actual type "Generator[int, None, str]", expected type "Awaitable[Any]") @@ -103,6 +107,7 @@ def g() -> Iterator[Any]: async def f() -> int: x = await g() return x +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] main:6: error: Incompatible types in "await" (actual type "Iterator[Any]", expected type "Awaitable[Any]") @@ -177,7 +182,7 @@ async def f() -> None: [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] -main:7: error: "Coroutine[Any, Any, AsyncGenerator[str, None]]" has no attribute "__aiter__" (not async iterable) +main:7: error: "CoroutineType[Any, Any, AsyncGenerator[str, None]]" has no attribute "__aiter__" (not async iterable) main:7: note: Maybe you forgot to use "await"? [case testAsyncForErrorCanBeIgnored] @@ -381,7 +386,7 @@ def g() -> Generator[Any, None, str]: [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [out] -main:6: error: "yield from" can't be applied to "Coroutine[Any, Any, str]" +main:6: error: "yield from" can't be applied to "CoroutineType[Any, Any, str]" [case testAwaitableSubclass] @@ -453,7 +458,7 @@ async def h() -> None: async def wrong_return() -> Generator[int, None, None]: # E: The return type of an async generator function should be "AsyncGenerator" or one of its supertypes yield 3 -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorReturnIterator] @@ -468,7 +473,7 @@ async def use_gen() -> None: async for item in gen(): reveal_type(item) # N: Revealed type is "builtins.int" -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorManualIter] @@ -485,7 +490,7 @@ async def user() -> None: reveal_type(await gen.__anext__()) # N: Revealed type is "builtins.int" -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorAsend] @@ -505,7 +510,7 @@ async def h() -> None: await g.asend(()) # E: Argument 1 to "asend" of "AsyncGenerator" has incompatible type "tuple[()]"; expected "str" reveal_type(await g.asend('hello')) # N: Revealed type is "builtins.int" -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorAthrow] @@ -523,7 +528,7 @@ async def h() -> None: reveal_type(v) # N: Revealed type is "builtins.str" reveal_type(await g.athrow(BaseException)) # N: Revealed type is "builtins.str" -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorNoSyncIteration] @@ -549,7 +554,7 @@ async def f() -> AsyncGenerator[int, None]: async def gen() -> AsyncGenerator[int, None]: yield from f() # E: "yield from" in async function -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testAsyncGeneratorNoReturnWithValue] @@ -588,7 +593,7 @@ async def test_implicit_generators() -> None: reveal_type(x for x in await get_list()) # N: Revealed type is "typing.Generator[builtins.int, None, None]" reveal_type(x for _ in [1] for x in await get_list()) # N: Revealed type is "typing.AsyncGenerator[builtins.int, None]" -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -641,9 +646,9 @@ def plain_host_generator() -> Generator[str, None, None]: yield 'a' x = 0 x = yield from plain_generator() - x = yield from plain_coroutine() # E: "yield from" can't be applied to "Coroutine[Any, Any, int]" + x = yield from plain_coroutine() # E: "yield from" can't be applied to "CoroutineType[Any, Any, int]" x = yield from decorated_generator() - x = yield from decorated_coroutine() # E: "yield from" can't be applied to "AwaitableGenerator[Any, Any, int, Coroutine[Any, Any, int]]" + x = yield from decorated_coroutine() # E: "yield from" can't be applied to "AwaitableGenerator[Any, Any, int, CoroutineType[Any, Any, int]]" x = yield from other_iterator() x = yield from other_coroutine() # E: "yield from" can't be applied to "Aw" @@ -721,7 +726,7 @@ async def f(x: str) -> str: ... async def f(x): pass -reveal_type(f) # N: Revealed type is "Overload(def (x: builtins.int) -> typing.Coroutine[Any, Any, builtins.int], def (x: builtins.str) -> typing.Coroutine[Any, Any, builtins.str])" +reveal_type(f) # N: Revealed type is "Overload(def (x: builtins.int) -> types.CoroutineType[Any, Any, builtins.int], def (x: builtins.str) -> types.CoroutineType[Any, Any, builtins.str])" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -738,7 +743,7 @@ async def g() -> None: forwardref: C class C: pass -reveal_type(f) # N: Revealed type is "def () -> typing.Coroutine[Any, Any, None]" +reveal_type(f) # N: Revealed type is "def () -> types.CoroutineType[Any, Any, None]" reveal_type(g) # N: Revealed type is "Any" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -832,7 +837,7 @@ class B: def bar() -> None: A() # E: Value of type "A" must be used [unused-awaitable] \ # N: Are you missing an await? - foo() # E: Value of type "Coroutine[Any, Any, None]" must be used [unused-coroutine] \ + foo() # E: Value of type "CoroutineType[Any, Any, None]" must be used [unused-coroutine] \ # N: Are you missing an await? B() @@ -891,12 +896,12 @@ class Custom(Generic[T]): class Sub(Custom[T]): ... async def test(x: Sub[D], tx: Type[Sub[D]]) -> None: - foo().x # E: "Coroutine[Any, Any, D]" has no attribute "x" \ + foo().x # E: "CoroutineType[Any, Any, D]" has no attribute "x" \ # N: Maybe you forgot to use "await"? (await foo()).x - foo().bad # E: "Coroutine[Any, Any, D]" has no attribute "bad" + foo().bad # E: "CoroutineType[Any, Any, D]" has no attribute "bad" - g(foo()) # E: Argument 1 to "g" has incompatible type "Coroutine[Any, Any, D]"; expected "C" \ + g(foo()) # E: Argument 1 to "g" has incompatible type "CoroutineType[Any, Any, D]"; expected "C" \ # N: Maybe you forgot to use "await"? g(await foo()) unknown: Awaitable[Any] @@ -1073,7 +1078,7 @@ class P(Protocol): raise BaseException class Launcher(P): - def launch(self) -> AsyncIterator[int]: # E: Return type "AsyncIterator[int]" of "launch" incompatible with return type "Coroutine[Any, Any, AsyncIterator[int]]" in supertype "P" \ + def launch(self) -> AsyncIterator[int]: # E: Return type "AsyncIterator[int]" of "launch" incompatible with return type "CoroutineType[Any, Any, AsyncIterator[int]]" in supertype "P" \ # N: Consider declaring "launch" in supertype "P" without "async" \ # N: See https://mypy.readthedocs.io/en/stable/more_types.html#asynchronous-iterators raise BaseException diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test index fe8a1551f81b..8e266eb19332 100644 --- a/test-data/unit/check-class-namedtuple.test +++ b/test-data/unit/check-class-namedtuple.test @@ -490,12 +490,12 @@ class XRepr(NamedTuple): return 0 reveal_type(XMeth(1).double()) # N: Revealed type is "builtins.int" -_ = reveal_type(XMeth(1).asyncdouble()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" +_ = reveal_type(XMeth(1).asyncdouble()) # N: Revealed type is "types.CoroutineType[Any, Any, builtins.int]" reveal_type(XMeth(42).x) # N: Revealed type is "builtins.int" reveal_type(XRepr(42).__str__()) # N: Revealed type is "builtins.str" reveal_type(XRepr(1, 2).__sub__(XRepr(3))) # N: Revealed type is "builtins.int" [typing fixtures/typing-async.pyi] -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testNewNamedTupleOverloading] from typing import NamedTuple, overload diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index d6e3366401dd..6f6cb58a75b1 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -383,7 +383,7 @@ async def asyncf(): # E: Function is missing a return type annotation [no-unty async def asyncf2(x: int): # E: Function is missing a return type annotation [no-untyped-def] return 0 [typing fixtures/typing-async.pyi] -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testErrorCodeCallUntypedFunction] # flags: --disallow-untyped-calls diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index bb64bb44d282..2846f0f737fa 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -430,7 +430,7 @@ async def g() -> NoReturn: async def h() -> NoReturn: # E: Implicit return in function which does not return # Purposely not evaluating coroutine _ = f() -[builtins fixtures/dict.pyi] +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] [case testNoWarnNoReturn] diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index ceb7af433dce..8e2785a54af8 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3544,7 +3544,7 @@ def decorator2(f: Callable[P, None]) -> Callable[ def key2(x: int) -> None: ... -@decorator2(key2) # E: Argument 1 has incompatible type "Callable[[Arg(int, 'y')], Coroutine[Any, Any, None]]"; expected "Callable[[Arg(int, 'x')], Awaitable[None]]" +@decorator2(key2) # E: Argument 1 has incompatible type "Callable[[Arg(int, 'y')], CoroutineType[Any, Any, None]]"; expected "Callable[[Arg(int, 'x')], Awaitable[None]]" async def foo2(y: int) -> None: ... @@ -3555,7 +3555,7 @@ class Parent: class Child(Parent): method_without: Callable[[], "Child"] method_with: Callable[[str], "Child"] # E: Incompatible types in assignment (expression has type "Callable[[str], Child]", base class "Parent" defined the type as "Callable[[Arg(str, 'param')], Parent]") -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testDistinctFormattingUnion] from typing import Callable, Union diff --git a/test-data/unit/check-python311.test b/test-data/unit/check-python311.test index 09c8d6082365..823117ae3dac 100644 --- a/test-data/unit/check-python311.test +++ b/test-data/unit/check-python311.test @@ -74,7 +74,7 @@ async def asynciter(iterable): async def coro() -> Generator[List[Any], None, None]: return ([i async for i in asynciter([0,j])] for j in [3, 5]) -reveal_type(coro) # N: Revealed type is "def () -> typing.Coroutine[Any, Any, typing.Generator[builtins.list[Any], None, None]]" +reveal_type(coro) # N: Revealed type is "def () -> types.CoroutineType[Any, Any, typing.Generator[builtins.list[Any], None, None]]" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index bfd6334b5077..f5797d88efcf 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -31,9 +31,10 @@ reveal_type(f(1)) # N: Revealed type is "builtins.int" async def g[T](x: T) -> T: return reveal_type(x) # N: Revealed type is "T`-1" -reveal_type(g(1)) # E: Value of type "Coroutine[Any, Any, int]" must be used \ +reveal_type(g(1)) # E: Value of type "CoroutineType[Any, Any, int]" must be used \ # N: Are you missing an await? \ - # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" + # N: Revealed type is "types.CoroutineType[Any, Any, builtins.int]" +[builtins fixtures/async_await.pyi] [case testPEP695TypeVarBasic] from typing import Callable diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 368431127b76..e34208c619c0 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -1300,7 +1300,7 @@ async def f_no_suppress_5() -> int: noop() # E: Statement is unreachable [typing fixtures/typing-full.pyi] -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testUnreachableFlagContextAsyncManagersSuppressed] # flags: --warn-unreachable @@ -1346,7 +1346,7 @@ async def f_mix() -> int: # E: Missing return statement return 3 noop() [typing fixtures/typing-full.pyi] -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testUnreachableFlagContextAsyncManagersAbnormal] # flags: --warn-unreachable @@ -1397,7 +1397,7 @@ async def f_malformed_2() -> int: noop() # E: Statement is unreachable [typing fixtures/typing-full.pyi] -[builtins fixtures/tuple.pyi] +[builtins fixtures/async_await.pyi] [case testUnreachableUntypedFunction] # flags: --warn-unreachable diff --git a/test-data/unit/deps-expressions.test b/test-data/unit/deps-expressions.test index fd5a4fe0ff9f..bc182a94a2ef 100644 --- a/test-data/unit/deps-expressions.test +++ b/test-data/unit/deps-expressions.test @@ -125,6 +125,7 @@ async def g() -> None: [typing fixtures/typing-async.pyi] [out] -> m.g + -> , m.g [case testStarExpr] from typing import Iterator diff --git a/test-data/unit/fixtures/async_await.pyi b/test-data/unit/fixtures/async_await.pyi index 96ade881111b..7827be7a0e5d 100644 --- a/test-data/unit/fixtures/async_await.pyi +++ b/test-data/unit/fixtures/async_await.pyi @@ -1,3 +1,4 @@ +import types import typing T = typing.TypeVar('T') diff --git a/test-data/unit/lib-stub/types.pyi b/test-data/unit/lib-stub/types.pyi index 3f713c31e417..2cccf0ed32a4 100644 --- a/test-data/unit/lib-stub/types.pyi +++ b/test-data/unit/lib-stub/types.pyi @@ -1,7 +1,9 @@ -from typing import Any, TypeVar +from typing import Any, TypeVar, Coroutine import sys _T = TypeVar('_T') +_U = TypeVar('_U') +_V = TypeVar('_V') def coroutine(func: _T) -> _T: pass @@ -13,6 +15,9 @@ class GenericAlias: def __or__(self, o): ... def __ror__(self, o): ... +class CoroutineType(Coroutine[_T, _U, _V]): + pass + if sys.version_info >= (3, 10): class NoneType: ...