Zac-HD: Hurray!  

This fixes another bug too: in the current released version, using a decorator named `overload` causes an internal error (because pyflakes thinks that it's `typing.overload`, and tries to access a nonexistent scope name).  We first noticed this a while ago in [Hypothesis' build](https://travis-ci.org/HypothesisWorks/hypothesis/jobs/498740860#L783), but it's reproducible by running `pyflakes` on the following file:

```python
overload = lambda f: f  # or `def overload(arg): return arg

@overload
def func(arg): pass

def func(arg): return ...
```

Happily I've confirmed that this change fixes pyflakes for both the minimal case above (which might be worth adding as another test case for this PR?) and for Hypothesis - thanks @asottile 😍 
asottile: @Zac-HD 🎉 though it was probably #423 that fixed that one ~o/
Zac-HD: Yeah, probably... still fixed though and still fixed by you 😁 
asottile: heh only fair -- I broke it in the first place /o\
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 4c88af2..0e636c1 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -530,14 +530,21 @@ def getNodeName(node):
         return node.name
 
 
-def is_typing_overload(value, scope):
+def is_typing_overload(value, scope_stack):
+    def name_is_typing_overload(name):  # type: (str) -> bool
+        for scope in reversed(scope_stack):
+            if name in scope:
+                return (
+                    isinstance(scope[name], ImportationFrom) and
+                    scope[name].fullName == 'typing.overload'
+                )
+        else:
+            return False
+
     def is_typing_overload_decorator(node):
         return (
             (
-                isinstance(node, ast.Name) and
-                node.id in scope and
-                isinstance(scope[node.id], ImportationFrom) and
-                scope[node.id].fullName == 'typing.overload'
+                isinstance(node, ast.Name) and name_is_typing_overload(node.id)
             ) or (
                 isinstance(node, ast.Attribute) and
                 isinstance(node.value, ast.Name) and
@@ -548,8 +555,10 @@ def is_typing_overload(value, scope):
 
     return (
         isinstance(value.source, ast.FunctionDef) and
-        len(value.source.decorator_list) == 1 and
-        is_typing_overload_decorator(value.source.decorator_list[0])
+        any(
+            is_typing_overload_decorator(dec)
+            for dec in value.source.decorator_list
+        )
     )
 
 
@@ -888,7 +897,7 @@ class Checker(object):
                                 node, value.name, existing.source)
                 elif not existing.used and value.redefines(existing):
                     if value.name != '_' or isinstance(existing, Importation):
-                        if not is_typing_overload(existing, self.scope):
+                        if not is_typing_overload(existing, self.scopeStack):
                             self.report(messages.RedefinedWhileUnused,
                                         node, value.name, existing.source)
 

F811 (redefinition of unused variable) incorrectly triggered with @overload decorator
This bug was fixed for functions in #320. It still occurs if the function is inside a class and/or has multiple decorators (e.g. @staticmethod, @classmethod):
```python
from typing import overload


class test:
    @overload
    def utf8(value: None) -> None:
        pass

    @overload
    def utf8(value: bytes) -> bytes:
        pass

    @overload
    def utf8(value: str) -> bytes:
        pass

    def utf8(value):
        pass  # actual implementation
```

```
test.py:9:5: F811 redefinition of unused 'utf8' from line 5
test.py:13:5: F811 redefinition of unused 'utf8' from line 9
test.py:17:5: F811 redefinition of unused 'utf8' from line 13
```

```python
from typing import overload


def do_nothing(func):
    return func


@overload
@do_nothing
def utf8(value: None) -> None:
    pass


@overload
@do_nothing
def utf8(value: bytes) -> bytes:
    pass


@overload
@do_nothing
def utf8(value: str) -> bytes:
    pass


def utf8(value):
    pass  # actual implementation
```

```
test.py:14:1: F811 redefinition of unused 'utf8' from line 8
test.py:20:1: F811 redefinition of unused 'utf8' from line 14
test.py:26:1: F811 redefinition of unused 'utf8' from line 20
```
diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py
index 48635bb..b8876cb 100644
--- a/pyflakes/test/test_type_annotations.py
+++ b/pyflakes/test/test_type_annotations.py
@@ -39,6 +39,41 @@ class TestTypeAnnotations(TestCase):
             return s
         """)
 
+    def test_overload_with_multiple_decorators(self):
+        self.flakes("""
+            from typing import overload
+            dec = lambda f: f
+
+            @dec
+            @overload
+            def f(x):  # type: (int) -> int
+                pass
+
+            @dec
+            @overload
+            def f(x):  # type: (str) -> str
+                pass
+
+            @dec
+            def f(x): return x
+       """)
+
+    def test_overload_in_class(self):
+        self.flakes("""
+        from typing import overload
+
+        class C:
+            @overload
+            def f(self, x):  # type: (int) -> int
+                pass
+
+            @overload
+            def f(self, x):  # type: (str) -> str
+                pass
+
+            def f(self, x): return x
+        """)
+
     def test_not_a_typing_overload(self):
         """regression test for @typing.overload detection bug in 2.1.0"""
         self.flakes("""

pip install -e .
parse_log_pytest
pytest
flake8==3.6.0 pytest
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
flake8==3.6.0
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mccabe==0.6.1
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.4.0
-e git+https://github.com/PyCQA/pyflakes.git@6ba3f8e0b59b8fe880345be7ae594ccd76661f6d#egg=pyflakes
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: pyflakes
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - flake8==3.6.0
      - mccabe==0.6.1
      - pycodestyle==2.4.0
prefix: /opt/conda/envs/pyflakes

pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_overload_in_class pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_overload_with_multiple_decorators
pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_annotated_async_def pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_not_a_typing_overload pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsAdditionalComemnt pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsAssignedToPreviousNode pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsFullSignature pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsFullSignatureWithDocstring pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsInvalidDoesNotMarkAsUsed pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsMarkImportsAsUsed pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsNoWhitespaceAnnotation pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsStarArgs pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsSyntaxError pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typeCommentsSyntaxErrorCorrectLine pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_typingOverload pyflakes/test/test_type_annotations.py::TestTypeAnnotations::test_variable_annotations
pyflakes/checker.py
pyflakes/checker.py