mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
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:
@@ -232,7 +232,7 @@ type
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
TSymFlag* = enum # 48 flags!
|
||||
TSymFlag* = enum # 49 flags!
|
||||
sfUsed, # read access of sym (for warnings) or simply used
|
||||
sfExported, # symbol is exported from module
|
||||
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
|
||||
sfNoalias # 'noalias' annotation, means C's 'restrict'
|
||||
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]
|
||||
|
||||
|
||||
@@ -1425,6 +1425,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
excl(objTy.flags, tfFinal)
|
||||
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
||||
nextSymId c.idgen, getCurrOwner(c), s.info)
|
||||
obj.flags.incl sfGeneratedType
|
||||
let symNode = newSymNode(obj)
|
||||
obj.ast = a.shallowCopy
|
||||
case a[0].kind
|
||||
|
||||
@@ -499,17 +499,20 @@ proc propagateFieldFlags(t: PType, n: PNode) =
|
||||
|
||||
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
|
||||
if t.sym != nil and sfGeneratedType in t.sym.flags:
|
||||
# Only consider the recursion limit if the symbol is a type with generic
|
||||
# parameters that have not been explicitly supplied, typechecking should
|
||||
# terminate when generic parameters are explicitly supplied.
|
||||
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
|
||||
|
||||
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]"
|
||||
Reference in New Issue
Block a user