diff options
-rw-r--r-- | compiler/ast.nim | 7 | ||||
-rw-r--r-- | compiler/semtypes.nim | 17 | ||||
-rw-r--r-- | tests/objects/tillegal_recursion.nim | 7 |
3 files changed, 24 insertions, 7 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 39d33bb7c..6bfaad527 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1317,6 +1317,13 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType = result = t while result.kind in kinds: result = lastSon(result) +proc skipTypesOrNil*(t: PType, kinds: TTypeKinds): PType = + ## same as skipTypes but handles 'nil' + result = t + while result != nil and result.kind in kinds: + if result.len == 0: return nil + result = lastSon(result) + proc isGCedMem*(t: PType): bool {.inline.} = result = t.kind in {tyString, tyRef, tySequence} or t.kind == tyProc and t.callConv == ccClosure diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 757cfb878..664d54221 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -646,14 +646,17 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = # n.sons[0] contains the pragmas (if any). We process these later... checkSonsLen(n, 3) if n.sons[1].kind != nkEmpty: - base = skipTypes(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs) - var concreteBase = skipGenericInvocation(base).skipTypes(skipPtrs) - if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: - addInheritedFields(c, check, pos, concreteBase) + base = skipTypesOrNil(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs) + if base.isNil: + localError(n.info, errIllegalRecursionInTypeX, "object") else: - if concreteBase.kind != tyError: - localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects) - base = nil + var concreteBase = skipGenericInvocation(base).skipTypes(skipPtrs) + if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: + addInheritedFields(c, check, pos, concreteBase) + else: + if concreteBase.kind != tyError: + localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects) + base = nil if n.kind != nkObjectTy: internalError(n.info, "semObjectNode") result = newOrPrevType(tyObject, prev, c) rawAddSon(result, base) diff --git a/tests/objects/tillegal_recursion.nim b/tests/objects/tillegal_recursion.nim new file mode 100644 index 000000000..171a04f87 --- /dev/null +++ b/tests/objects/tillegal_recursion.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "illegal recursion in type 'object'" + line: 7 +""" +# bug #1691 +type + Foo = ref object of Foo |