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

Concatenate false positive (no problem with pyright) #14168

Closed
supersergiy opened this issue Nov 23, 2022 · 7 comments · Fixed by #15892
Closed

Concatenate false positive (no problem with pyright) #14168

supersergiy opened this issue Nov 23, 2022 · 7 comments · Fixed by #15892
Labels
bug mypy got something wrong topic-paramspec PEP 612, ParamSpec, Concatenate

Comments

@supersergiy
Copy link

Bug Report

Concatenate causes a false positive in the following example:

To Reproduce
Playground Link

from typing import Protocol
from typing_extensions import ParamSpec, Concatenate

P = ParamSpec("P")

class A(Protocol[P]):
    def foo(self, a: int, *args: P.args, **kwargs: P.kwargs):
        ...
        
class B(Protocol[P]):
    def foo(self, a: int, b: int, *args: P.args, **kwargs: P.kwargs):
        ...
    
def bar(b: B[P]) -> A[Concatenate[int, P]]:
    return b # error

Expected Behavior

No type error expected, which works with pyright (pyright playground)

Actual Behavior

# main.py:15: error: Incompatible return value type (got "B[P]", expected "A[[int, **P]]")  [return-value]
# main.py:15: note: Following member(s) of "B[P]" have conflicts:
# main.py:15: note:     Expected:
# main.py:15: note:         def foo(self, a: int, *args: [int, **P.args], **kwargs: [int, **P.kwargs]) -> Any
# main.py:15: note:     Got:
# main.py:15: note:         def foo(self, a: int, b: int, *args: P.args, **kwargs: P.kwargs) -> Any
# Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.991
@supersergiy supersergiy added the bug mypy got something wrong label Nov 23, 2022
@JelleZijlstra JelleZijlstra added the topic-paramspec PEP 612, ParamSpec, Concatenate label Nov 23, 2022
@ilevkivskyi
Copy link
Member

On master mypy emits a better error now:

error: Incompatible return value type (got "B[P]", expected "A[[int, **P]]")  [return-value]
note: Following member(s) of "B[P]" have conflicts:
note:     Expected:
note:         def foo(a: int, int, /, *args: P.args, **kwargs: P.kwargs) -> Any
note:     Got:
note:         def foo(self, a: int, b: int, *args: P.args, **kwargs: P.kwargs) -> Any

I think this should be allowed, function with named argument should be fine where a function with positional-only argument is expected (unless I am missing something). And this error also hints a workaround: making a and b arguments in both foo positional-only (e.g. using __a and __b argument names) makes the error go away.

@ilevkivskyi
Copy link
Member

ilevkivskyi commented Aug 16, 2023

OK, after reading the code, it looks like there is some unsafety here. Consider for example A[Concatenate[int, ...]] (btw I think we don't support this syntax yet) or similar, then the signature of A.foo is

def foo(self, a: int, int, *args: Any, **kwargs: Any)

and foo(1, 2, b="what?") is a valid call for this signature (because second argument is positional-only, so b will map to **kwargs), while it is obviously not valid for B. This is a super rare corner-case however, and funny part is that this check should be only enabled in --strict mode, but it was accidentally always on in few places.

ilevkivskyi added a commit that referenced this issue Aug 17, 2023
Fixes #14169
Fixes #14168

Two sings here:
* Actually check prefix when we should
* `strict_concatenate` check should be off by default (IIUC it is not
mandated by the PEP)
@hauntsaninja
Copy link
Collaborator

@supersergiy is the project you were running into this on open source?

@supersergiy
Copy link
Author

@hauntsaninja yup it is, why?

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Aug 20, 2023

Where can I find it — is it https://github.com/ZettaAI/zetta_utils? I'd like to add it to https://github.com/hauntsaninja/mypy_primer . This will let us detect regressions or measure future improvements on your code. I think we could use more coverage of real world ParamSpec usage.

@supersergiy
Copy link
Author

Yup, that's the one. Happy if it helps

@hauntsaninja
Copy link
Collaborator

It has already helped :-) #15953 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-paramspec PEP 612, ParamSpec, Concatenate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants