-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Enhance reportInvalidTypeVarUse to report situations where class-scoped TypeVars may go unsolved in constructor #3501
Comments
@JelleZijlstra, I've implemented this expanded check. It reports an additional 32 errors within typeshed (in addition to the 37 errors reported for function-scoped TypeVars that may go unsolved). Here's a full list of the errors, which includes both of the above:
|
@JelleZijlstra, I'm having second thoughts about this expanded check. I think it may result in less type safe code. The problem is that if you make changes to typeshed to eliminate the above errors, I presume you'll do so by explicitly supplying an For example, here's the current constructor for class UserList(MutableSequence[_T]):
def __init__(self, initlist: Iterable[_T] | None = ...) -> None: ... To eliminate the new error, it will need to be changed to: class UserList(MutableSequence[_T]):
@overload
def __init__(self, initlist: Iterable[_T]) -> None: ...
@overload
def __init__(self: UserList[Any], initlist: None = ...) -> None: ... Previously, a user could have used: x1 = UserList()
reveal_type(x1) # UserList[Unknown]
x2 = UserList[int]()
reveal_type(x2) # UserList[int] Now, this will result in the following: x1 = UserList()
reveal_type(x1) # UserList[Any]
x2 = UserList[int]()
reveal_type(x2) # UserList[Any] This seems like a step backward, so I'm inclined to revert this change. What do you think? I suppose the error could be eliminated without adding an explicit class UserList(MutableSequence[_T]):
@overload
def __init__(self, initlist: Iterable[_T]) -> None: ...
@overload
def __init__(self, initlist: None = ...) -> None: ... But this will still result in an unsolved TypeVar, which defeats the purpose of adding an overload and flagging the original constructor declaration as an inappropriate use of a TypeVar. |
Yes, empty collections are a tricky situation. Looking at the collection builtins, there are three options:
@overload
def __init__(self) -> None: ...
@overload
def __init__(self: dict[_KT, _VT]) -> None: ...
def __init__(self, __iterable: Iterable[_T] = ...) -> None: ... Only the Do you have a preference between the |
@JelleZijlstra If after making the change, there would still be unsolved TypeVar anyway, then we could just ignore the error too, instead of adding overloads. And is it only empty collections where this will be an issue? |
Many cases (e.g., FileInput) do have correct solutions when the default is used. I think it's worth it to add this check to help us catch such cases. |
Okay well at least it is a separate rule, so can be enabled/disabled by choice without affecting other rules. |
OK, you've convinced me that we should leave this new check in place. I reserve the right to revert it if we get a backlash from pyright users, but I'm willing to publish a new version with this check in place.
I don't have a preference between these two. They both seem fine to me. |
This is addressed in pyright 1.1.249, which I just published. It will also be included in the next release of pylance. |
…tructors (#7944) See microsoft/pyright#3501 (comment) Related to #7928
From the list in microsoft/pyright#3501
- TypeVar changes from microsoft/pyright#3501 - Fix pos-only param - Use protocols instead of IO classes
From the list in microsoft/pyright#3501
- TypeVar changes from microsoft/pyright#3501 - Fix pos-only param - Use protocols instead of IO classes
This is similar to #3495 but applies to constructors and class-scoped TypeVars.
The text was updated successfully, but these errors were encountered: