mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-09 13:18:11 +00:00
* 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:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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; " &
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "inheritance only works with non-final objects"
|
||||
errormsg: "Cannot inherit from: 'Foo:ObjectType'"
|
||||
line: 7
|
||||
"""
|
||||
# bug #1691
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user