fix arraymancer regression: gate handleGenericInvocation's copy on Sealed

The early IC fix made the else branch (concrete generic args) copy the
invocation type unconditionally before propagateToOwner. Besides
avoiding the in-place mutation, the copy flips `header != t` for
all-concrete invocations, which activates the searchInstTypes/sameFlags
cached-instance return path that devel skipped - a cached, meta-flagged
instance could be returned where a fresh one was expected.
Arraymancer's build then failed with "cannot cast to a non concrete
type: 'ptr NimSeqV2[Node[Tensor[float32]]]'" in seqs_v2.setLen.

Copy only when the invocation type is actually immutable
(IC-loaded/Sealed); non-IC behavior is devel's again, the IC assert
stays fixed.

Verified: arraymancer tests_cpu.nim builds and links (its test-suite
SIGSEGV in io_npy is pre-existing - a devel-built compiler produces the
identical 226-tests-then-crash). Macro sweep 93/95, tests/ic 5/5,
koch boot -d:release and clean koch bootic reach bit-identical fixed
points.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Araq
2026-06-10 14:53:16 +02:00
parent cc2afc616f
commit b72affa1a1

View File

@@ -446,12 +446,13 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
header[i] = x
propagateToOwner(header, x)
else:
# Honor the same copy-before-mutate invariant as the branch above: never
# mutate the original invocation type `t` in place. Besides being cleaner,
# under IC `t` may be a loaded dep type (Sealed/immutable), and mutating it
# would assert. The flags propagated here end up on `header`, which is what
# is used downstream (`result.flags = header.flags`).
if header == t: header = instCopyType(cl, t)
# Under IC `t` may be a loaded dep type (Sealed/immutable); mutating it
# would assert, so propagate into a copy. For non-Sealed types keep
# devel's in-place propagation: unconditionally copying here changes
# `header != t` and with it the cached-instance lookup below, which
# regressed non-IC generic instantiations (arraymancer: a cached
# NimSeqV2 instance with stale flags was returned for a cast target).
if header == t and t.state == Sealed: header = instCopyType(cl, t)
propagateToOwner(header, x)
if header != t: