@@ -334,12 +334,19 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
334
334
# for functions decorated with `@types.coroutine` or
335
335
# `@asyncio.coroutine`. Its single parameter corresponds to tr.
336
336
#
337
+ # PEP 525 adds a new type, the asynchronous generator, which was
338
+ # first released in Python 3.6. Async generators are `async def`
339
+ # functions that can also `yield` values. They can be parameterized
340
+ # with two types, ty and tc, because they cannot return a value.
341
+ #
337
342
# There are several useful methods, each taking a type t and a
338
343
# flag c indicating whether it's for a generator or coroutine:
339
344
#
340
345
# - is_generator_return_type(t, c) returns whether t is a Generator,
341
346
# Iterator, Iterable (if not c), or Awaitable (if c), or
342
347
# AwaitableGenerator (regardless of c).
348
+ # - is_async_generator_return_type(t) returns whether t is an
349
+ # AsyncGenerator.
343
350
# - get_generator_yield_type(t, c) returns ty.
344
351
# - get_generator_receive_type(t, c) returns tc.
345
352
# - get_generator_return_type(t, c) returns tr.
@@ -361,6 +368,14 @@ def is_generator_return_type(self, typ: Type, is_coroutine: bool) -> bool:
361
368
return True
362
369
return isinstance (typ , Instance ) and typ .type .fullname () == 'typing.AwaitableGenerator'
363
370
371
+ def is_async_generator_return_type (self , typ : Type ) -> bool :
372
+ """Is `typ` a valid type for an async generator?
373
+
374
+ True if `typ` is a supertype of AsyncGenerator.
375
+ """
376
+ agt = self .named_generic_type ('typing.AsyncGenerator' , [AnyType (), AnyType ()])
377
+ return is_subtype (agt , typ )
378
+
364
379
def get_generator_yield_type (self , return_type : Type , is_coroutine : bool ) -> Type :
365
380
"""Given the declared return type of a generator (t), return the type it yields (ty)."""
366
381
if isinstance (return_type , AnyType ):
@@ -569,9 +584,9 @@ def is_implicit_any(t: Type) -> bool:
569
584
570
585
# Check that Generator functions have the appropriate return type.
571
586
if defn .is_generator :
572
- if defn .is_coroutine :
587
+ if defn .is_async_generator :
573
588
if not self .is_async_generator_return_type (typ .ret_type ):
574
- pass
589
+ self . fail ( messages . INVALID_RETURN_TYPE_FOR_ASYNC_GENERATOR , typ )
575
590
else :
576
591
if not self .is_generator_return_type (typ .ret_type , defn .is_coroutine ):
577
592
self .fail (messages .INVALID_RETURN_TYPE_FOR_GENERATOR , typ )
0 commit comments