diff options
Diffstat (limited to 'compiler/semtypinst.nim')
-rw-r--r-- | compiler/semtypinst.nim | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 914b92fc8..3ac145eb8 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -90,6 +90,7 @@ type allowMetaTypes*: bool # allow types such as seq[Number] # i.e. the result contains unresolved generics skipTypedesc*: bool # wether we should skip typeDescs + recursionLimit: int proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym @@ -233,7 +234,9 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = # XXX: relying on allowMetaTypes is a kludge result = copyType(t, t.owner, cl.allowMetaTypes) result.flags.incl tfFromGeneric - result.flags.excl tfInstClearedFlags + if not (t.kind in tyMetaTypes or + (t.kind == tyStatic and t.n == nil)): + result.flags.excl tfInstClearedFlags proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvocation[A, tyGenericInvocation[A, B]] @@ -363,6 +366,19 @@ proc propagateFieldFlags(t: PType, n: PNode) = else: discard proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = + template bailout = + if cl.recursionLimit > 100: + # bail out, see bug #2509. But note this caching is in general wrong, + # look at this example where TwoVectors should not share the generic + # instantiations (bug #3112): + + # type + # Vector[N: static[int]] = array[N, float64] + # TwoVectors[Na, Nb: static[int]] = (Vector[Na], Vector[Nb]) + result = PType(idTableGet(cl.localCache, t)) + if result != nil: return result + inc cl.recursionLimit + result = t if t == nil: return @@ -418,8 +434,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = t of tyGenericInst: - result = PType(idTableGet(cl.localCache, t)) - if result != nil: return result + bailout() result = instCopyType(cl, t) idTablePut(cl.localCache, t, result) for i in 1 .. <result.sonsLen: @@ -429,8 +444,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = else: if containsGenericType(t): #if not cl.allowMetaTypes: - result = PType(idTableGet(cl.localCache, t)) - if result != nil: return result + bailout() result = instCopyType(cl, t) result.size = -1 # needs to be recomputed #if not cl.allowMetaTypes: @@ -438,8 +452,14 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = for i in countup(0, sonsLen(result) - 1): if result.sons[i] != nil: - result.sons[i] = replaceTypeVarsT(cl, result.sons[i]) - propagateToOwner(result, result.sons[i]) + var r = replaceTypeVarsT(cl, result.sons[i]) + if result.kind == tyObject: + # carefully coded to not skip the precious tyGenericInst: + let r2 = r.skipTypes({tyGenericInst}) + if r2.kind in {tyPtr, tyRef}: + r = skipTypes(r2, {tyPtr, tyRef}) + result.sons[i] = r + propagateToOwner(result, r) result.n = replaceTypeVarsN(cl, result.n) |