Skip to content

Commit 6fdd068

Browse files
committed
Fix wrong inference cache result for typing.cast calls inside functions
1 parent dfd88f5 commit 6fdd068

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

ChangeLog

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ Release date: TBA
1414

1515
* Fix issues with ``typing_extensions.TypeVar``.
1616

17-
1817
* Fix ``ClassDef.fromlino`` for PyPy 3.8 (v7.3.11) if class is wrapped by a decorator.
1918

19+
* Fix wrong inference cache result for ``typing.cast`` calls inside functions.
20+
21+
Closes PyCQA/pylint#8074
22+
2023

2124
What's New in astroid 2.13.3?
2225
=============================

astroid/brain/brain_typing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def infer_typing_cast(
419419
Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript
420420
)
421421
AstroidManager().register_transform(
422-
Call, inference_tip(infer_typing_cast), _looks_like_typing_cast
422+
Call, inference_tip(infer_typing_cast, cached=False), _looks_like_typing_cast
423423
)
424424

425425
if PY39_PLUS:

astroid/inference_tip.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,16 @@ def _inference_tip_cached(
4747
return iter(result)
4848

4949

50-
def inference_tip(infer_function: InferFn, raise_on_overwrite: bool = False) -> InferFn:
50+
def inference_tip(
51+
infer_function: InferFn, raise_on_overwrite: bool = False, *, cached: bool = True
52+
) -> InferFn:
5153
"""Given an instance specific inference function, return a function to be
5254
given to AstroidManager().register_transform to set this inference function.
5355
5456
:param bool raise_on_overwrite: Raise an `InferenceOverwriteError`
5557
if the inference tip will overwrite another. Used for debugging
58+
:param cached: Whether to cache the inference function and reuse the result.
59+
Set to 'False' if the result is dependents on the caller.
5660
5761
Typical usage
5862
@@ -84,7 +88,9 @@ def transform(node: NodeNG, infer_function: InferFn = infer_function) -> NodeNG:
8488
)
8589
)
8690
# pylint: disable=no-value-for-parameter
87-
node._explicit_inference = _inference_tip_cached(infer_function)
91+
node._explicit_inference = (
92+
_inference_tip_cached(infer_function) if cached else infer_function
93+
)
8894
return node
8995

9096
return transform

tests/unittest_brain.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,8 +2132,7 @@ class A:
21322132
pass
21332133
21342134
b = 42
2135-
a = cast(A, b)
2136-
a
2135+
cast(A, b)
21372136
"""
21382137
)
21392138
inferred = next(node.infer())
@@ -2148,14 +2147,33 @@ class A:
21482147
pass
21492148
21502149
b = 42
2151-
a = typing.cast(A, b)
2152-
a
2150+
typing.cast(A, b)
21532151
"""
21542152
)
21552153
inferred = next(node.infer())
21562154
assert isinstance(inferred, nodes.Const)
21572155
assert inferred.value == 42
21582156

2157+
def test_typing_cast_multiple_inference_calls(self) -> None:
2158+
ast_nodes = builder.extract_node(
2159+
"""
2160+
from typing import TypeVar, cast
2161+
T = TypeVar("T")
2162+
def ident(var: T) -> T:
2163+
return cast(T, var)
2164+
2165+
ident(2) #@
2166+
ident("Hello") #@
2167+
"""
2168+
)
2169+
i0 = next(ast_nodes[0].infer())
2170+
assert isinstance(i0, nodes.Const)
2171+
assert i0.value == 2
2172+
2173+
i1 = next(ast_nodes[1].infer())
2174+
assert isinstance(i1, nodes.Const)
2175+
assert i1.value == "Hello"
2176+
21592177

21602178
@pytest.mark.skipif(
21612179
not HAS_TYPING_EXTENSIONS,

0 commit comments

Comments
 (0)