Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stubtest crashes on a stub with an overloaded method where the first overload is decorated with @final #14950

Closed
AlexWaygood opened this issue Mar 23, 2023 · 0 comments · Fixed by #16457

Comments

@AlexWaygood
Copy link
Member

Crash Report

If you run stubtest on a stub with a method like this, stubtest will crash:

from typing import final, overload

class C:
    @overload
    @final
    def foo(self, obj: str) -> int: ...
    @overload
    def foo(self, obj: int) -> str: ...

The crash occurs regardless of the order in which you stack the @final and @overload decorator on the first overload. (PEP 591 specifies that for overloaded definitions in stubs, the @final decorator should be placed on the first overload, but doesn't specify which order they should be stacked in.)

Traceback

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 1823, in <module>
    sys.exit(main())
             ^^^^^^
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 1819, in main
    return test_stubs(parse_options(sys.argv[1:]))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 1692, in test_stubs
    for error in test_module(module):
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 218, in test_module
    yield from verify(stub, runtime, [module_name])
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 396, in verify_mypyfile
    yield from verify(stub_entry, runtime_entry, object_path + [entry])
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 517, in verify_typeinfo
    yield from verify(stub_to_verify, runtime_attr, object_path + [entry])
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 1050, in verify_overloadedfuncdef
    stub_sig = Signature.from_overloadedfuncdef(stub)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\AppData\Local\Temp\tmp_p_nrkoa\Lib\site-packages\mypy\stubtest.py", line 756, in from_overloadedfuncdef
    assert func is not None
           ^^^^^^^^^^^^^^^^
AssertionError

To Reproduce

Two ways to reproduce:

(1) Apply this diff, and then run pytest mypy/test/teststubtest.py:

diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py
index d39812b5f..b7f114b5e 100644
--- a/mypy/test/teststubtest.py
+++ b/mypy/test/teststubtest.py
@@ -1177,6 +1177,24 @@ class StubtestUnit(unittest.TestCase):
             """,
             error="C",
         )
+        yield Case(
+            stub="""
+            from typing import overload
+            from typing_extensions import final
+            class D:
+                @overload
+                @final
+                def foo(self, obj: int) -> str: ...
+                @overload
+                def foo(self, obj: str) -> int: ...
+            """,
+            runtime="""
+            class D:
+                def foo(self, obj):
+                    return 42 if isinstance(obj, str) else "foo"
+            """,
+            error=None
+        )

(2) With a typeshed clone checked out, apply this diff, then run python tests/stubtest_stdlib.py:

diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi
index 2c21cd95d..8cdcd3b6a 100644
--- a/stdlib/builtins.pyi
+++ b/stdlib/builtins.pyi
@@ -189,6 +189,7 @@ class type:

 class super:
     @overload
+    @final
     def __init__(self, __t: Any, __obj: Any) -> None: ...
     @overload
     def __init__(self, __t: Any) -> None: ...

Your Environment

Reproduced with mypy 1.1.1 and mypy @ bfa9eac

sobolevn pushed a commit that referenced this issue Mar 24, 2023
…l` if they are decorated with `@final` at runtime (#14951)

This implements most of #14924. The only thing it _doesn't_ implement is
verification for overloaded methods decorated with `@final` -- I tried
working on that, but hit #14950.
hauntsaninja added a commit to hauntsaninja/mypy that referenced this issue Nov 11, 2023
We should probably lean into the type checker harder here

Fixes python#14950
Fixes python/typeshed#11009 (comment)
ilevkivskyi pushed a commit that referenced this issue Nov 11, 2023
We should probably lean into the type checker harder here

Fixes #14950
Fixes
python/typeshed#11009 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant