summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorParashurama <Rhagdamaziel@ymail.com>2017-06-07 08:52:50 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-06-07 08:52:50 +0200
commitbbf9ef606d08a6ae91fdf1efccd6f37aadc41237 (patch)
tree7a5721bd93d3b4c71a079a3810e06bd5c89cf867
parent210955c3b6bfbb1d27c426f78cd9315bab2dd0ec (diff)
downloadNim-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.nim7
-rw-r--r--tests/misc/tcast.nim23
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))