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 <rumpf_a@web.de>
This commit is contained in:
Juan M Gómez
2023-06-15 08:56:08 +01:00
committed by GitHub
parent 13b7e4e0e5
commit d90581c677
5 changed files with 13 additions and 8 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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; " &

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "inheritance only works with non-final objects"
errormsg: "Cannot inherit from: 'Foo:ObjectType'"
line: 7
"""
# bug #1691

View File

@@ -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