summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJuan M Gómez <info@jmgomez.me>2023-09-01 12:42:47 +0100
committerGitHub <noreply@github.com>2023-09-01 13:42:47 +0200
commit0c6e13806d0abfad30b8a4bd9f1fe7858ff2125a (patch)
tree252de32fedf2cd3c0f27171eafe2fc90bc97ec74
parentf1789cc465bcabc7afe0fe991df615246cfadb3b (diff)
downloadNim-0c6e13806d0abfad30b8a4bd9f1fe7858ff2125a.tar.gz
fixes internal error: no generic body fixes #1500 (#22580)
* fixes internal error: no generic body fixes #1500

* adds guard

* adds guard

* removes unnecessary test

* refactor: extracts containsGenericInvocationWithForward
-rw-r--r--compiler/semdata.nim2
-rw-r--r--compiler/semtypes.nim10
-rw-r--r--tests/generics/t1500.nim8
3 files changed, 19 insertions, 1 deletions
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index db3b8370e..00559a5b6 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -168,7 +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 and sets.
+    skipTypes*: seq[PNode] # used to skip types between passes in type section. So far only used for inheritance, sets and generic bodies.
   TBorrowState* = enum
     bsNone, bsReturnNotMatch, bsNoDistinct, bsGeneric, bsNotSupported, bsMatch
 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index b469c69fb..282bc53fe 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1508,6 +1508,14 @@ proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): b
   var newf = newNodeI(nkRecList, n.info)
   semRecordNodeAux(c, t.n, check, pos, newf, t)
 
+proc containsGenericInvocationWithForward(n: PNode): bool = 
+  if n.kind == nkSym and n.sym.ast != nil and n.sym.ast.len > 1 and n.sym.ast[2].kind == nkObjectTy:
+    for p in n.sym.ast[2][^1]:
+      if p.kind == nkIdentDefs and p[1].typ != nil and p[1].typ.kind == tyGenericInvocation and
+        p[1][0].kind == nkSym and p[1][0].typ.kind == tyForward:
+          return true
+  return false
+
 proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
   if s.typ == nil:
     localError(c.config, n.info, "cannot instantiate the '$1' $2" %
@@ -1577,6 +1585,8 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
         # XXX: What kind of error is this? is it still relevant?
         localError(c.config, n.info, errCannotInstantiateX % s.name.s)
         result = newOrPrevType(tyError, prev, c)
+      elif containsGenericInvocationWithForward(n[0]):
+        c.skipTypes.add n #fixes 1500
       else:
         result = instGenericContainer(c, n.info, result,
                                       allowMetaTypes = false)
diff --git a/tests/generics/t1500.nim b/tests/generics/t1500.nim
new file mode 100644
index 000000000..6dd457d33
--- /dev/null
+++ b/tests/generics/t1500.nim
@@ -0,0 +1,8 @@
+#issue 1500
+
+type
+  TFtpBase*[SockType] = object
+    job: TFTPJob[SockType]
+  PFtpBase*[SockType] = ref TFtpBase[SockType]
+  TFtpClient* = TFtpBase[string]
+  TFTPJob[T] = object
\ No newline at end of file