Fixes #20348; only respect the recursion limit if the symbol's generic type has been generated by the compiler (#20377)
Fixes #20348
This commit is contained in:
parent
db8a62d480
commit
be4bd8a0ed
4 changed files with 145 additions and 12 deletions
|
|
@ -232,7 +232,7 @@ type
|
||||||
TNodeKinds* = set[TNodeKind]
|
TNodeKinds* = set[TNodeKind]
|
||||||
|
|
||||||
type
|
type
|
||||||
TSymFlag* = enum # 48 flags!
|
TSymFlag* = enum # 49 flags!
|
||||||
sfUsed, # read access of sym (for warnings) or simply used
|
sfUsed, # read access of sym (for warnings) or simply used
|
||||||
sfExported, # symbol is exported from module
|
sfExported, # symbol is exported from module
|
||||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||||
|
|
@ -304,6 +304,12 @@ type
|
||||||
sfSingleUsedTemp # For temporaries that we know will only be used once
|
sfSingleUsedTemp # For temporaries that we know will only be used once
|
||||||
sfNoalias # 'noalias' annotation, means C's 'restrict'
|
sfNoalias # 'noalias' annotation, means C's 'restrict'
|
||||||
sfEffectsDelayed # an 'effectsDelayed' parameter
|
sfEffectsDelayed # an 'effectsDelayed' parameter
|
||||||
|
sfGeneratedType # A anonymous generic type that is generated by the compiler for
|
||||||
|
# objects that do not have generic parameters in case one of the
|
||||||
|
# object fields has one.
|
||||||
|
#
|
||||||
|
# This is disallowed but can cause the typechecking to go into
|
||||||
|
# an infinite loop, this flag is used as a sentinel to stop it.
|
||||||
|
|
||||||
TSymFlags* = set[TSymFlag]
|
TSymFlags* = set[TSymFlag]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1425,6 +1425,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||||
excl(objTy.flags, tfFinal)
|
excl(objTy.flags, tfFinal)
|
||||||
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
||||||
nextSymId c.idgen, getCurrOwner(c), s.info)
|
nextSymId c.idgen, getCurrOwner(c), s.info)
|
||||||
|
obj.flags.incl sfGeneratedType
|
||||||
let symNode = newSymNode(obj)
|
let symNode = newSymNode(obj)
|
||||||
obj.ast = a.shallowCopy
|
obj.ast = a.shallowCopy
|
||||||
case a[0].kind
|
case a[0].kind
|
||||||
|
|
|
||||||
|
|
@ -499,17 +499,20 @@ proc propagateFieldFlags(t: PType, n: PNode) =
|
||||||
|
|
||||||
proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
template bailout =
|
template bailout =
|
||||||
if cl.recursionLimit > 100:
|
if t.sym != nil and sfGeneratedType in t.sym.flags:
|
||||||
# bail out, see bug #2509. But note this caching is in general wrong,
|
# Only consider the recursion limit if the symbol is a type with generic
|
||||||
# look at this example where TwoVectors should not share the generic
|
# parameters that have not been explicitly supplied, typechecking should
|
||||||
# instantiations (bug #3112):
|
# terminate when generic parameters are explicitly supplied.
|
||||||
|
if cl.recursionLimit > 100:
|
||||||
# type
|
# bail out, see bug #2509. But note this caching is in general wrong,
|
||||||
# Vector[N: static[int]] = array[N, float64]
|
# look at this example where TwoVectors should not share the generic
|
||||||
# TwoVectors[Na, Nb: static[int]] = (Vector[Na], Vector[Nb])
|
# instantiations (bug #3112):
|
||||||
result = PType(idTableGet(cl.localCache, t))
|
# type
|
||||||
if result != nil: return result
|
# Vector[N: static[int]] = array[N, float64]
|
||||||
inc cl.recursionLimit
|
# 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
|
result = t
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
|
|
|
||||||
123
tests/generics/tgeneric_recursionlimit.nim
Normal file
123
tests/generics/tgeneric_recursionlimit.nim
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
discard """
|
||||||
|
action: "compile"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/20348
|
||||||
|
|
||||||
|
type
|
||||||
|
Payload[T] = object
|
||||||
|
payload: T
|
||||||
|
Carrier[T] = object
|
||||||
|
val: T
|
||||||
|
|
||||||
|
type
|
||||||
|
Payload0*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload1*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload2*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload3*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload4*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload5*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload6*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload7*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload8*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload9*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload10*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload11*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload12*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload13*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload14*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload15*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload16*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload17*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload18*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload19*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload20*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload21*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload22*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload23*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload24*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload25*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload26*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload27*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload28*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload29*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload30*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload31*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload32*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
Payload33*[T] = object
|
||||||
|
payload: Payload[T]
|
||||||
|
|
||||||
|
type
|
||||||
|
Carriers*[T] = object
|
||||||
|
c0*: Carrier[Payload0[T]]
|
||||||
|
c1*: Carrier[Payload1[T]]
|
||||||
|
c2*: Carrier[Payload2[T]]
|
||||||
|
c3*: Carrier[Payload3[T]]
|
||||||
|
c4*: Carrier[Payload4[T]]
|
||||||
|
c5*: Carrier[Payload5[T]]
|
||||||
|
c6*: Carrier[Payload6[T]]
|
||||||
|
c7*: Carrier[Payload7[T]]
|
||||||
|
c8*: Carrier[Payload8[T]]
|
||||||
|
c9*: Carrier[Payload9[T]]
|
||||||
|
c10*: Carrier[Payload10[T]]
|
||||||
|
c11*: Carrier[Payload11[T]]
|
||||||
|
c12*: Carrier[Payload12[T]]
|
||||||
|
c13*: Carrier[Payload13[T]]
|
||||||
|
c14*: Carrier[Payload14[T]]
|
||||||
|
c15*: Carrier[Payload15[T]]
|
||||||
|
c16*: Carrier[Payload16[T]]
|
||||||
|
c17*: Carrier[Payload17[T]]
|
||||||
|
c18*: Carrier[Payload18[T]]
|
||||||
|
c19*: Carrier[Payload19[T]]
|
||||||
|
c20*: Carrier[Payload20[T]]
|
||||||
|
c21*: Carrier[Payload21[T]]
|
||||||
|
c22*: Carrier[Payload22[T]]
|
||||||
|
c23*: Carrier[Payload23[T]]
|
||||||
|
c24*: Carrier[Payload24[T]]
|
||||||
|
c25*: Carrier[Payload25[T]]
|
||||||
|
c26*: Carrier[Payload26[T]]
|
||||||
|
c27*: Carrier[Payload27[T]]
|
||||||
|
c28*: Carrier[Payload28[T]]
|
||||||
|
c29*: Carrier[Payload29[T]]
|
||||||
|
c30*: Carrier[Payload30[T]]
|
||||||
|
c31*: Carrier[Payload31[T]]
|
||||||
|
c32*: Carrier[Payload32[T]]
|
||||||
|
c33*: Carrier[Payload33[T]]
|
||||||
|
|
||||||
|
var carriers : Carriers[int]
|
||||||
|
|
||||||
|
static:
|
||||||
|
assert $(typeof(carriers.c33.val)) == "Payload33[system.int]"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue