Skip to content

Restrict tuple nodeselect methods to integer indices - #174

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas:fix-nodeselect-cartesian
Oct 16, 2026
Merged

ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas:fix-nodeselect-cartesian

Conversation

@ChrisRackauckas

@ChrisRackauckas ChrisRackauckas commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

🚧 UNREVIEWED — awaiting review by @ChrisRackauckas. Filed by an AI agent running as @ChrisRackauckas; Chris has not seen this.
Harness: Claude Code 2.1.300 · Model: claude-opus-5-5
Conversation: https://claude.ai/code/session_01VZjwf7Ux9YtTzwHGHMqnsq

Please ignore this draft until it has been reviewed by @ChrisRackauckas.

Fixes a regression from #172 (merged, unreleased); it should land before the release in #173.

What changed and why

#172 added recursive tuple methods of nodeselect that evaluate i == 1 and i - 1 on any index type. A CartesianIndex first-level index therefore throws MethodError: no method matching -(::CartesianIndex{1}, ::Int64) where it used to return the element. It is reachable through public getindex(m, i, I...) when m.values is empty, e.g. plant[CartesianIndex(2), 1, 1]. Both tuple methods now take i::Integer, so other index types go back to the generic ns[i][I...] method. Both methods need the restriction: restricting only the ::Tuple one makes nodeselect(::Tuple{}, ::Int, ...) ambiguous.

nodeselect(([10, 20], [1.5, 2.5, 3.5]), CartesianIndex(2), 1) returns 1.5 again (as before #172).

Verification

Regression test added to test/tuple_nodes.jl (CartesianIndex first-level index through public getindex on tuple-node structures with empty values, at two depths).

Before (fix stashed, test present, julia +release 1.13.2):

tuple_nodes: Error During Test at test/tuple_nodes.jl:55
  Expression: plant1[CartesianIndex(2), 1, 1] == plant1[2, 1, 1] == 4.1
  MethodError: no method matching -(::CartesianIndex{1}, ::Int64)
tuple_nodes: Error During Test at test/tuple_nodes.jl:56
  Expression: scenario[CartesianIndex(1), 1, 1] === scenario[1, 1, 1]
  MethodError: no method matching -(::CartesianIndex{1}, ::Int64)
Test Summary: | Pass  Error  Total
tuple_nodes   |   21      2     23

After (same file, with the fix), on both 1.13.2 and 1.10.12:

Test Summary: | Pass  Total
tuple_nodes   |   23     23
MultiScaleArrays.nodeselect(([10, 20], [1.5, 2.5, 3.5]), CartesianIndex(2), 1) = 1.5
Test.detect_ambiguities(MultiScaleArrays) = Tuple{Method, Method}[]

The type-stability gain from #172 is kept: the @inferred getindex(community, 4) and @inferred getindex(scenario, 8) lines in test/tuple_nodes.jl pass on 1.13.2 and 1.10.12 (they take an Int index, which still hits the recursive methods).

  • GROUP=Core julia +release --project -e 'using Pkg; Pkg.test()' (1.13.2, JULIA_NUM_THREADS=4): Testing MultiScaleArrays tests passed
  • GROUP=Core julia +lts --project -e 'using Pkg; Pkg.test()' (1.10.12): Testing MultiScaleArrays tests passed
  • GROUP=QA on 1.13.2: passed
  • Runic: no changes. typos: clean.

Not verified: Core 32-bit and pre lanes (left to CI). No docs changes (no public API change).

Risk assessment

  • Risk: low
  • Blast radius: nodeselect (internal) via getindex(m, i, I...) on structures with tuple nodes. Integer indices take the same path as in Make tuple-node getindex type-stable; replace @test_broken @inferred with @inferred #172; non-integer first-level indices take the pre-Make tuple-node getindex type-stable; replace @test_broken @inferred with @inferred #172 generic path. No public API change, no new dependencies.
  • Evidence: regression test fails before / passes after (above); GROUP=Core passes on 1.13.2 and 1.10.12; QA passes; no method ambiguities.
  • Independent review: codex gpt-6.1-sol rated it low, high confidence: narrow dispatch correction restores generic indexing while preserving tested inference on both supported Julia versions. This rating was selected before reading the author's risk assessment. (review run locally; codex-cli 0.162.1 session 01a142db-f871-7e33-9164-14f6b68fc93b, no published URL)
  • Merge: needs human review — fixes an unreleased regression that blocks the release PR; small diff, but it touches indexing.

Independent reviewer's risk assessment (codex-cli 0.162.1 / gpt-6.1-sol, verdict MERGE)

  • Risk: low
  • Blast radius: Internal tuple-node selection reached through public hierarchical getindex. Integer indices retain recursive selection; other index types use the original generic tuple indexing method. No dependencies or public signatures change.
  • Evidence: Reviewed head 4a48db28847e9bac7db6d4bbd2182868fa0c8a89. On Julia 1.13.2 and 1.10.12, the full test/tuple_nodes.jl passed 23/23 assertions, including both deep @inferred checks. Both new CartesianIndex assertions errored with PR 172's methods restored. A 108-case comparison against pre-172 selection produced zero value/exception-type differences on either version. Test.detect_ambiguities(MultiScaleArrays; recursive=false) returned an empty list on both. CI remains pending for several lanes; no failed checks were reported when inspected.
  • Independent review: codex gpt-6.1-sol rated it low, high confidence: narrow dispatch correction restores generic indexing while preserving tested inference on both supported Julia versions. This rating was selected before reading the author's risk assessment.
  • Merge: auto-merge candidate — small, tested regression repair; wait for required CI and the repository's review requirements.

🤖 Posted by an AI agent — harness: Claude Code 2.1.300 · model: claude-opus-5-5
Conversation: https://claude.ai/code/session_01VZjwf7Ux9YtTzwHGHMqnsq

🤖 Generated with Claude Code

The recursive tuple methods of nodeselect compare and decrement the
index, so a CartesianIndex first-level index through getindex(m, i, I...)
on a structure with empty values threw a MethodError. Restricting them to
i::Integer sends other index types to the generic ns[i][I...] method.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Harness: Claude Code 2.1.300
Agent-Model: claude-opus-5-5
Claude-Session: https://claude.ai/code/session_01VZjwf7Ux9YtTzwHGHMqnsq
@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review October 16, 2026 05:00
@ChrisRackauckas
ChrisRackauckas merged commit 8c51d10 into SciML:master Oct 16, 2026
13 checks passed
ChrisRackauckas referenced this pull request Oct 16, 2026
Agent-Harness: Claude Code 2.1.301
Agent-Model: claude-opus-5-5
Claude-Session: https://claude.ai/code/session_01VZjwf7Ux9YtTzwHGHMqnsq

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant