-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Issue with constrained type var and Protocol #18024
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
Comments
Looks potentially related to python/typeshed#12286 (which landed in v1.12.0 with #17586) |
|
Cannot infer type argument
for open & gzipCannot infer type argument
for open & gzip
Here's an attempt to create a simplified, self-contained reproducer: from typing import AnyStr, Protocol, TypeVar, Generic, overload
class Buffer(Protocol):
def __buffer__(self, flags: int, /) -> memoryview: ...
class IO(Generic[AnyStr]):
@overload
def write(self: IO[bytes], s: Buffer, /) -> int: ...
@overload
def write(self, s: AnyStr, /) -> int: ...
def write(self, s):
return 0
class TextIO(IO[str]):
pass
_T_contra = TypeVar("_T_contra", contravariant=True)
class SupportsWrite(Protocol[_T_contra]):
def write(self, s: _T_contra, /) -> object: ...
def foo(
f: SupportsWrite[AnyStr],
) -> None: ...
def bar(d: TextIO) -> None:
foo(d) # Value of type variable "AnyStr" of "foo" cannot be "Buffer" Interestingly, this fails on 1.11 as well, and doesn't depend on the changes in #17586. I looked at this a bit, it seems that constraints inference from protocol generates invalid constraints ( @ilevkivskyi I remember that you mentioned that you've looked into inconsistencies between |
Y
8000
es, and it may not be trivial to fix. Ultimately, we need to refactor this, so that everything uses |
It may still be possible to fix this specific regression by a more ad-hoc fix, by adding some functionality to |
As of at least version 1.15.0, this issue seems to be resolved...
|
Hm yeah, looks like it got fixed in a more recent typeshed sync: #17971 Jukka's self contained repro still reproduces, so we should keep this issue open It could also maybe be worth adding a test case to typeshed |
Cannot infer type argument
for open & gzipFixes #18024 Fixes #18706 Fixes #17734 Fixes #15097 Fixes #14814 Fixes #14806 Fixes #14259 Fixes #13041 Fixes #11993 Fixes #9585 Fixes #9266 Fixes #9202 Fixes #5481 This is a fourth "major" PR toward #7724. This is one is watershed/crux of the whole series (but to set correct expectations, there are almost a dozen smaller follow-up/clean-up PRs in the pipeline). The core of the idea is to set current type-checker as part of the global state. There are however some details: * There are cases where we call `is_subtype()` before type-checking. For now, I fall back to old logic in this cases. In follow up PRs we may switch to using type-checker instances before type checking phase (this requires some care). * This increases typeops import cycle by a few modules, but unfortunately this is inevitable. * This PR increases potential for infinite recursion in protocols. To mitigate I add: one legitimate fix for `__call__`, and one temporary hack for `freshen_all_functions_type_vars` (to reduce performance impact). * Finally I change semantics for method access on class objects to match the one in old `find_member()`. Now we will expand type by instance, so we have something like this: ```python class B(Generic[T]): def foo(self, x: T) -> T: ... class C(B[str]): ... reveal_type(C.foo) # def (self: B[str], x: str) -> str ``` FWIW, I am not even 100% sure this is correct, it seems to me we _may_ keep the method generic. But in any case what we do currently is definitely wrong (we infer a _non-generic_ `def (x: T) -> T`). --------- Co-authored-by: hauntsaninja <hauntsaninja@gmail.com> Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Fixes python#18024 Fixes python#18706 Fixes python#17734 Fixes python#15097 Fixes python#14814 Fixes python#14806 Fixes python#14259 Fixes python#13041 Fixes python#11993 Fixes python#9585 Fixes python#9266 Fixes python#9202 Fixes python#5481 This is a fourth "major" PR toward python#7724. This is one is watershed/crux of the whole series (but to set correct expectations, there are almost a dozen smaller follow-up/clean-up PRs in the pipeline). The core of the idea is to set current type-checker as part of the global state. There are however some details: * There are cases where we call `is_subtype()` before type-checking. For now, I fall back to old logic in this cases. In follow up PRs we may switch to using type-checker instances before type checking phase (this requires some care). * This increases typeops import cycle by a few modules, but unfortunately this is inevitable. * This PR increases potential for infinite recursion in protocols. To mitigate I add: one legitimate fix for `__call__`, and one temporary hack for `freshen_all_functions_type_vars` (to reduce performance impact). * Finally I change semantics for method access on class objects to match the one in old `find_member()`. Now we will expand type by instance, so we have something like this: ```python class B(Generic[T]): def foo(self, x: T) -> T: ... class C(B[str]): ... reveal_type(C.foo) # def (self: B[str], x: str) -> str ``` FWIW, I am not even 100% sure this is correct, it seems to me we _may_ keep the method generic. But in any case what we do currently is definitely wrong (we infer a _non-generic_ `def (x: T) -> T`). --------- Co-authored-by: hauntsaninja <hauntsaninja@gmail.com> Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Bug Report
Seems like a regression from 11.2, consider the following
I see errors even though this should be fine?
no errors in 1.11.2:
Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: