From 269b4985afbca40dfd13f735ad9d876f87b67de7 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:53:13 +0800 Subject: [PATCH 1/3] fixes #22861; Error: internal error: invalid kind for lastOrd(tyGenericParam) Co-authored-by: Copilot --- compiler/sigmatch.nim | 8 ++++++-- tests/generics/tgenerics_various.nim | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 55fcc43bd9733..f2501feec9b1f 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1425,13 +1425,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, if a.kind == tyArray: var fRange = f.indexType var aRange = a.indexType + var indexRel = isEqual if fRange.kind in {tyGenericParam, tyAnything}: var prev = lookup(c.bindings, fRange) if prev == nil: - if typeRel(c, fRange, aRange) == isNone: + indexRel = typeRel(c, fRange, aRange) + if indexRel == isNone: return isNone put(c, fRange, a.indexType) - fRange = a + fRange = aRange else: fRange = prev let ff = f[1].skipTypes({tyTypeDesc}) @@ -1442,6 +1444,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, result = isGeneric else: result = typeRel(c, ff, aa, flags) + if indexRel == isGeneric and result > isGeneric: + result = isGeneric if result < isGeneric: if nimEnableCovariance and trNoCovariance notin flags and diff --git a/tests/generics/tgenerics_various.nim b/tests/generics/tgenerics_various.nim index 53661236ed017..ce5246a169e0f 100644 --- a/tests/generics/tgenerics_various.nim +++ b/tests/generics/tgenerics_various.nim @@ -252,3 +252,9 @@ block: # issue #9381 var x: GenericObj[int] static: doAssert evalCount == 1 + +block: # bug #22861 + proc fromHex[N](A: type array[N, int]) = discard + proc fromHex (T: typedesc[array[1, int]]) = discard + fromHex(array[1, int]) + From b4efcbdbf6e4f15b81b0d8fe3ca5eea9c51e5633 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:15:12 +0800 Subject: [PATCH 2/3] progress Co-authored-by: Copilot --- compiler/sigmatch.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index f2501feec9b1f..39dc44eb2e032 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1456,6 +1456,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return isNone if fRange.rangeHasUnresolvedStatic: + if trCheckGeneric in flags and aOrig.kind == tyArray and + aOrig.indexType.kind == tyGenericParam: + return isNone if (aRange.kind in {tyGenericParam} and aRange.reduceToBase() == aRange) or (aRange.kind == tyRange and aRange.rangeHasUnresolvedStatic): return @@ -1463,6 +1466,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, elif c.c.matchedConcept != nil and aRange.rangeHasUnresolvedStatic: return inferStaticsInRange(c, aRange, f) elif result == isGeneric and concreteType(c, aa, ff) == nil: + if indexRel != isGeneric: + return isNone + elif trCheckGeneric in flags and aRange.kind == tyGenericParam: return isNone else: if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange): From 33e5bfa424d374dd7a9d4a7c16597a1114a0f5dc Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 29 Apr 2026 19:46:21 +0800 Subject: [PATCH 3/3] adds comments Co-authored-by: Copilot --- compiler/sigmatch.nim | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 39dc44eb2e032..9322f8185b414 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1425,6 +1425,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, if a.kind == tyArray: var fRange = f.indexType var aRange = a.indexType + # Keep index matching separate so array[N, T] stays generic when only the + # index matched through a generic parameter. var indexRel = isEqual if fRange.kind in {tyGenericParam, tyAnything}: var prev = lookup(c.bindings, fRange) @@ -1456,19 +1458,25 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return isNone if fRange.rangeHasUnresolvedStatic: + # During reverse generic checks, a plain generic array index must not be + # treated as specific enough to infer a static range overload. if trCheckGeneric in flags and aOrig.kind == tyArray and aOrig.indexType.kind == tyGenericParam: return isNone if (aRange.kind in {tyGenericParam} and aRange.reduceToBase() == aRange) or (aRange.kind == tyRange and aRange.rangeHasUnresolvedStatic): - return + return isNone return inferStaticsInRange(c, fRange, a) elif c.c.matchedConcept != nil and aRange.rangeHasUnresolvedStatic: return inferStaticsInRange(c, aRange, f) elif result == isGeneric and concreteType(c, aa, ff) == nil: + # If the element type is still unresolved, only keep the match alive + # when the array index already established the generic relationship. if indexRel != isGeneric: return isNone elif trCheckGeneric in flags and aRange.kind == tyGenericParam: + # Reverse generic disambiguation should stop before exact length + # comparison if the actual array index is still generic. return isNone else: if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange):