Skip to content

Extend special case for context-based typevar inference to typevar unions in return position #18976

New issue

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

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

Already on GitHub? # to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
7 changes: 6 additions & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2013,7 +2013,12 @@ def infer_function_type_arguments_using_context(
# variables in an expression are inferred at the same time.
# (And this is hard, also we need to be careful with lambdas that require
# two passes.)
if isinstance(ret_type, TypeVarType):
proper_ret = get_proper_type(ret_type)
if (
isinstance(proper_ret, TypeVarType)
or isinstance(proper_ret, UnionType)
and all(isinstance(get_proper_type(u), TypeVarType) for u in proper_ret.items)
):
# Another special case: the return type is a type variable. If it's unrestricted,
# we could infer a too general type for the type variable if we use context,
# and this could result in confusing and spurious type errors elsewhere.
Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-inference-context.test
Original file line number Diff line number Diff line change
Expand Up @@ -1495,3 +1495,18 @@ def g(b: Optional[str]) -> None:
z: Callable[[], str] = lambda: reveal_type(b) # N: Revealed type is "builtins.str"
f2(lambda: reveal_type(b)) # N: Revealed type is "builtins.str"
lambda: reveal_type(b) # N: Revealed type is "builtins.str"

[case testInferenceContextReturningTypeVarUnion]
from collections.abc import Callable, Iterable
from typing import TypeVar, Union

_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")

def mymin(
iterable: Iterable[_T1], /, *, key: Callable[[_T1], int], default: _T2
) -> Union[_T1, _T2]: ...

def check(paths: Iterable[str], key: Callable[[str], int]) -> Union[str, None]:
return mymin(paths, key=key, default=None)
[builtins fixtures/tuple.pyi]