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
This commit is contained in:
Parashurama
2017-06-07 08:52:50 +02:00
committed by Andreas Rumpf
parent 210955c3b6
commit bbf9ef606d
2 changed files with 29 additions and 1 deletions

View File

@@ -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]))

23
tests/misc/tcast.nim Normal file
View File

@@ -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))