summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semcall.nim18
-rw-r--r--tests/errmsgs/tgcsafety.nim30
2 files changed, 46 insertions, 2 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index d8ee6e7a1..c4f13a237 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -124,6 +124,15 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
     else:
       break
 
+proc effectProblem(f, a: PType; result: var string) =
+  if f.kind == tyProc and a.kind == tyProc:
+    if tfThread in f.flags and tfThread notin a.flags:
+      result.add "\n  This expression is not GC-safe. Annotate the " &
+          "proc with {.gcsafe.} to get extended error information."
+    elif tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
+      result.add "\n  This expression can have side effects. Annotate the " &
+          "proc with {.noSideEffect.} to get extended error information."
+
 proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
                             (TPreferedDesc, string) =
   var prefer = preferName
@@ -158,15 +167,20 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
     if err.firstMismatch != 0 and n.len > 2:
       add(candidates, "  first type mismatch at position: " & $err.firstMismatch &
         "\n  required type: ")
+      var wanted, got: PType = nil
       if err.firstMismatch < err.sym.typ.len:
-        candidates.add typeToString(err.sym.typ.sons[err.firstMismatch])
+        wanted = err.sym.typ.sons[err.firstMismatch]
+        candidates.add typeToString(wanted)
       else:
         candidates.add "none"
       if err.firstMismatch < n.len:
         candidates.add "\n  but expression '"
         candidates.add renderTree(n[err.firstMismatch])
         candidates.add "' is of type: "
-        candidates.add typeToString(n[err.firstMismatch].typ)
+        got = n[err.firstMismatch].typ
+        candidates.add typeToString(got)
+      if wanted != nil and got != nil:
+        effectProblem(wanted, got, candidates)
       candidates.add "\n"
     elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
       add(candidates, "for a 'var' type a variable needs to be passed, but '" &
diff --git a/tests/errmsgs/tgcsafety.nim b/tests/errmsgs/tgcsafety.nim
new file mode 100644
index 000000000..4d192db90
--- /dev/null
+++ b/tests/errmsgs/tgcsafety.nim
@@ -0,0 +1,30 @@
+discard """
+cmd: "nim check $file"
+errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>"
+nimout: '''
+type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>
+but expected one of:
+proc serve(server: AsyncHttpServer; port: Port;
+          callback: proc (request: Request): Future[void]; address = ""): Future[void]
+  first type mismatch at position: 3
+  required type: proc (request: Request): Future[system.void]{.closure, gcsafe.}
+  but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.}
+  This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information.
+
+expression: serve(server, Port(7898), cb)
+'''
+"""
+
+# bug #6186
+
+import asyncdispatch, asynchttpserver
+
+var server = newAsyncHttpServer()
+
+var foo = "foo"
+proc cb(req: Request) {.async.} =
+  var baa = foo & "asds"
+  await req.respond(Http200, baa)
+
+asyncCheck server.serve(Port(7898), cb )
+runForever()