parent
e9a3ffbc3d
commit
03172bef6f
4 changed files with 42 additions and 7 deletions
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
# This module does the instantiation of generic types.
|
# This module does the instantiation of generic types.
|
||||||
|
|
||||||
import ast, astalgo, msgs, types, magicsys, semdata, renderer
|
import ast, astalgo, msgs, types, magicsys, semdata, renderer, options
|
||||||
|
|
||||||
const
|
const
|
||||||
tfInstClearedFlags = {tfHasMeta, tfUnresolved}
|
tfInstClearedFlags = {tfHasMeta, tfUnresolved}
|
||||||
|
|
@ -50,6 +50,9 @@ proc searchInstTypes*(key: PType): PType =
|
||||||
# types such as Channel[empty]. Why?
|
# types such as Channel[empty]. Why?
|
||||||
# See the notes for PActor in handleGenericInvocation
|
# See the notes for PActor in handleGenericInvocation
|
||||||
return
|
return
|
||||||
|
if not sameFlags(inst, key):
|
||||||
|
continue
|
||||||
|
|
||||||
block matchType:
|
block matchType:
|
||||||
for j in 1 .. high(key.sons):
|
for j in 1 .. high(key.sons):
|
||||||
# XXX sameType is not really correct for nested generics?
|
# XXX sameType is not really correct for nested generics?
|
||||||
|
|
@ -247,10 +250,11 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = PType(idTableGet(cl.localCache, t))
|
result = PType(idTableGet(cl.localCache, t))
|
||||||
else:
|
else:
|
||||||
result = searchInstTypes(t)
|
result = searchInstTypes(t)
|
||||||
|
|
||||||
if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
|
if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
|
||||||
for i in countup(1, sonsLen(t) - 1):
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
var x = t.sons[i]
|
var x = t.sons[i]
|
||||||
if x.kind == tyGenericParam:
|
if x.kind in {tyGenericParam}:
|
||||||
x = lookupTypeVar(cl, x)
|
x = lookupTypeVar(cl, x)
|
||||||
if x != nil:
|
if x != nil:
|
||||||
if header == t: header = instCopyType(cl, t)
|
if header == t: header = instCopyType(cl, t)
|
||||||
|
|
|
||||||
|
|
@ -1422,9 +1422,10 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
internalAssert a.sons != nil and a.sons.len > 0
|
internalAssert a.sons != nil and a.sons.len > 0
|
||||||
c.typedescMatched = true
|
c.typedescMatched = true
|
||||||
var aa = a
|
var aa = a
|
||||||
while aa.kind in {tyTypeDesc, tyGenericParam} and
|
while aa.kind in {tyTypeDesc, tyGenericParam} and aa.len > 0:
|
||||||
aa.len > 0:
|
|
||||||
aa = lastSon(aa)
|
aa = lastSon(aa)
|
||||||
|
if aa.kind == tyGenericParam:
|
||||||
|
return isGeneric
|
||||||
result = typeRel(c, f.base, aa)
|
result = typeRel(c, f.base, aa)
|
||||||
if result > isGeneric: result = isGeneric
|
if result > isGeneric: result = isGeneric
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -886,6 +886,9 @@ proc isGenericAlias*(t: PType): bool =
|
||||||
proc skipGenericAlias*(t: PType): PType =
|
proc skipGenericAlias*(t: PType): PType =
|
||||||
return if t.isGenericAlias: t.lastSon else: t
|
return if t.isGenericAlias: t.lastSon else: t
|
||||||
|
|
||||||
|
proc sameFlags*(a, b: PType): bool {.inline.} =
|
||||||
|
result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
|
||||||
|
|
||||||
proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
template cycleCheck() =
|
template cycleCheck() =
|
||||||
# believe it or not, the direct check for ``containsOrIncl(c, a, b)``
|
# believe it or not, the direct check for ``containsOrIncl(c, a, b)``
|
||||||
|
|
@ -898,9 +901,6 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
else:
|
else:
|
||||||
if containsOrIncl(c, a, b): return true
|
if containsOrIncl(c, a, b): return true
|
||||||
|
|
||||||
proc sameFlags(a, b: PType): bool {.inline.} =
|
|
||||||
result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
|
|
||||||
|
|
||||||
if x == y: return true
|
if x == y: return true
|
||||||
var a = skipTypes(x, {tyGenericInst, tyAlias})
|
var a = skipTypes(x, {tyGenericInst, tyAlias})
|
||||||
var b = skipTypes(y, {tyGenericInst, tyAlias})
|
var b = skipTypes(y, {tyGenericInst, tyAlias})
|
||||||
|
|
|
||||||
30
tests/generics/t5643.nim
Normal file
30
tests/generics/t5643.nim
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
type
|
||||||
|
Matrix*[M, N: static[int], T: SomeReal] = object
|
||||||
|
data: ref array[N * M, T]
|
||||||
|
|
||||||
|
Matrix64*[M, N: static[int]] = Matrix[M, N, float64]
|
||||||
|
|
||||||
|
proc zeros64(M,N: static[int]): Matrix64[M,N] =
|
||||||
|
new result.data
|
||||||
|
for i in 0 .. < (M * N):
|
||||||
|
result.data[i] = 0'f64
|
||||||
|
|
||||||
|
proc bar*[M,N: static[int], T](a: Matrix[M,N,T], b: Matrix[M,N,T]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
let a = zeros64(2,2)
|
||||||
|
bar(a,a)
|
||||||
|
# https://github.com/nim-lang/Nim/issues/5643
|
||||||
|
#
|
||||||
|
# The test case was failing here, because the compiler failed to
|
||||||
|
# detect the two matrix instantiations as the same type.
|
||||||
|
#
|
||||||
|
# The root cause was that the `T` type variable is a different
|
||||||
|
# type after the first Matrix type has been matched.
|
||||||
|
#
|
||||||
|
# Sigmatch was failing to match the second version of `T`, but
|
||||||
|
# due to some complex interplay between tyOr, tyTypeDesc and
|
||||||
|
# tyGenericParam this was allowed to went through. The generic
|
||||||
|
# instantiation of the second matrix was incomplete and the
|
||||||
|
# generic cache lookup failed, producing two separate types.
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue