Skip to content

Commit 6cd8e00

Browse files
authored
Fix type query for recursive aliases (#14136)
See #14130 for context. Btw it looks like these `Any` reports are quite broken in general. Some issues I found: * Many types are reported twice (even non-recursive) * Explicit `Any` in alias r.h.s are not counted (because of reckless `res = make_any_non_explicit(res)` in semanal.py) * For generic aliases we count their r.h.s. as containing `Any` from omitted generics I tried to fix these things, but it is not trivial, so maybe we can do it later in a separate PR.
1 parent a2477ff commit 6cd8e00

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

mypy/type_visitor.py

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -404,24 +404,16 @@ def visit_placeholder_type(self, t: PlaceholderType) -> T:
404404
return self.query_types(t.args)
405405

406406
def visit_type_alias_type(self, t: TypeAliasType) -> T:
407+
# Skip type aliases already visited types to avoid infinite recursion.
408+
# TODO: Ideally we should fire subvisitors here (or use caching) if we care
409+
# about duplicates.
410+
if t in self.seen_aliases:
411+
return self.strategy([])
412+
self.seen_aliases.add(t)
407413
if self.skip_alias_target:
408414
return self.query_types(t.args)
409415
return get_proper_type(t).accept(self)
410416

411417
def query_types(self, types: Iterable[Type]) -> T:
412-
"""Perform a query for a list of types.
413-
414-
Use the strategy to combine the results.
415-
Skip type aliases already visited types to avoid infinite recursion.
416-
"""
417-
res: list[T] = []
418-
for t in types:
419-
if isinstance(t, TypeAliasType):
420-
# Avoid infinite recursion for recursive type aliases.
421-
# TODO: Ideally we should fire subvisitors here (or use caching) if we care
422-
# about duplicates.
423-
if t in self.seen_aliases:
424-
continue
425-
self.seen_aliases.add(t)
426-
res.append(t.accept(self))
427-
return self.strategy(res)
418+
"""Perform a query for a list of types using the strategy to combine the results."""
419+
return self.strategy([t.accept(self) for t in types])

mypy/typeanal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Typ
450450
if fullname == "builtins.None":
451451
return NoneType()
452452
elif fullname == "typing.Any" or fullname == "builtins.Any":
453-
return AnyType(TypeOfAny.explicit)
453+
return AnyType(TypeOfAny.explicit, line=t.line, column=t.column)
454454
elif fullname in FINAL_TYPE_NAMES:
455455
self.fail(
456456
"Final can be only used as an outermost qualifier in a variable annotation",

test-data/unit/reports.test

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ class A(object):
103103
</body>
104104
</html>
105105

106+
[case testNoCrashRecursiveAliasInReport]
107+
# cmd: mypy --any-exprs-report report n.py
108+
109+
[file n.py]
110+
from typing import Union, List, Any, TypeVar
111+
112+
Nested = List[Union[Any, Nested]]
113+
T = TypeVar("T")
114+
NestedGen = List[Union[T, NestedGen[T]]]
115+
116+
x: Nested
117+
y: NestedGen[int]
118+
z: NestedGen[Any]
119+
120+
[file report/any-exprs.txt]
121+
[outfile report/types-of-anys.txt]
122+
Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact
123+
-----------------------------------------------------------------------------------------------------------------
124+
n 0 4 0 8 0 0 0
125+
-----------------------------------------------------------------------------------------------------------------
126+
Total 0 4 0 8 0 0 0
127+
106128
[case testTypeVarTreatedAsEmptyLine]
107129
# cmd: mypy --html-report report n.py
108130

@@ -480,7 +502,7 @@ namespace_packages = True
480502
<link rel="stylesheet" type="text/css" href="../../../mypy-html.css">
481503
</head>
482504
<body>
483-
<h2>folder.subfolder.something</h2>
505+
<h2>folder.subfolder.something</h2>
484506
<table>
485507
<caption>folder/subfolder/something.py</caption>
486508
<tbody><tr>

0 commit comments

Comments
 (0)