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

False-positive cannot assign expression to yield type (with TypeVar, overload, and Union) #1809

Closed
cdce8p opened this issue Sep 12, 2021 · 6 comments
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@cdce8p
Copy link

cdce8p commented Sep 12, 2021

Environment data

  • Language Server version: 2021.9.1
  • OS and version: darwin x64
  • Python version: 3.10.0rc2
  • python.analysis.indexing: true
  • python.analysis.typeCheckingMode: basic

Expected behaviour

no error

Actual behaviour

Expression of type "X" cannot be assigned to yield type "T1@return_iter | T2@return_iter"
  Type "X" cannot be assigned to type "T1@return_iter | T2@return_iter"
    Type "X" cannot be assigned to type "T1@return_iter"
    Type "X" cannot be assigned to type "T2@return_iter"

Logs

--

Code Snippet / Additional information

from typing import TypeVar, overload, Iterator

T1 = TypeVar("T1", bound="X")
T2 = TypeVar("T2", bound="X")

class X:
    element_list: list["X"]

    @overload
    def return_iter(self, klass: type[T1]) -> Iterator[T1]:
        ...

    @overload
    def return_iter(self, klass: tuple[type[T1], type[T2]]) -> Iterator[T1] | Iterator[T2]:
        ...

    def return_iter(self, klass: type[T1] | tuple[type[T1], type[T2]]) -> Iterator[T1] | Iterator[T2]:
        for item in self.element_list:
            if isinstance(item, klass):
                yield item  # error

Mypy output
no error

@judej
Copy link
Contributor

judej commented Sep 13, 2021

Thanks for the report.

@github-actions github-actions bot removed the triage label Sep 13, 2021
@erictraut
Copy link
Contributor

Thanks, this will be fixed in the next release.

The code that handles isinstance and issubclass type narrowing was handling the case where the second argument was a union of classes or a tuple of classes, but it didn't properly handle a union that included both classes and tuples of classes. That's now fixed.

@erictraut erictraut added bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version and removed needs investigation Could be an issue - needs investigation labels Sep 14, 2021
@jakebailey
Copy link
Member

This issue has been fixed in version 2021.9.2, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202192-16-september-2021

@cdce8p
Copy link
Author

cdce8p commented Sep 17, 2021

This is still an issue when modified slightly:

from typing import TypeVar, Iterator

T1 = TypeVar("T1", bound="X")
T2 = TypeVar("T2", bound="X")


class X:
    element_list: list["X"]

    def return_iter(
        self, klass: type[T1] | tuple[type[T1], type[T2]] | tuple[type[T1], ...]
    ) -> Iterator[T1] | Iterator[T2]:
        for item in self.element_list:
            if isinstance(item, klass):
                yield item  # error

Added tuple[type[T1], ...] as fallback for tuples with len > 2. No error when tested with mypy.

@erictraut
Copy link
Contributor

You're right — I didn't handle the required special casing for open-ended tuples (the ... form) in this code path. It will be fixed in the next release.

@cdce8p
Copy link
Author

cdce8p commented Sep 17, 2021

You're right — I didn't handle the required special casing for open-ended tuples (the ... form) in this code path. It will be fixed in the next release.

Thank you @erictraut! I appreciate how fast you and the team address these issues. It's amazing to see pylance and pyright getting better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version
Projects
None yet
Development

No branches or pull requests

4 participants