8000 Constant slices are deduplicated too aggressively · Issue #126298 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content
Constant slices are deduplicated too aggressively #126298
Closed
@befeleme

Description

@befeleme

Bug report

Bug description:

I try to build numpy with Python 3.14.0a1 and encounter very strange test failures regarding array slicing. The offending tests source code can be found here and here.
I compiled both numpy 1.26.4 and 2.1.2 for Fedora Linux and installed it into an environment with Python 3.14. This happens for both versions of numpy. It doesn't happen with Python 3.13 and numpy 1.26.4.

In both tests, it's either TypeError expected and not raised (test_slicing_no_floats), or the other way around (test_valid_slicing). Let's take a look at test_slicing_no_floats. assert_raises is numpy's wrapper over unittest, but that's irrelevant for the problem - let's replace it with a minimal viable function and run the offending piece of code:

>>> def assert_raises(e, c):
...    try:
...        r = c()
...    except e:
...        pass
...    else:
...        raise AssertionError(f"function call: {c}, did not raise: {e}, return value: {r}")
...
>>> def test_slicing_no_floats():
...    a = np.array([[5]])
...    assert_raises(TypeError, lambda: a[0.0:])
...    assert_raises(TypeError, lambda: a[0:, 0.0:2])
...    assert_raises(TypeError, lambda: a[0.0::2, :0])
...    assert_raises(TypeError, lambda: a[0.0:1:2,:])
...    assert_raises(TypeError, lambda: a[:, 0.0:])
...    assert_raises(TypeError, lambda: a[:0.0])
...
>>> test_slicing_no_floats()
Traceback (most recent call last):
  File "<python-input-45>", line 1, in <module>
    test_slicing_no_floats()
    ~~~~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-44>", line 8, in test_slicing_no_floats
    assert_raises(TypeError, lambda: a[:0.0])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<python-input-34>", line 7, in assert_raises
    raise AssertionError(f"function call: {c}, did not raise: {e}, return code: {r}")
AssertionError: function call: <function test_slicing_no_floats.<locals>.<lambda> at 0x7f9a8a987c10>, did not raise: <class 'TypeError'>, return value: []

What if I switch the 1st and last line of the test? A completely different row stops raising TypeError:

>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[:0.0])
...     assert_raises(TypeError, lambda: a[0:, 0.0:2])
...     assert_raises(TypeError, lambda: a[0.0::2, :0])
...     assert_raises(TypeError, lambda: a[0.0:1:2,:])
...     assert_raises(TypeError, lambda: a[:, 0.0:])
...     assert_raises(TypeError, lambda: a[0.0:])
...     
>>> test_slicing_no_floats()
Traceback (most recent call last):
  File "<python-input-49>", line 1, in <module>
    test_slicing_no_floats()
    ~~~~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-48>", line 7, in test_slicing_no_floats
    assert_raises(TypeError, lambda: a[:, 0.0:])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<python-input-34>", line 7, in assert_raises
    raise AssertionError(f"function call: {c}, did not raise: {e}, return code: {r}")
AssertionError: function call: <function test_slicing_no_floats.<locals>.<lambda> at 0x7f9a8a987740>, did not raise: <class 'TypeError'>, return value: [[5]]

When I arbitrarily remove the 3rd row from the function, suddenly TypeError is correctly raised:

>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[0.0:])
...     assert_raises(TypeError, lambda: a[0:, 0.0:2])
...     assert_raises(TypeError, lambda: a[0.0:1:2,:])
...     assert_raises(TypeError, lambda: a[:, 0.0:])
...     assert_raises(TypeError, lambda: a[:0.0])
...     
>>> test_slicing_no_floats()
>>>

Other modifications are somewhat unpredictable:

