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

Walrus operator causes no overload match for str.join in dataclass #9659

Closed
ostr00000 opened this issue Jan 4, 2025 · 2 comments
Closed
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working

Comments

@ostr00000
Copy link

Describe the bug

Pyright reports an error when a walrus operator is used while passing a variable to str.join and then to a dataclass.
The error is: No overloads for "join" match the provided arguments.

Code or Screenshots

from dataclasses import dataclass

@dataclass
class T_dataclass:
    base: list[str]
    joined: str

T_dataclass(
    base=(b := ['abc', 'def']),
    joined=' '.join(b),
)

Similar code with no error

  • when we define variable not in walrus, then there is no error:
b = ['abc', 'def']
T_dataclass(base=b, joined=' '.join(b))
  • when we define normal class instead of dataclass, then there is no error:
class T_normal:
    def __init__(self, base: list[str], joined: str):
        self.base = base
        self.joined = joined

b = ['abc', 'def']
T_normal(base=b, joined=' '.join(b))

T_normal(
    base=(b := ['abc', 'def']),
    joined=' '.join(b),
)

VS Code extension or command-line

Error detected in VS Code by Pylance. Pylance version is 2024.12.1.

Also, the error is replicated in pyright playground for version 1.1.391.

@ostr00000 ostr00000 added the bug Something isn't working label Jan 4, 2025
erictraut added a commit that referenced this issue Jan 14, 2025
…ion (walrus operator) is used as an argument to a constructor call when the constructor has both a `__new__` and `__init__` with differing bidirectional type inference contexts. This addresses #9659.
erictraut added a commit that referenced this issue Jan 14, 2025
…ion (walrus operator) is used as an argument to a constructor call when the constructor has both a `__new__` and `__init__` with differing bidirectional type inference contexts. This addresses #9659. (#9699)
@erictraut
Copy link
Collaborator

Thanks for the bug report. The reason this happens with a dataclass and not the class in your example is that the dataclass has both an __init__ and a __new__ method (both synthesized), and the parameters corresponding to the argument that includes the walrus operator have different bidirectional type inference contexts.

If I add a __new__ method to your second code sample above, we can recreate the bug without the use of a dataclass.

from typing import Any, Self

class T_normal:
    def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...
    def __init__(self, base: list[str], joined: str): ...

T_normal(base=(b := ["abc", "def"]), joined=" ".join(b))

In case you're interested in the details... The bug is related to the way that pyright internally caches the type of a subexpression once it is evaluated. In this case, the subexpression b := ["abc", "def"] was being evaluated with the inference context of Any (thanks to the **kwargs annotation in the __new__ method). The resulting type of that subexpression is list[Any]. The same subexpression evaluated in the context of the __init__ method is evaluated as type list[str], but the list[Any] type had already been cached. This confused the overload evaluation logic when evaluating the expression ' '.join(b).

This will be addressed in the next release.

@erictraut erictraut added the addressed in next version Issue is fixed and will appear in next published version label Jan 14, 2025
@erictraut
Copy link
Collaborator

This is addressed in pyright 1.1.392.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants