Repository: PyCQA/pyflakes

Issue:
@overload of async functions
Since #435, pyflakes git tip copes with synchronous @overload'ed functions, but not with async ones:

```python
from typing import overload

@overload
def f(x: int) -> int:
    ...

@overload
def f(x: float) -> float:
    ...

def f(x):
    return x

@overload
async def g(x: int) -> int:
    ...

@overload
async def g(x: float) -> float:
    ...

async def g(x):
    return x
```
```bash
$ python -m pyflakes .

18:1 redefinition of unused 'g' from line 14
22:1 redefinition of unused 'g' from line 18
```

Discussion:
crusaderky: Tested manually; it works
asottile: (counting that as two approvals :laughing:)

Patch:
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 44c6b25..eca2002 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -72,9 +72,11 @@ else:
 if PY35_PLUS:
     FOR_TYPES = (ast.For, ast.AsyncFor)
     LOOP_TYPES = (ast.While, ast.For, ast.AsyncFor)
+    FUNCTION_TYPES = (ast.FunctionDef, ast.AsyncFunctionDef)
 else:
     FOR_TYPES = (ast.For,)
     LOOP_TYPES = (ast.While, ast.For)
+    FUNCTION_TYPES = (ast.FunctionDef,)
 
 # https://github.com/python/typed_ast/blob/1.4.0/ast27/Parser/tokenizer.c#L102-L104
 TYPE_COMMENT_RE = re.compile(r'^#\s*type:\s*')
@@ -642,7 +644,7 @@ def is_typing_overload(value, scope_stack):
         )
 
     return (
-        isinstance(value.source, ast.FunctionDef) and
+        isinstance(value.source, FUNCTION_TYPES) and
         any(
             is_typing_overload_decorator(dec)
             for dec in value.source.decorator_list


Test patch:
diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py
index 676a4a5..045c57a 100644
--- a/pyflakes/test/test_type_annotations.py
+++ b/pyflakes/test/test_type_annotations.py
@@ -56,6 +56,24 @@ class TestTypeAnnotations(TestCase):
             return s
         """)
 
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_typingOverloadAsync(self):
+        """Allow intentional redefinitions via @typing.overload (async)"""
+        self.flakes("""
+        from typing import overload
+
+        @overload
+        async def f(s):  # type: (None) -> None
+            pass
+
+        @overload
+        async def f(s):  # type: (int) -> int
+            pass
+
+        async def f(s):
+            return s
+        """)
+
     def test_overload_with_multiple_decorators(self):
         self.flakes("""
             from typing import overload