>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[:0.0])
...     assert_raises(TypeError, lambda: a[0:, 0.0:2])
...     assert_raises(TypeError, lambda: a[0.0:1:2,:])
...     assert_raises(TypeError, lambda: a[0.0:])
...     
>>> test_slicing_no_floats()
Traceback (most recent call last):
  File "<python-input-51>", line 1, in <module>
    test_slicing_no_floats()
    ~~~~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-50>", line 6, in test_slicing_no_floats
    assert_raises(TypeError, lambda: a[0.0:])
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<python-input-34>", line 7, in assert_raises
    raise AssertionError(f"function call: {c}, did not raise: {e}, return code: {r}")
AssertionError: function call: <function test_slicing_no_floats.<locals>.<lambda> at 0x7f9a8a987950>, did not raise: <class 'TypeError'>, return value: [[5]]
>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[:0.0])
...     assert_raises(TypeError, lambda: a[0.0:1:2,:])
...     assert_raises(TypeError, lambda: a[0.0:])
...     
>>> test_slicing_no_floats()  # no problem
>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[:0.0])
...     assert_raises(TypeError, lambda: a[0.0:1:2,:])
...     
>>> test_slicing_no_floats() # no problem
>>> def test_slicing_no_floats():
...     a = np.array([[5]])
...     assert_raises(TypeError, lambda: a[:0.0])
...     
>>> test_slicing_no_floats() # no problem
>>>

I tried also direct slicing, in all cases TypeError was correctly raised:

>>> a = np.array([[5]])
>>> a[:0.0]
Traceback (most recent call last):
  File "<python-input-18>", line 1, in <module>
    a[:0.0]
    ~^^^^^^
TypeError: slice indices must be integers or None or have an __index__ method

And calling lambdas with the same result:

>>> (lambda: a[0.0::2, :0])()
Traceback (most recent call last):
  File "<python-input-59>", line 1, in <module>
    (lambda: a[0.0::2, :0])()
    ~~~~~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-59>", line 1, in <lambda>
    (lambda: a[0.0::2, :0])()
             ~^^^^^^^^^^^^
TypeError: slice indices must be integers or None or have an __index__ method
The original test failure from our build system

    def test_slicing_no_floats():
        a = np.array([[5]])
    
        # start as float.
        assert_raises(TypeError, lambda: a[0.0:])
        assert_raises(TypeError, lambda: a[0:, 0.0:2])
        assert_raises(TypeError, lambda: a[0.0::2, :0])
        assert_raises(TypeError, lambda: a[0.0:1:2,:])
        assert_raises(TypeError, lambda: a[:, 0.0:])
        # stop as float.
>       assert_raises(TypeError, lambda: a[:0.0])

a          = array([[5]])
self       = <numpy.core.tests.test_indexing.TestIndexing object at 0x7f7e1a3bfd90>

../../../BUILDROOT/usr/lib64/python3.14/site-packages/numpy/core/tests/test_indexing.py:54: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib64/python3.14/unittest/case.py:804: in assertRaises
    return context.handle('assertRaises', args, kwargs)
        args       = (<function TestIndexing.test_slicing_no_floats.<locals>.<lambda> at 0x7f7e081dae50>,)
        context    = None
        expected_exception = <class 'TypeError'>
        kwargs     = {}
        self       = <numpy.testing._private.utils._Dummy testMethod=nop>
/usr/lib64/python3.14/unittest/case.py:237: in handle
    with self:
        args       = []
        callable_obj = <function TestIndexing.test_slicing_no_floats.<locals>.<lambda> at 0x7f7e081dae50>
        kwargs     = {}
        name       = 'assertRaises'
        self       = None
/usr/lib64/python3.14/unittest/case.py:260: in __exit__
    self._raiseFailure("{} not raised by {}".format(exc_name,
        exc_name   = 'TypeError'
        exc_type   = None
        exc_value  = None
        self       = <unittest.case._AssertRaisesContext object at 0x7f7e07ca8dd0>
        tb         = None
        
    # here no TypeError is expected, yet it is raised
    def test_valid_slicing(self):
        # These should raise no errors.
        a = np.array([[[5]]])
    
        a[::]
>       a[0:]
E       TypeError: slice indices must be integers or None or have an __index__ method

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

Labels

3.14bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0