Comments (7)
Here's a slightly more minimal repro that doesn't involve Literal
or Any
:
from __future__ import annotations
from typing import Protocol, TypeVar, overload
X = TypeVar("X")
Y = TypeVar("Y")
X2 = TypeVar("X2")
Y2 = TypeVar("Y2")
class Transform(Protocol[X, Y]):
def __or__(self, other: Transform[X2, Y2]) -> Transform[tuple[X, X2], tuple[Y, Y2]]: ...
@overload
def chain_encoders(e: Transform[X, Y], simplify: bool) -> Transform[X, Y]: ...
@overload
def chain_encoders(*es: *tuple[*tuple[Transform, ...], Transform[X, object]]) -> Transform[X, Y]: ...
The cause is a recursion error; recursion errors cause segfaults if the code has been compiled with mypyc. Here's the last part of the traceback if you use an uncompiled version of mypy from the master
branch:
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 180, in is_subtype
return _is_subtype(left, right, subtype_context, proper_subtype=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 353, in _is_subtype
return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 1966, in accept
return visitor.visit_callable_type(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 711, in visit_callable_type
return is_callable_compatible(
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 1550, in is_callable_compatible
if not ignore_return and not is_compat_return(left.ret_type, right.ret_type):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 415, in _is_subtype
return is_subtype(left, right, subtype_context=self.subtype_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 180, in is_subtype
return _is_subtype(left, right, subtype_context, proper_subtype=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 353, in _is_subtype
return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 1422, in accept
return visitor.visit_instance(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 607, in visit_instance
if right.type.is_protocol and is_protocol_implementation(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/subtypes.py", line 1147, in is_protocol_implementation
if l == left and r == right:
^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 1434, in __eq__
and self.args == other.args
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 2406, in __eq__
return self.items == other.items and self.partial_fallback == other.partial_fallback
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 2406, in __eq__
return self.items == other.items and self.partial_fallback == other.partial_fallback
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/alexw/dev/mypy/mypy/types.py", line 2406, in __eq__
return self.items == other.items and self.partial_fallback == other.partial_fallback
^^^^^^^^^^^^^^^^^^^^^^^^^
[Previous line repeated 370 more times]
RecursionError: maximum recursion depth exceeded
from mypy.
An appropriate issue title might be something like "segfault on recursive protocol used in overloaded function that also uses PEP-646"
from mypy.
This has actually nothing to do with overloads or tuples. The real problem is diverging recursive protocols. These are very similar to diverging recursive aliases (that are plain prohibited at semanal level), even though they (theoretically) may have real use cases (e.g. an exercise: represent a non-mixed union like list[T] | list[list[T]] | list[list[list[T]]] | ...
).
Sorry for a detour, the real minimal repro is:
[case testDivergingProtocol]
from typing import Protocol, TypeVar, List
T = TypeVar("T")
class P(Protocol[T]):
def meth(self) -> P[List[T]]: ...
class C:
def meth(self) -> C: ...
x: P = C()
[builtins fixtures/tuple.pyi]
FWIW generic types like type A[T] = <something with A[Other[T]]>
, where Other
is an arbitrary non-identity (technically maybe non-linear, like not representable as a union with T
) type constructor, are highly problematic. And not just in mypy, to the best of my knowledge, the only existing "algorithm" to handle them is finite nesting expansion.
TBH I am not sure what to do. We may just prohibit such protocols, and require them to be nominal classes.
from mypy.
Maybe related to #17319, since I also do tuple unpacking.
from mypy.
For context, the __or__
method here is simply the binary Cartesian product of functions. All I am saying here is if one has a Transform
Transform
f | g
(as notational substitute for Transform
from
from mypy.
class P(Protocol[T]): def meth(self) -> P[List[T]]: ... class C: def meth(self) -> C: ...
Hm, I think I see the issue, when trying to test C <: P[T]
, the condition on .meth
leads to C <: P[T] ⟺ C <: P[list[T]] ⟺ C <: P[list[list[T]]] ⟺ ...
, an infinite regress. However, there are no additional conditions here, so shouldn't T=Unknown
be a trivial solution? That's what pyright
reports: Code sample in pyright playground
from typing import Protocol
class P[T](Protocol):
def meth(self) -> "P[list[T]]": ...
class C:
def meth(self) -> "C":
return self
def as_p[T](x: P[T]) -> P[T]:
return x
reveal_type(as_p(C())) # P[Unknown]
from mypy.
That's what
pyright
reports
Well, what do you think
export const maxTypeRecursionCount = 20;
mean?
from mypy.
Related Issues (20)
- Support typing.Union/typing.Optional in isinstance check (/support old-style unions) HOT 1
- Set the config file’s location with an environment variable.
- Can't call get on an empty dict
- Constrained `TypeVar` default causes false positive error if the default is a `TypedDict` type
- Clarification on how to Run .test Files? HOT 6
- Spurious assignment error in disjunt condition branches
- [good-first-issue] Incomplete Cobertura XML spec support
- Raise errors when importing from the `typing` package instead of using the built-in types. HOT 2
- RecursionError: maximum recursion depth exceeded HOT 8
- new generics should be inferred as covariant instead of invariant on frozen dataclasses
- `functools.reduce` over sets: empty set not accepted without annotation
- `functools.reduce` over sets becomes unacceptable when used in a larger expression
- Assertion Error in StubtestUnit::test_protocol with Python 3.7 Environment HOT 2
- assignment to `_` inside a function incorrectly becomes `Any`
- constrained TypeVar and star operator incompatible type
- `--untyped-calls-exclude` does not exclude some packages/libraries HOT 1
- Mypy cannot guess callable return type (`Tuple[Type[T], ...] -> T`) HOT 2
- Should mypy check existence of module attributes for unannotated modules? HOT 1
- False positive: "overloaded signature will never be matched" with Self
- module name assumed is __main__ for .pyw files on windows
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mypy.