diff options
-rw-r--r-- | compiler/semcall.nim | 18 | ||||
-rw-r--r-- | tests/errmsgs/tgcsafety.nim | 30 |
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() |