Skip to content

Commit afb99eb

Browse files
authored
Fix union edge case in function argument redefinition (#20908)
Logic is simple: inference for function arguments should match inference for regular annotated variables exactly, including falling back to empty context in _union context_ (even if there are no errors) provided this results in a narrower type.
1 parent 40498e8 commit afb99eb

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

mypy/checker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4725,7 +4725,7 @@ def infer_rvalue_with_fallback_context(
47254725
# and use it results in a narrower type. This helps with various practical
47264726
# examples, see e.g. testOptionalTypeNarrowedByGenericCall.
47274727
union_fallback = (
4728-
inferred is None
4728+
preferred_context is not None
47294729
and isinstance(get_proper_type(lvalue_type), UnionType)
47304730
and binder_version == self.binder.version
47314731
)
@@ -4744,7 +4744,7 @@ def infer_rvalue_with_fallback_context(
47444744
not alt_local_errors.has_new_errors()
47454745
and is_valid_inferred_type(alt_rvalue_type, self.options)
47464746
and (
4747-
# For redefinition fallback we are fine getting not a subtype.
4747+
# For redefinition fallbacks we are fine getting not a subtype.
47484748
redefinition_fallback
47494749
or argument_redefinition_fallback
47504750
# Skip Any type, since it is special cased in binder.

test-data/unit/check-redefine2.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,30 @@ def process(items: list[Optional[str]]) -> None:
13211321
reveal_type(items) # N: Revealed type is "builtins.list[builtins.str | None]"
13221322
process(items) # OK
13231323

1324+
[case testNewRedefineUnionArgumentFallbackUnion]
1325+
# flags: --allow-redefinition-new --local-partial-types
1326+
from typing import Union, Optional, TypeVar, Sequence
1327+
1328+
T = TypeVar("T")
1329+
def gen(x: T) -> Union[str, T]: ...
1330+
1331+
def test(x: Optional[str]) -> None:
1332+
if x is None:
1333+
x = gen("foo")
1334+
reveal_type(x) # N: Revealed type is "builtins.str"
1335+
1336+
[case testNewRedefineUnionArgumentFallbackAsync]
1337+
# flags: --allow-redefinition-new --local-partial-types
1338+
from typing import Optional, TypeVar
1339+
1340+
T = TypeVar("T")
1341+
async def gen(x: T) -> T: ...
1342+
1343+
async def test(x: Optional[str]) -> None:
1344+
if x is None:
1345+
x = await gen("foo")
1346+
reveal_type(x) # N: Revealed type is "builtins.str"
1347+
13241348
[case testNewRedefineFunctionArgumentsEmptyContext]
13251349
# flags: --allow-redefinition-new --local-partial-types
13261350
def process1(items: list[str]) -> None:

0 commit comments

Comments
 (0)