Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1425,13 +1425,17 @@ 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)
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})
Expand All @@ -1442,6 +1446,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
Expand All @@ -1452,13 +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):
Expand Down
6 changes: 6 additions & 0 deletions tests/generics/tgenerics_various.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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])

Loading