summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorJuan M Gómez <info@jmgomez.me>2023-06-15 08:56:08 +0100
committerGitHub <noreply@github.com>2023-06-15 09:56:08 +0200
commitd90581c677586023756ab26ffb69a64cf67db6f3 (patch)
tree738dfd71e4e36b729a9bec721d37b9aa9297bc10 /compiler
parent13b7e4e0e5f6edf573ee725dd52669ac5687cb5b (diff)
downloadNim-d90581c677586023756ab26ffb69a64cf67db6f3.tar.gz
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>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--compiler/semtypes.nim9
3 files changed, 10 insertions, 5 deletions
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index e92698916..bf0f73f80 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 48b075570..95820c939 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 a9fc980db..b342356f8 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; " &