Skip to content

BUG: make void scalar ellipsis indexing consistent - #32744

Merged
ikrommyd merged 3 commits into
numpy:mainfrom
ikrommyd:fix-void-scalar-indexing
Sep 22, 2026
Merged

ikrommyd merged 3 commits into
numpy:mainfrom
ikrommyd:fix-void-scalar-indexing

Conversation

@ikrommyd

@ikrommyd ikrommyd commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

PR summary

Closes #32742.

voidtype_subscript had special casing only for the single ellipsis before running every other index through PyArray_Return which made v[...,] get demoted back to np.void while v[...] returned a 0d array.
We scope PyArray_Return to field selection so that every other index behaves as it does on the equivalent 0d array.
This felt more natural as other scalar types have no special casing and let array_subscript decide the return type.
If you'd rather have another if statement for the 1-element ellipsis tuple, let me know.

Of course this has implications on np.record which just forwards indexing to np.void so the following

In [1]: r = np.rec.array([(1, 2.0)], dtype=[('x', 'i4'), ('y', 'f8')])[0]

In [2]: r
Out[2]: np.record((1, 2.0), dtype=[('x', '<i4'), ('y', '<f8')])

In [3]: r[...]
Out[3]: array((1, 2.), dtype=(numpy.record, [('x', '<i4'), ('y', '<f8')]))

In [4]: r[...,]
Out[4]: np.record((1, 2.0), dtype=[('x', '<i4'), ('y', '<f8')])

returns an array in both cases on the PR branch. But this is what it should do IMO.

If there is a reason to have the 1-element ellipsis tuple behave differently, we can just close this and the issue.

AI Disclosure

AI wrote the test cause I was lazy

Comment thread numpy/_core/src/multiarray/mapping.h Resolved
Comment on lines +3152 to +3154
if (res == NULL) {
return NULL;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a random check I thought I'd add while I'm at it.

@ikrommyd
ikrommyd requested a review from ngoldbaum September 21, 2026 22:21

@ngoldbaum ngoldbaum left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this change causes a concrete regression in astropy:

import numpy as np
from astropy.uncertainty import Distribution

s = Distribution(np.arange(12.).reshape(3, 4))[0]
x = s[...,]
x.pdf_mean()

So, definitely obscure (x = s[...,] is not realistic but maybe someone is doing something like this in a generic function). On numpy main this returns 1.5 but on your PR it's an AttributeError because x is a plain ndarray.

I think the existence of this sort of downstream subclassing might require a FutureWarning? I'm not sure if @mhvk has opinions with an AstroPy hat on.

If it does require a warning cycle, is it really worth the churn to make this change? Sure it improves consistency but we're also not starting NumPy from scratch.

Comment thread numpy/_core/src/multiarray/mapping.h Resolved
Signed-off-by: Iason Krommydas <[email protected]>
@ikrommyd

ikrommyd commented Sep 21, 2026 •

Copy link
Copy Markdown
Member Author

Yikes....I would like this from a consistency perspective as it makes void consistent with every other scalar on that aspect but yeah if people are writing such code that would be annoying so I'd want to hear Marten's opinion too. On the other hand, relying somehow on s[...,] giving you back a scalar while s[...] gives you back an array feels a bit wild to me but sure I understand that we are not dealing with 1000 user packages here.

@mhvk

mhvk commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Let's not worry about astropy in this case. If on main I do the "regular" case,

s = Distribution(np.arange(12.).reshape(3, 4))[0]
s[...]
# array(([(0.,), (1.,), (2.,), (3.,)],),
#       dtype=(astropy.uncertainty.core.ScalarDistribution, [('samples', [('sample', '<f8')], (4,))]))

I get an array instead of a Distribution back, so that means astropy has a bug there already. I think I'll just have to remove that special scalar type; it was basically to help with array printing only...

Anyway, I think this PR is a good idea and, given the above, the fact that this PR makes s[...,] also be wrong does not worry me.

@charris

charris commented Sep 22, 2026

Copy link
Copy Markdown
Member

feels a bit wild to me

It's a typo risk for sure.

@ngoldbaum ngoldbaum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with the nitpick on the release note. Feel free to merge yourself, I think given what Marten and Chuck said this is OK to change without a deprecation.

Signed-off-by: Iason Krommydas <[email protected]>
@ikrommyd

Copy link
Copy Markdown
Member Author

Thanks for the reviews! Let's try this out. In it goes

@ikrommyd
ikrommyd merged commit 0b6274e into numpy:main Sep 22, 2026
91 checks passed
@jorenham

Copy link
Copy Markdown
Member

Thanks Iason

@ikrommyd
ikrommyd deleted the fix-void-scalar-indexing branch September 22, 2026 15:37
Riaz1729 pushed a commit to Riaz1729/numpy that referenced this pull request Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Indexing a void array scalar with (...,) does not return an ndarray

5 participants