Skip to content

Commit f637215

Browse files
ilevkivskyimsullivan
authored andcommitted
Fix two crashes in duplicate decorated functions (#5427)
1 parent 1222c96 commit f637215

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

mypy/nodes.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -427,17 +427,24 @@ class OverloadedFuncDef(FuncBase, SymbolNode, Statement):
427427
"""
428428

429429
items = None # type: List[OverloadPart]
430+
unanalyzed_items = None # type: List[OverloadPart]
430431
impl = None # type: Optional[OverloadPart]
431432

432433
def __init__(self, items: List['OverloadPart']) -> None:
433434
super().__init__()
434435
assert len(items) > 0
435436
self.items = items
437+
self.unanalyzed_items = items.copy()
436438
self.impl = None
437439
self.set_line(items[0].line)
438440

439441
def name(self) -> str:
440-
return self.items[0].name()
442+
if self.items:
443+
return self.items[0].name()
444+
else:
445+
# This may happen for malformed overload
446+
assert self.impl is not None
447+
return self.impl.name()
441448

442449
def accept(self, visitor: StatementVisitor[T]) -> T:
443450
return visitor.visit_overloaded_func_def(self)

mypy/semanal.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
518518
# The first item was already visited
519519
item.is_overload = True
520520
item.accept(self)
521-
# TODO support decorated overloaded functions properly
521+
# TODO: support decorated overloaded functions properly
522522
if isinstance(item, Decorator):
523523
callable = function_type(item.func, self.builtin_type('builtins.function'))
524524
assert isinstance(callable, CallableType)

mypy/server/aststrip.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,8 @@ def visit_decorator(self, node: Decorator) -> None:
130130
def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> None:
131131
if not self.recurse_into_functions:
132132
return
133-
if node.impl:
134-
# Revert change made during semantic analysis pass 2.
135-
assert node.items[-1] is not node.impl
136-
node.items.append(node.impl)
133+
# Revert change made during semantic analysis pass 2.
134+
node.items = node.unanalyzed_items.copy()
137135
super().visit_overloaded_func_def(node)
138136

139137
@contextlib.contextmanager

test-data/unit/fine-grained.test

+62
Original file line numberDiff line numberDiff line change
@@ -7300,6 +7300,68 @@ def A(x: str) -> str: pass
73007300
==
73017301
a.py:4: error: Incompatible import of "A" (imported name has type "Callable[[str], str]", local name has type "Type[List[Any]]")
73027302

7303+
[case testFakeOverloadCrash]
7304+
import b
7305+
[file a.py]
7306+
def dec(fun):
7307+
pass
7308+
a = 1
7309+
[file a.py.2]
7310+
def dec(fun):
7311+
pass
7312+
a = 2
7313+
[file b.py]
7314+
from a import dec
7315+
@dec
7316+
def a():
7317+
pass
7318+
@dec
7319+
def a():
7320+
pass
7321+
[out]
7322+
b.py:5: error: Name 'a' already defined on line 2
7323+
==
7324+
b.py:5: error: Name 'a' already defined on line 2
7325+
7326+
[case testFakeOverloadCrash2]
7327+
# this test just should not crash
7328+
import a
7329+
[file a.py]
7330+
T = TypeVar("T")
7331+
7332+
def foo(func):
7333+
return func
7334+
7335+
@foo
7336+
def bar(x: T) -> T:
7337+
pass
7338+
7339+
@foo
7340+
def bar(x: T) -> T:
7341+
pass
7342+
[file a.py.2]
7343+
T = TypeVar("T")
7344+
7345+
def foo(func):
7346+
return func
7347+
7348+
@foo
7349+
def bar(x: T) -> T:
7350+
pass
7351+
7352+
@foo
7353+
def bar(x: T) -> T:
7354+
pass
7355+
x = 1
7356+
[out]
7357+
a.py:1: error: Name 'TypeVar' is not defined
7358+
a.py:10: error: Name 'bar' already defined on line 6
7359+
a.py:11: error: Invalid type "a.T"
7360+
==
7361+
a.py:1: error: Name 'TypeVar' is not defined
7362+
a.py:10: error: Name 'bar' already defined on line 6
7363+
a.py:11: error: Invalid type "a.T"
7364+
73037365
[case testRefreshForWithTypeComment1]
73047366
[file a.py]
73057367
from typing import List

0 commit comments

Comments
 (0)