pyright icon indicating copy to clipboard operation
pyright copied to clipboard

Numpy type checking false positive

Open hmc-cs-mdrissi opened this issue 1 year ago • 3 comments

Describe the bug

from numpy._typing._array_like import _ArrayLikeNumber_co


def f(x: list[float]):
    _: _ArrayLikeNumber_co = x

This code fails to type check on 1.1.383 but passes on 1.1.382. The error message is,

  /Users/pa-loaner/Snapchat/Dev/training-platform/scratch/debug_pyright.py:5:30 - error: Type "list[float]" is not assignable to declared type "_ArrayLikeNumber_co"
    Type "list[float]" is not assignable to type "_ArrayLikeNumber_co"
      "list[float]" is incompatible with protocol "_SupportsArray[dtype[bool_ | number[Any]]]"
        "__array__" is not present
      "list[float]" is incompatible with protocol "_NestedSequence[_SupportsArray[dtype[bool_ | number[Any]]]]"
        "__getitem__" is an incompatible type
          One or more overloads of "__getitem__" is not assignable
            No overloaded function matches type "(index: int, /) -> (_T_co@_NestedSequence | _NestedSequence[_T_co@_NestedSequence])"
        "__iter__" is an incompatible type
    ... (reportAssignmentType)

The definition of _ArrayLikeNumber_co is (including key related definitions),

_T_co = TypeVar("_T_co", covariant=True)

class _NestedSequence(Protocol[_T_co]):
    @overload
    def __getitem__(self, index: int, /) -> _T_co | _NestedSequence[_T_co]: ...
    @overload
    def __getitem__(self, index: slice, /) -> _NestedSequence[_T_co]: ...

_DualArrayLike = Union[
    _SupportsArray[_DType],
    _NestedSequence[_SupportsArray[_DType]],
    _T,
    _NestedSequence[_T],
]


_ArrayLikeNumber_co = _DualArrayLike[
    "dtype[Union[bool_, number[Any]]]",
    Union[bool, int, float, complex],
]

I'd expect the fourth element in Union (_NestedSequence[Union[bool, int, float, complex]]) to match with list[float]. The error message also cuts off early and --verbose doesn't give fuller message so unsure why it failed with _NestedSequence[Union[bool, int, float, complex]].

hmc-cs-mdrissi avatar Oct 02 '24 05:10 hmc-cs-mdrissi

I'm not able to repro the problem. Which version of numpy do you have installed? Can you confirm that you can repro the issue with a clean install, a clean project, and the above code sample?

erictraut avatar Oct 02 '24 06:10 erictraut

I have numpy==1.24.4 installed. Creating a new empty environment and installing that version + latest pyright that code sample reproduces it.

Installing latest numpy, the error does go away. Sorry for not realizing numpy versioned mattered and mentioning it.

hmc-cs-mdrissi avatar Oct 02 '24 06:10 hmc-cs-mdrissi

We might be seeing a related problem:

import numpy as np
import numpy.typing as npt

def foo(x: npt.NDArray[np.float32], y: list[list[float]]) -> npt.NDArray[np.float32]:
    return x * y


def foo2(x: npt.NDArray[np.float32], y: list[tuple[float]]) -> npt.NDArray[np.float32]:
    return x * y

This typechecks with PyRight 382 but not 383:

test.py:11:12 - error: Operator "*" not supported for types "NDArray[float32]" and "list[list[float]]" (reportOperatorIssue)
test:15:12 - error: Operator "*" not supported for types "NDArray[float32]" and "list[tuple[float]]" (reportOperatorIssue)

This reproduces for numpy from 1.23.3 to 1.26.0. We can't upgrade to 2.x yet.

xixixao avatar Oct 02 '24 09:10 xixixao

This is addressed in pyright 1.1.384

erictraut avatar Oct 09 '24 02:10 erictraut