summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-06-08 18:35:37 +0200
committerAraq <rumpf_a@web.de>2017-06-08 18:35:37 +0200
commit4033929127f940a967d0ef522e7e1ecba049b6f1 (patch)
tree3bb7b168ba6767b55f3bf8a373d810e1449eb06a
parent82effc581d956edabed9f0abd68db264b4dcd509 (diff)
downloadNim-4033929127f940a967d0ef522e7e1ecba049b6f1.tar.gz
fixes tproctypecache_falsepositive.nim test case
-rw-r--r--compiler/seminst.nim3
-rw-r--r--compiler/semtypinst.nim5
-rw-r--r--compiler/types.nim6
-rw-r--r--tests/generics/tproctypecache_falsepositive.nim17
4 files changed, 28 insertions, 3 deletions
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index b5dca4c1b..486065563 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -88,7 +88,8 @@ proc sameInstantiation(a, b: TInstantiation): bool =
   if a.concreteTypes.len == b.concreteTypes.len:
     for i in 0..a.concreteTypes.high:
       if not compareTypes(a.concreteTypes[i], b.concreteTypes[i],
-                          flags = {ExactTypeDescValues}): return
+                          flags = {ExactTypeDescValues,
+                                   ExactGcSafety}): return
     result = true
 
 proc genericCacheGet(genericSym: PSym, entry: TInstantiation;
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 80fb9168b..037b07510 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -243,6 +243,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
 proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
   # tyGenericInvocation[A, tyGenericInvocation[A, B]]
   # is difficult to handle:
+  const eqFlags = eqTypeFlags + {tfGcSafe}
   var body = t.sons[0]
   if body.kind != tyGenericBody: internalError(cl.info, "no generic body")
   var header: PType = t
@@ -252,7 +253,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
   else:
     result = searchInstTypes(t)
 
-  if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
+  if result != nil and eqFlags*result.flags == eqFlags*t.flags: return
   for i in countup(1, sonsLen(t) - 1):
     var x = t.sons[i]
     if x.kind in {tyGenericParam}:
@@ -267,7 +268,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
   if header != t:
     # search again after first pass:
     result = searchInstTypes(header)
-    if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
+    if result != nil and eqFlags*result.flags == eqFlags*t.flags: return
   else:
     header = instCopyType(cl, t)
 
diff --git a/compiler/types.nim b/compiler/types.nim
index 2886ac619..13b24ccf8 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -139,6 +139,9 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   add(result, ')')
   if n.sons[0].typ != nil:
     result.add(": " & typeToString(n.sons[0].typ, prefer))
+  result.add "[declared in "
+  result.add($sym.info)
+  result.add "]"
 
 proc elemType*(t: PType): PType =
   assert(t != nil)
@@ -688,6 +691,7 @@ type
     ExactTypeDescValues
     ExactGenericParams
     ExactConstraints
+    ExactGcSafety
     AllowCommonBase
 
   TTypeCmpFlags* = set[TTypeCmpFlag]
@@ -976,6 +980,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     cycleCheck()
     if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
     result = sameChildrenAux(a, b, c) and sameFlags(a, b)
+    if result and ExactGcSafety in c.flags:
+      result = a.flags * {tfThread} == b.flags * {tfThread}
     if result and a.kind == tyProc:
       result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
                ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n))
diff --git a/tests/generics/tproctypecache_falsepositive.nim b/tests/generics/tproctypecache_falsepositive.nim
new file mode 100644
index 000000000..4f24a1fc8
--- /dev/null
+++ b/tests/generics/tproctypecache_falsepositive.nim
@@ -0,0 +1,17 @@
+
+import asyncdispatch
+
+type
+  Callback = proc() {.closure, gcsafe.}
+  GameState = ref object
+    playerChangeHandlers: seq[Callback]
+
+#proc dummy() =
+#  var x = newSeq[proc() {.cdecl, gcsafe.}]()
+
+proc newGameState(): GameState =
+  result = GameState(
+    playerChangeHandlers: newSeq[Callback]() # this fails
+  )
+
+#dummy()