diff options
-rw-r--r-- | compiler/astalgo.nim | 4 | ||||
-rw-r--r-- | compiler/semmagic.nim | 26 | ||||
-rw-r--r-- | compiler/sempass2.nim | 4 | ||||
-rw-r--r-- | tests/arc/t14383.nim | 14 |
4 files changed, 36 insertions, 12 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index d9cd5ade1..832f8819a 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -110,14 +110,14 @@ proc iiTablePut*(t: var TIITable, key, val: int) # implementation -proc skipConvAndClosure*(n: PNode): PNode = +proc skipConvCastAndClosure*(n: PNode): PNode = result = n while true: case result.kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64, nkClosure: result = result[0] - of nkHiddenStdConv, nkHiddenSubConv, nkConv: + of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: result = result[1] else: break diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 5e6b4dbe2..3368bcfbf 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -527,14 +527,24 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}: localError(c.config, n.info, "finalizer must be a direct reference to a proc") elif optTinyRtti in c.config.globalOptions: - let fin = if n[^1].kind in {nkLambda, nkDo}: n[^1][namePos].sym - else: n[^1].sym - # check if we converted this finalizer into a destructor already: - let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) - if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin: - discard "already turned this one into a finalizer" - else: - bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) + let nfin = skipConvCastAndClosure(n[^1]) + let fin = case nfin.kind + of nkSym: nfin.sym + of nkLambda, nkDo: nfin[namePos].sym + else: + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + nil + if fin != nil: + if fin.kind notin {skProc, skFunc}: + # calling convention is checked in codegen + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + + # check if we converted this finalizer into a destructor already: + let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) + if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin: + discard "already turned this one into a finalizer" + else: + bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) result = n of mDestroy: result = n diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 92a896a38..39ba1b307 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -510,7 +510,7 @@ proc procVarCheck(n: PNode; conf: ConfigRef) = proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType.isNil or paramType.kind != tyTypeDesc: - procVarCheck skipConvAndClosure(n), tracked.config + procVarCheck skipConvCastAndClosure(n), tracked.config #elif n.kind in nkSymChoices: # echo "came here" let paramType = paramType.skipTypesOrNil(abstractInst) @@ -556,7 +556,7 @@ proc isTrival(caller: PNode): bool {.inline.} = result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved, mSwap} proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, paramType: PType; caller: PNode) = - let a = skipConvAndClosure(n) + let a = skipConvCastAndClosure(n) let op = a.typ # assume indirect calls are taken here: if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and not isTrival(caller): diff --git a/tests/arc/t14383.nim b/tests/arc/t14383.nim index f112a1a6c..834c50def 100644 --- a/tests/arc/t14383.nim +++ b/tests/arc/t14383.nim @@ -34,3 +34,17 @@ echo x import std/os discard getFileInfo(".") + + +#------------------------------------------------------------------------------ +# Issue #15707 +#------------------------------------------------------------------------------ + +type + JVMObject = ref object +proc freeJVMObject(o: JVMObject) = + discard +proc fromJObject(T: typedesc[JVMObject]): T = + result.new(cast[proc(r: T) {.nimcall.}](freeJVMObject)) + +discard JVMObject.fromJObject() \ No newline at end of file |