Uh oh!
There was an error while loading. Please reload this page.
Update list.{count, index, remove} to accept object type - #15472
Update list.{count, index, remove} to accept object type#15472randolf-scholz wants to merge 8 commits into
object type#15472Conversation
This comment has been minimized.
This comment has been minimized.
Hm, not exactly sure what's going on with defcount(self, value: Any, /) ->int:
"""Return the number of occurrences of `value`."""raiseNotImplementedErrordefindex(self, value: Any, /) ->int:
"""Return the first index of `value`."""raiseNotImplementedErrorthen after we make EDIT: I am starting to think that this may be related to mypy interal solver semantics. we removed some constrains, so now it may find solutions for the |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
srittau
commented
May 8, 2026
The primer output is not promising. The fixed |
randolf-scholz
commented
May 8, 2026
The main issue seems to be [var-annotated] issue originating from numpy: importnumpyasnpreveal_type(np.array([])) |
randolf-scholz
commented
May 8, 2026
@srittau I wouldn't call the colour results true-positives. For instance https://github.com/colour-science/colour/blob/c9cfa1f333452cc05e42f09eebd2f3dd935a5981/colour/utilities/network.py#L1756-L1773 is exactly one of the cases of a valid |
randolf-scholz
commented
May 8, 2026
OK, I think I have a repro of the numpy issue that causes the [var-annotated] errors. It has to do with the fromtypingimportAny, Protocol, reveal_typeclassNestedSeq[_T_co](Protocol):
def__getitem__(self, index: int, /) ->"_T_co | NestedSeq[_T_co]":
raiseNotImplementedErrordefcount(self, value: Any, /) ->int:
raiseNotImplementedErrordefas_nested_sequence[T](seq: NestedSeq[T], /) ->NestedSeq[T]:
returnseqreveal_type(as_nested_sequence([]))
# main: NestedSeq[Any], PR: NestedSeq[Never]And this happens due to how mypy solves type-vars. on main, Imo, this is more of a mypy problem than a typeshed problem. But it could be worked around if for example numpy used |
Sure, we could do that. |
jorenham
commented
May 8, 2026
The workaround will be present in the upcoming 2.4.5 and 2.5.0 releases. |
jorenham
commented
May 15, 2026
numpy 2.4.5 was just released (https://github.com/numpy/numpy/releases/tag/v2.4.5) |
This comment has been minimized.
This comment has been minimized.
randolf-scholz
commented
May 16, 2026
@jorenham Ugh, terribly sorry but that wasn't sufficient. @overloaddefarray(
object: _ArrayLike[_ScalarT],
dtype: None=None,
*,
copy: bool|_CopyMode|None=True,
order: _OrderKACF="K",
subok: bool=False,
ndmin: int=0,
ndmax: int=0,
like: _SupportsArrayFunc|None=None,
) ->NDArray[_ScalarT]: ...because it doesn't find any constraints on So actually it is this typevar that needs a default (either Again, sorry for not testing this more thoroughly locally, doing the default on Footnotes
|
jorenham
commented
May 16, 2026
Ah no worries. At least we know what to put in the mypy bug report now ;) |
randolf-scholz
commented
May 17, 2026
@srittau I inspected the optunavisualization_tests/test_rank.py#L699: This error should be expected. If colour
pandas
xarray
scipy-stubs
|
This comment has been minimized.
This comment has been minimized.
randolf-scholz
commented
May 17, 2026
The pyright failures seem unrelated |
Those are indeed tests for true positives. The trick is that in scipy-stubs all type-checkers are configured to complain in case of unused ignore comments. So it's indeed a good thing that mypy now also reports an error. |
Diff from mypy_primer, showing the effect of this PR on open source code: optuna (https://github.com/optuna/optuna)
+ tests/visualization_tests/test_rank.py:699: error: Need type annotation for "x2" [var-annotated]
colour (https://github.com/colour-science/colour)
- colour/utilities/network.py:1772: error: Argument 1 to "remove" of "list" has incompatible type "PortNode"; expected "Self" [arg-type]- colour/notation/munsell/centore2014.py:2053: error: Argument 1 to "index" of "list" has incompatible type "tuple[Any, Any, Any]"; expected "tuple[float, float]" [arg-type]- colour/notation/munsell/centore2014.py:2058: error: Argument 1 to "index" of "list" has incompatible type "tuple[Any, Any, Any]"; expected "tuple[float, float]" [arg-type]- colour/notation/munsell/centore2014.py:2065: error: Argument 1 to "index" of "list" has incompatible type "tuple[Any, Any, Any]"; expected "tuple[float, float]" [arg-type]- colour/notation/munsell/centore2014.py:2070: error: Argument 1 to "index" of "list" has incompatible type "tuple[Any, Any, Any]"; expected "tuple[float, float]" [arg-type]- colour/plotting/models.py:1457: error: Incompatible types in assignment (expression has type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]", variable has type "ndarray[tuple[Any, ...], dtype[Any]]") [assignment]+ colour/plotting/models.py:1457: error: Incompatible types in assignment (expression has type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]", variable has type "ndarray[Any, Any]") [assignment]
pwndbg (https://github.com/pwndbg/pwndbg)
+ pwndbg/aglib/elf.py:448: error: Unused "type: ignore" comment [unused-ignore]
dedupe (https://github.com/dedupeio/dedupe)
+ dedupe/labeler.py:410: error: List item 1 has incompatible type "Iterable[Literal[0, 1]]"; expected "_SupportsArray[dtype[signedinteger[_64Bit]]] | _NestedSequence[_SupportsArray[dtype[signedinteger[_64Bit]]]]" [list-item]
pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/dtypes/dtypes.py:983: error: Need type annotation for "np_dtype" [var-annotated]+ pandas/core/dtypes/dtypes.py:984: error: Argument 1 has incompatible type "list[dtype[Any] | ExtensionDtype]"; expected "_SupportsArray[dtype[Never]] | _NestedSequence[_SupportsArray[dtype[Never]]]" [arg-type]+ pandas/core/arrays/sparse/array.py:1526: error: Need type annotation for "sparse_values" [var-annotated]+ pandas/core/internals/managers.py:2502: error: List comprehension has incompatible type List[ndarray[tuple[Any, ...], dtype[Any]] | ExtensionArray]; expected List[_SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]]] [misc]+ pandas/plotting/_matplotlib/misc.py:170: error: Need type annotation for "s" [var-annotated]+ pandas/plotting/_matplotlib/core.py:1207: error: List item 0 has incompatible type "Number | number[Any, int | float | complex]"; expected "_SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]]" [list-item]
xarray (https://github.com/pydata/xarray)
+ xarray/tests/test_concat.py: note: In function "create_typed_datasets":+ xarray/tests/test_concat.py:112: error: Argument 1 to "reshape" has incompatible type "list[Timedelta]"; expected "_SupportsArray[dtype[Never]] | _NestedSequence[_SupportsArray[dtype[Never]]]" [arg-type]+ xarray/tests/test_concat.py: note: At top level:+ xarray/tests/test_backends.py: note: In member "test_mask_and_scale" of class "NetCDF4Base":+ xarray/tests/test_backends.py:2090: error: Need type annotation for "expected" [var-annotated]+ xarray/tests/test_backends.py: note: At top level:
scipy-stubs (https://github.com/scipy/scipy-stubs)
+ tests/linalg/test_blas.pyi:27: error: Expression is of type "list[_FortranFunction]", not "list[_FortranFunction] | _FortranFunction" [assert-type]+ tests/linalg/test__decomp_svd.pyi:72: error: Unused "type: ignore" comment [unused-ignore]+ tests/linalg/test__decomp_svd.pyi:73: error: Unused "type: ignore" comment [unused-ignore]+ tests/linalg/test__decomp_svd.pyi:74: error: Unused "type: ignore" comment [unused-ignore]+ tests/special/test_ufuncs.pyi:75: error: Argument 1 to "__call__" of "_UFunc11f" has incompatible type "list[complex]"; expected "CanArrayND[floating[_16Bit] | integer[Any] | numpy.bool[builtins.bool], tuple[Any, ...]] | SequenceND[CanArrayND[floating[_16Bit] | integer[Any] | numpy.bool[builtins.bool], tuple[Any, ...]]] | SequenceND[JustFloat | int]" [arg-type]+ tests/special/test_ufuncs.pyi:75: note: "list" is missing following "CanArrayND" protocol member:+ tests/special/test_ufuncs.pyi:75: note: __array__ |
I think More generally, I don't think it makes sense to allow an overlapping type in these methods (let alone |
randolf-scholz
commented
May 19, 2026
@Akuli There are legitimate use cases, for instance calling classRGB: ...
classRGBA(RGB): ...
classDemo:
colors: list[RGBA]
defcheck_value(self, value: RGB) ->None:
ifvalueinself.colors:
position=self.colors.index(value)
...I understand why you want |
Akuli
commented
May 19, 2026
In your example, ideally the type checker would narrow the type of You could also make the same argument with any other operation that needs an classRGB:
red: floatgreen: floatblue: float
...
classRGBA(RGB):
alpha: float
...
colors: list[RGBA] = [...]
value=get_some_rgb_color()
ifvalueincolors:
print(f"opacity is {value.alpha}")More generally, the correct fix is to help type checkers know the correct type, not to silence errors when they have the wrong type. To be concrete, I would be very surprised if mistakes like |
randolf-scholz
commented
May 19, 2026
This would not be ideal, but actually incorrect as list containment is equality based. Your own example will error on the line fromdataclassesimportdataclass@dataclass(frozen=True)classRGB:
red: intgreen: intblue: int@dataclass(frozen=True)classRGBA(RGB):
alpha: int=255def__eq__(self, other):
ifisinstance(other, RGBA):
returnhash(self) ==hash(other)
ifisinstance(other, RGB):
returnRGB.__hash__(self) ==hash(other) andself.alpha==255returnNotImplementedblack=RGB(0, 0, 0)
colors= [RGBA(0, 0, 0)]
ifblackincolors:
print(black.alpha) # ERROR at runtimeanother example with pytorch: importtorch# Note: torch.Size subclasses tuple[int, ...]sizes: list[torch.Size] = [torch.Size([1, 2, 3])]
print(sizes[0].numel()) # 6 (product of values)value= (1, 2, 3)
ifvalueinsizes:
print(value.numel()) # ERROR |
randolf-scholz
commented
May 19, 2026
There is actually a regression in |
Akuli
commented
May 19, 2026
I see. There might not be a way to express this so that overrided There are probably many other places too where overrided |
randolf-scholz
commented
May 19, 2026
Again I think what you want is a fine strict linter rule to have, but you seem very eager to force this linter rule on everyone else, even when it caues false positives in their code. |
Partially fixes#15271