Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

TypeVar yields an error when used with reduce #4614

Closed
egeres opened this issue Jul 16, 2023 · 2 comments
Closed

TypeVar yields an error when used with reduce #4614

egeres opened this issue Jul 16, 2023 · 2 comments
Assignees

Comments

@egeres
Copy link

egeres commented Jul 16, 2023

👉🏻 Describe the bug
When analyzing the code from below, I get:

Expression of type "list[int]" cannot be assigned to return type "T@foo"
  Type "list[int]" cannot be assigned to type "T@foo"Pylance[reportGeneralTypeIssues](...

This seems to happen because, the output of reduce is correctly parsed as a list[int], but then that type would be different from list[T], even if T is bound to list[int]

👉🏻 To Reproduce
Put the code below in VSCode + pylance version v2023.7.20

👉🏻 Expected behavior
If a TypeVar is bound to a type (even if it's a composition using Union etc...), Pylance should consider another type valid if it matches with the bound of such TypeVar

👉🏻 Code

from functools import reduce
from typing import TypeVar

T = TypeVar("T", bound=list[int])

def foo(x: list[T]) -> T:
    return reduce(lambda a, b: a + b, x)

👉🏻 VS Code extension or command-line
Running pylance in VSCode as an extension!

@erictraut
Copy link
Contributor

Pyright is correct to emit an error here. You're using a TypeVar that is bound to list[int]. Here's the applicable overload for reduce:

def reduce(function: Callable[[_T, _T], _T], sequence: Iterable[_T]) -> _T:
    ...

That means the two inputs to the callable must be the same type as the output. In your case, the inputs are type T, but the output is type list[int]. The expression a + b in the lambda maps to the method __add__ in the list class. This is defined to always return another list, not a Self. That means if T happens to be a subclass of list, the a + b operation will not produce the same subtype.

Not surprisingly, mypy generates the same error for this code.

Here's how to adjust your code so it type checks without error:

T = TypeVar("T")

def foo(x: Iterable[list[T]]) -> list[T]:
    return reduce(lambda a, b: a + b, x)

@egeres
Copy link
Author

egeres commented Jul 16, 2023

I'm sorry I didn't see this and reported a false positive!! 🙇🏻‍♂️

@egeres egeres closed this as completed Jul 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants