discardable async procs are now an error (#14176)

* add discard warning in manual
This commit is contained in:
hlaaftana
2020-05-01 10:49:13 +03:00
committed by GitHub
parent d5fc35c968
commit 9b01c6cf48
4 changed files with 26 additions and 10 deletions

View File

@@ -2568,7 +2568,8 @@ Example:
discard p(3, 4) # discard the return value of `p` discard p(3, 4) # discard the return value of `p`
The ``discard`` statement evaluates its expression for side-effects and The ``discard`` statement evaluates its expression for side-effects and
throws the expression's resulting value away. throws the expression's resulting value away, and should only be used
when ignoring this value is known not to cause problems.
Ignoring the return value of a procedure without using a discard statement is Ignoring the return value of a procedure without using a discard statement is
a static error. a static error.

View File

@@ -112,7 +112,7 @@ proc getName(node: NimNode): string {.compileTime.} =
of nnkEmpty: of nnkEmpty:
return "anonymous" return "anonymous"
else: else:
error("Unknown name.") error("Unknown name.", node)
proc getFutureVarIdents(params: NimNode): seq[NimNode] {.compileTime.} = proc getFutureVarIdents(params: NimNode): seq[NimNode] {.compileTime.} =
result = @[] result = @[]
@@ -125,10 +125,10 @@ proc getFutureVarIdents(params: NimNode): seq[NimNode] {.compileTime.} =
proc isInvalidReturnType(typeName: string): bool = proc isInvalidReturnType(typeName: string): bool =
return typeName notin ["Future"] #, "FutureStream"] return typeName notin ["Future"] #, "FutureStream"]
proc verifyReturnType(typeName: string) {.compileTime.} = proc verifyReturnType(typeName: string, node: NimNode = nil) {.compileTime.} =
if typeName.isInvalidReturnType: if typeName.isInvalidReturnType:
error("Expected return type of 'Future' got '$1'" % error("Expected return type of 'Future' got '$1'" %
typeName) typeName, node)
proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} = proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
## This macro transforms a single procedure into a closure iterator. ## This macro transforms a single procedure into a closure iterator.
@@ -141,7 +141,13 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
if prc.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}: if prc.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}:
error("Cannot transform this node kind into an async proc." & error("Cannot transform this node kind into an async proc." &
" proc/method definition or lambda node expected.") " proc/method definition or lambda node expected.", prc)
if prc[4].kind != nnkEmpty:
for prag in prc[4]:
if prag.eqIdent("discardable"):
error("Cannot make async proc discardable. Futures have to be " &
"checked with `asyncCheck` instead of discarded", prag)
let prcName = prc.name.getName let prcName = prc.name.getName
@@ -153,16 +159,16 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
# Verify that the return type is a Future[T] # Verify that the return type is a Future[T]
if returnType.kind == nnkBracketExpr: if returnType.kind == nnkBracketExpr:
let fut = repr(returnType[0]) let fut = repr(returnType[0])
verifyReturnType(fut) verifyReturnType(fut, returnType[0])
baseType = returnType[1] baseType = returnType[1]
elif returnType.kind in nnkCallKinds and returnType[0].eqIdent("[]"): elif returnType.kind in nnkCallKinds and returnType[0].eqIdent("[]"):
let fut = repr(returnType[1]) let fut = repr(returnType[1])
verifyReturnType(fut) verifyReturnType(fut, returnType[0])
baseType = returnType[2] baseType = returnType[2]
elif returnType.kind == nnkEmpty: elif returnType.kind == nnkEmpty:
baseType = returnType baseType = returnType
else: else:
verifyReturnType(repr(returnType)) verifyReturnType(repr(returnType), returntype)
let subtypeIsVoid = returnType.kind == nnkEmpty or let subtypeIsVoid = returnType.kind == nnkEmpty or
(baseType.kind == nnkIdent and returnType[1].eqIdent("void")) (baseType.kind == nnkIdent and returnType[1].eqIdent("void"))
@@ -303,7 +309,7 @@ proc stripReturnType(returnType: NimNode): NimNode =
result = returnType result = returnType
if returnType.kind == nnkBracketExpr: if returnType.kind == nnkBracketExpr:
let fut = repr(returnType[0]) let fut = repr(returnType[0])
verifyReturnType(fut) verifyReturnType(fut, returnType)
result = returnType[1] result = returnType[1]
proc splitProc(prc: NimNode): (NimNode, NimNode) = proc splitProc(prc: NimNode): (NimNode, NimNode) =

View File

@@ -0,0 +1,9 @@
discard """
errmsg: "Cannot make async proc discardable. Futures have to be checked with `asyncCheck` instead of discarded"
"""
import async
proc foo {.async, discardable.} = discard
foo()

View File

@@ -26,5 +26,5 @@ proc hop(): bool =
echo "done" echo "done"
const r = hop() const r {.used.} = hop()