diff --git a/tensor-shapes/pyrefly-numpy-stubs/numpy-stubs/__init__.pyi b/tensor-shapes/pyrefly-numpy-stubs/numpy-stubs/__init__.pyi index 7cf497070f..38a202930b 100644 --- a/tensor-shapes/pyrefly-numpy-stubs/numpy-stubs/__init__.pyi +++ b/tensor-shapes/pyrefly-numpy-stubs/numpy-stubs/__init__.pyi @@ -510,7 +510,35 @@ class bool_(generic): class float16(floating): ... class float32(floating): ... -class float64(floating): ... + +class float64(floating): + # Narrow builtin-float support without inheriting float (which + # rewrites reflected ops like ``1j * float64`` via complex*float). + @overload + def __sub__(self, other: float, /) -> float64: ... + @overload + def __sub__(self, other: _NumberScalar, /) -> number: ... + @overload + def __rsub__(self, other: float, /) -> float64: ... + @overload + def __rsub__(self, other: _NumberScalar, /) -> number | complex: ... + @overload + def __gt__(self, other: float, /) -> bool_: ... + @overload + def __gt__(self, other: _NumberScalar, /) -> bool_: ... + @overload + def __ge__(self, other: float, /) -> bool_: ... + @overload + def __ge__(self, other: _NumberScalar, /) -> bool_: ... + @overload + def __lt__(self, other: float, /) -> bool_: ... + @overload + def __lt__(self, other: _NumberScalar, /) -> bool_: ... + @overload + def __le__(self, other: float, /) -> bool_: ... + @overload + def __le__(self, other: _NumberScalar, /) -> bool_: ... + class longdouble(floating): ... class complex64(complexfloating): ... class complex128(complexfloating): ... diff --git a/tensor-shapes/pyrefly-numpy-stubs/test/test_dtype_properties.py b/tensor-shapes/pyrefly-numpy-stubs/test/test_dtype_properties.py index 8a6ad3710e..1a80cb1b4e 100644 --- a/tensor-shapes/pyrefly-numpy-stubs/test/test_dtype_properties.py +++ b/tensor-shapes/pyrefly-numpy-stubs/test/test_dtype_properties.py @@ -107,6 +107,23 @@ def test_numeric_scalar_operations() -> None: np.float64(1j) # E: not assignable +def test_float64_operations_with_builtin_float() -> None: + real = np.float64(2.0) + builtin_float = 1.0 + + # Ops only — do not inherit builtins.float (breaks 1j * float64 typing). + assert_type(real - builtin_float, np.float64) + assert_type(builtin_float - real, np.float64) + assert_type(real > builtin_float, np.bool_) + assert_type(builtin_float > real, np.bool_) + assert_shape((real - builtin_float).shape, ()) + assert_shape((builtin_float - real).shape, ()) + assert real - builtin_float == 1.0 + assert builtin_float - real == -1.0 + assert real > builtin_float + assert not builtin_float > real + + def test_integer_scalar_array_index() -> None: index = np.ones((), dtype=np.int64) assert_shape(index.shape, ())