Skip to content

Commit 18eeafa

Browse files
ringaboutcapocasa
authored andcommitted
fixes nim-lang#19401; fixes nim-lang#19402; rework Forward declaration and finalizer for ORC (nim-lang#20295)
* fixes nim-lang#19401; fixes nim-lang#19402; rework Forward declaration and finalizer for ORC * add more tests * give it a name * make more tests * fixes tests * hidden addr for cpp * move code to a function
1 parent 084fd39 commit 18eeafa

File tree

3 files changed

+112
-24
lines changed

3 files changed

+112
-24
lines changed

compiler/semmagic.nim

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,53 @@ proc semOld(c: PContext; n: PNode): PNode =
449449
localError(c.config, n[1].info, n[1].sym.name.s & " does not belong to " & getCurrOwner(c).name.s)
450450
result = n
451451

452+
proc semNewFinalize(c: PContext; n: PNode): PNode =
453+
# Make sure the finalizer procedure refers to a procedure
454+
if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}:
455+
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
456+
elif optTinyRtti in c.config.globalOptions:
457+
let nfin = skipConvCastAndClosure(n[^1])
458+
let fin = case nfin.kind
459+
of nkSym: nfin.sym
460+
of nkLambda, nkDo: nfin[namePos].sym
461+
else:
462+
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
463+
nil
464+
if fin != nil:
465+
if fin.kind notin {skProc, skFunc}:
466+
# calling convention is checked in codegen
467+
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
468+
469+
# check if we converted this finalizer into a destructor already:
470+
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
471+
if t != nil and getAttachedOp(c.graph, t, attachedDestructor) != nil and
472+
getAttachedOp(c.graph, t, attachedDestructor).owner == fin:
473+
discard "already turned this one into a finalizer"
474+
else:
475+
if sfForward in fin.flags:
476+
let wrapperSym = newSym(skProc, getIdent(c.graph.cache, fin.name.s & "FinalizerWrapper"), nextSymId c.idgen, fin.owner, fin.info)
477+
let selfSymNode = newSymNode(copySym(fin.ast[paramsPos][1][0].sym, nextSymId c.idgen))
478+
wrapperSym.flags.incl sfUsed
479+
let wrapper = c.semExpr(c, newProcNode(nkProcDef, fin.info, body = newTree(nkCall, newSymNode(fin), selfSymNode),
480+
params = nkFormalParams.newTree(c.graph.emptyNode,
481+
newTree(nkIdentDefs, selfSymNode, fin.ast[paramsPos][1][1], c.graph.emptyNode)
482+
),
483+
name = newSymNode(wrapperSym), pattern = c.graph.emptyNode,
484+
genericParams = c.graph.emptyNode, pragmas = c.graph.emptyNode, exceptions = c.graph.emptyNode), {})
485+
var transFormedSym = turnFinalizerIntoDestructor(c, wrapperSym, wrapper.info)
486+
transFormedSym.owner = fin
487+
if c.config.backend == backendCpp or sfCompileToCpp in c.module.flags:
488+
let origParamType = transFormedSym.ast[bodyPos][1].typ
489+
let selfSymbolType = makePtrType(c, origParamType.skipTypes(abstractPtrs))
490+
let selfPtr = newNodeI(nkHiddenAddr, transFormedSym.ast[bodyPos][1].info)
491+
selfPtr.add transFormedSym.ast[bodyPos][1]
492+
selfPtr.typ = selfSymbolType
493+
transFormedSym.ast[bodyPos][1] = c.semExpr(c, selfPtr)
494+
bindTypeHook(c, transFormedSym, n, attachedDestructor)
495+
else:
496+
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
497+
result = n
498+
452499
proc semPrivateAccess(c: PContext, n: PNode): PNode =
453500
let t = n[1].typ[0].toObjectFromRefPtrGeneric
454501
c.currentScope.allowPrivateAccess.add t.sym
@@ -513,30 +560,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
513560
else:
514561
result = plugin(c, n)
515562
of mNewFinalize:
516-
# Make sure the finalizer procedure refers to a procedure
517-
if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}:
518-
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
519-
elif optTinyRtti in c.config.globalOptions:
520-
let nfin = skipConvCastAndClosure(n[^1])
521-
let fin = case nfin.kind
522-
of nkSym: nfin.sym
523-
of nkLambda, nkDo: nfin[namePos].sym
524-
else:
525-
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
526-
nil
527-
if fin != nil:
528-
if fin.kind notin {skProc, skFunc}:
529-
# calling convention is checked in codegen
530-
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
531-
532-
# check if we converted this finalizer into a destructor already:
533-
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
534-
if t != nil and getAttachedOp(c.graph, t, attachedDestructor) != nil and
535-
getAttachedOp(c.graph, t, attachedDestructor).owner == fin:
536-
discard "already turned this one into a finalizer"
537-
else:
538-
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
539-
result = n
563+
result = semNewFinalize(c, n)
540564
of mDestroy:
541565
result = n
542566
let t = n[1].typ.skipTypes(abstractVar)

tests/arc/t19401.nim

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
discard """
2+
output: '''
3+
delete foo
4+
delete foo
5+
delete foo
6+
'''
7+
matrix: "--mm:arc"
8+
"""
9+
10+
type Foo = ref object
11+
data: int
12+
proc delete(self: Foo)
13+
proc newFoo: Foo =
14+
let x = 12
15+
discard x
16+
new(result, delete)
17+
result.data = x
18+
proc delete(self: Foo) =
19+
doAssert self.data == 12
20+
echo("delete foo")
21+
22+
if isMainModule:
23+
proc test() =
24+
let x1 = newFoo()
25+
let x2 = newFoo()
26+
discard x1
27+
discard x2
28+
var x3: Foo
29+
new(x3, delete)
30+
x3.data = 12
31+
discard x3
32+
test()

tests/arc/t19402.nim

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
discard """
2+
output: '''
3+
delete foo
4+
delete foo
5+
delete foo
6+
'''
7+
matrix: "--mm:arc"
8+
"""
9+
10+
type Foo = ref object of RootObj
11+
data: int
12+
proc delete(self: Foo)
13+
proc newFoo: Foo =
14+
let x = 12
15+
discard x
16+
new(result, delete)
17+
result.data = x
18+
proc delete(self: Foo) =
19+
doAssert self.data == 12
20+
echo("delete foo")
21+
22+
if isMainModule:
23+
proc test() =
24+
let x1 = newFoo()
25+
let x2 = newFoo()
26+
discard x1
27+
discard x2
28+
var x3: Foo
29+
new(x3, delete)
30+
x3.data = 12
31+
discard x3
32+
test()

0 commit comments

Comments
 (0)