diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2022-08-24 01:58:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-23 19:58:50 +0200 |
commit | a895bbf714894b059361d0c63a0e46e54eb22da3 (patch) | |
tree | f47c2c1a56b1fc0fe22ad169a42397767e7357a1 /compiler | |
parent | f6eb1d4d7d09eee1c366eff44437034e12bbb099 (diff) | |
download | Nim-a895bbf714894b059361d0c63a0e46e54eb22da3.tar.gz |
fixes #18983 #5282 #13008; recursive types casue infinite type (#20172)
* fixes #18983 #5282 #13008; recursive types casue infinite type * re * add testcases
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semtypes.nim | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 584da1305..3fa449334 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -212,10 +212,34 @@ proc semVarOutType(c: PContext, n: PNode, prev: PType; kind: TTypeKind): PType = else: result = newConstraint(c, kind) +proc isRecursiveType(t: PType, cycleDetector: var IntSet): bool = + if t == nil: + return false + if cycleDetector.containsOrIncl(t.id): + return true + case t.kind + of tyAlias, tyGenericInst, tyDistinct: + return isRecursiveType(t.lastSon, cycleDetector) + else: + return false + +proc isRecursiveType*(t: PType): bool = + # handle simple recusive types before typeFinalPass + var cycleDetector = initIntSet() + isRecursiveType(t, cycleDetector) + +proc addSonSkipIntLitChecked(c: PContext; father, son: PType; it: PNode, id: IdGenerator) = + let s = son.skipIntLit(id) + father.sons.add(s) + if isRecursiveType(s): + localError(c.config, it.info, "illegal recursion in type '" & typeToString(s) & "'") + else: + propagateToOwner(father, s) + proc semDistinct(c: PContext, n: PNode, prev: PType): PType = if n.len == 0: return newConstraint(c, tyDistinct) result = newOrPrevType(tyDistinct, prev, c) - addSonSkipIntLit(result, semTypeNode(c, n[0], nil), c.idgen) + addSonSkipIntLitChecked(c, result, semTypeNode(c, n[0], nil), n[0], c.idgen) if n.len > 1: result.n = n[1] proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = @@ -447,7 +471,8 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = localError(c.config, n.info, errTypeExpected) result = newOrPrevType(tyTuple, prev, c) for it in n: - addSonSkipIntLit(result, semTypeNode(c, it, nil), c.idgen) + let t = semTypeNode(c, it, nil) + addSonSkipIntLitChecked(c, result, t, it, c.idgen) proc semTuple(c: PContext, n: PNode, prev: PType): PType = var typ: PType |