mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-27 01:34:02 +00:00
discardable async procs are now an error (#14176)
* add discard warning in manual
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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) =
|
||||||
|
|||||||
9
tests/async/tdiscardableproc.nim
Normal file
9
tests/async/tdiscardableproc.nim
Normal 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()
|
||||||
@@ -26,5 +26,5 @@ proc hop(): bool =
|
|||||||
|
|
||||||
echo "done"
|
echo "done"
|
||||||
|
|
||||||
const r = hop()
|
const r {.used.} = hop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user