diff options
author | Parashurama <Rhagdamaziel@ymail.com> | 2017-06-07 08:52:50 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-06-07 08:52:50 +0200 |
commit | bbf9ef606d08a6ae91fdf1efccd6f37aadc41237 (patch) | |
tree | 7a5721bd93d3b4c71a079a3810e06bd5c89cf867 | |
parent | 210955c3b6bfbb1d27c426f78cd9315bab2dd0ec (diff) | |
download | Nim-bbf9ef606d08a6ae91fdf1efccd6f37aadc41237.tar.gz |
restrict casting for closure. (#5948); fixes #5742
* restrict casting for closure. This commit forbid casting a closure to anything other than another closure. use rawEnv/rawProc to access underlaying pointers. * better error message for closure cast * fixes #5742
-rw-r--r-- | compiler/semexprs.nim | 7 | ||||
-rw-r--r-- | tests/misc/tcast.nim | 23 |
2 files changed, 29 insertions, 1 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9c93d54a3..67a718b91 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -152,6 +152,8 @@ proc isCastable(dst, src: PType): bool = result = false elif typeAllowed(dst, skParam) != nil: result = false + elif dst.kind == tyProc and dst.callConv == ccClosure: + result = src.kind == tyProc and src.callConv == ccClosure else: result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or @@ -227,7 +229,10 @@ proc semCast(c: PContext, n: PNode): PNode = if tfHasMeta in targetType.flags: localError(n.sons[0].info, errCastToANonConcreteType, $targetType) if not isCastable(targetType, castedExpr.typ): - localError(n.info, errExprCannotBeCastToX, $targetType) + let tar = $targetType + let alt = typeToString(targetType, preferDesc) + let msg = if tar != alt: tar & "=" & alt else: tar + localError(n.info, errExprCannotBeCastToX, msg) result = newNodeI(nkCast, n.info) result.typ = targetType addSon(result, copyTree(n.sons[0])) diff --git a/tests/misc/tcast.nim b/tests/misc/tcast.nim new file mode 100644 index 000000000..4e27040fb --- /dev/null +++ b/tests/misc/tcast.nim @@ -0,0 +1,23 @@ +discard """ + output: ''' +Hello World +Hello World''' +""" +type MyProc = proc() {.cdecl.} +type MyProc2 = proc() {.nimcall.} +type MyProc3 = proc() #{.closure.} is implicit + +proc testProc() = echo "Hello World" + +proc callPointer(p: pointer) = + # can cast to proc(){.cdecl.} + let ffunc0 = cast[MyProc](p) + # can cast to proc(){.nimcall.} + let ffunc1 = cast[MyProc2](p) + # cannot cast to proc(){.closure.} + doAssert(not compiles(cast[MyProc3](p))) + + ffunc0() + ffunc1() + +callPointer(cast[pointer](testProc)) |