Skip to content

Commit

Permalink
Fixes nim-lang#20348; only respect the recursion limit if the symbol…
Browse files Browse the repository at this point in the history
…'s generic type has been generated by the compiler (nim-lang#20377)

Fixes nim-lang#20348
  • Loading branch information
deech authored Sep 22, 2022
1 parent db8a62d commit be4bd8a
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 12 deletions.
8 changes: 7 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]

Expand Down
1 change: 1 addition & 0 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 14 additions & 11 deletions compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
123 changes: 123 additions & 0 deletions tests/generics/tgeneric_recursionlimit.nim
Original file line number Diff line number Diff line change
@@ -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]"

0 comments on commit be4bd8a

Please sign in to comment.