From d90581c677586023756ab26ffb69a64cf67db6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20M=20G=C3=B3mez?= Date: Thu, 15 Jun 2023 08:56:08 +0100 Subject: [PATCH] Allows for arbitrary ordering of inheritance in type section #6259 (#22070) * Allows for arbitrary ordering of inheritance in type section #6259 * prevents ilegal recursion * fixes ilegal recursion. Test passes with a better message * Apply suggestions from code review --------- Co-authored-by: Andreas Rumpf --- compiler/semdata.nim | 1 + compiler/semstmts.nim | 5 +++-- compiler/semtypes.nim | 9 ++++++--- tests/objects/tillegal_recursion.nim | 2 +- tests/types/tinheritref.nim | 4 ++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index e92698916f..bf0f73f80f 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -168,6 +168,7 @@ type sideEffects*: Table[int, seq[(TLineInfo, PSym)]] # symbol.id index inUncheckedAssignSection*: int importModuleLookup*: Table[int, seq[int]] # (module.ident.id, [module.id]) + skipTypes*: seq[PNode] # used to skip types between passes in type section. So far only used for inheritance. template config*(c: PContext): ConfigRef = c.graph.config diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 48b075570b..95820c9397 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1498,7 +1498,9 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = obj.flags.incl sfPure obj.typ = objTy objTy.sym = obj - + for sk in c.skipTypes: + discard semTypeNode(c, sk, nil) + c.skipTypes = @[] proc checkForMetaFields(c: PContext; n: PNode) = proc checkMeta(c: PContext; n: PNode; t: PType) = if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: @@ -1565,7 +1567,6 @@ proc typeSectionFinalPass(c: PContext, n: PNode) = # fix bug #5170, bug #17162, bug #15526: ensure locally scoped types get a unique name: if s.typ.kind in {tyEnum, tyRef, tyObject} and not isTopLevel(c): incl(s.flags, sfGenSym) - #instAllTypeBoundOp(c, n.info) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a9fc980dbf..b342356f80 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -865,14 +865,15 @@ proc skipGenericInvocation(t: PType): PType {.inline.} = result = lastSon(result) proc tryAddInheritedFields(c: PContext, check: var IntSet, pos: var int, - obj: PType, n: PNode, isPartial = false): bool = - if (not isPartial) and (obj.kind notin {tyObject, tyGenericParam} or tfFinal in obj.flags): + obj: PType, n: PNode, isPartial = false, innerObj: PType = nil): bool = + if ((not isPartial) and (obj.kind notin {tyObject, tyGenericParam} or tfFinal in obj.flags)) or + (innerObj != nil and obj.sym.id == innerObj.sym.id): localError(c.config, n.info, "Cannot inherit from: '" & $obj & "'") result = false elif obj.kind == tyObject: result = true if (obj.len > 0) and (obj[0] != nil): - result = result and tryAddInheritedFields(c, check, pos, obj[0].skipGenericInvocation, n) + result = result and tryAddInheritedFields(c, check, pos, obj[0].skipGenericInvocation, n, false, obj) addInheritedFieldsAux(c, check, pos, obj.n) else: result = true @@ -905,6 +906,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType if not tryAddInheritedFields(c, check, pos, concreteBase, n): return newType(tyError, nextTypeId c.idgen, result.owner) + elif concreteBase.kind == tyForward: + c.skipTypes.add n #we retry in the final pass else: if concreteBase.kind != tyError: localError(c.config, n[1].info, "inheritance only works with non-final objects; " & diff --git a/tests/objects/tillegal_recursion.nim b/tests/objects/tillegal_recursion.nim index 2221391016..428c2e445c 100644 --- a/tests/objects/tillegal_recursion.nim +++ b/tests/objects/tillegal_recursion.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "inheritance only works with non-final objects" + errormsg: "Cannot inherit from: 'Foo:ObjectType'" line: 7 """ # bug #1691 diff --git a/tests/types/tinheritref.nim b/tests/types/tinheritref.nim index b799263562..c03e3bcab2 100644 --- a/tests/types/tinheritref.nim +++ b/tests/types/tinheritref.nim @@ -11,10 +11,10 @@ ob = T[int](elem: 23) doAssert ob.elem == 23 type - TTreeIteratorA* {.inheritable.} = ref object - TKeysIteratorA* = ref object of TTreeIteratorA #compiles + TTreeIteratorA* {.inheritable.} = ref object + TTreeIterator* [T,D] {.inheritable.} = ref object TKeysIterator* [T,D] = ref object of TTreeIterator[T,D] #this not