parent
abea80376a
commit
eadd1ba9ed
3 changed files with 24 additions and 2 deletions
|
|
@ -383,7 +383,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||||
# little hack for injectdestructors.nim (see bug #11350):
|
# little hack for injectdestructors.nim (see bug #11350):
|
||||||
#result[0].typ = nil
|
#result[0].typ = nil
|
||||||
|
|
||||||
proc turnFinalizerIntoDestructor(c: PContext; orig: PSym): PSym =
|
proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym =
|
||||||
# We need to do 2 things: Replace n.typ which is a 'ref T' by a 'var T' type.
|
# We need to do 2 things: Replace n.typ which is a 'ref T' by a 'var T' type.
|
||||||
# Replace nkDerefExpr by nkHiddenDeref
|
# Replace nkDerefExpr by nkHiddenDeref
|
||||||
# nkDeref is for 'ref T': x[].field
|
# nkDeref is for 'ref T': x[].field
|
||||||
|
|
@ -400,7 +400,9 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym): PSym =
|
||||||
# result =
|
# result =
|
||||||
|
|
||||||
result = copySym(orig)
|
result = copySym(orig)
|
||||||
|
result.info = info
|
||||||
result.flags.incl sfFromGeneric
|
result.flags.incl sfFromGeneric
|
||||||
|
result.owner = orig
|
||||||
let origParamType = orig.typ[1]
|
let origParamType = orig.typ[1]
|
||||||
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs))
|
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs))
|
||||||
let oldParam = orig.typ.n[1].sym
|
let oldParam = orig.typ.n[1].sym
|
||||||
|
|
@ -477,7 +479,12 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}:
|
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")
|
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||||
elif optTinyRtti in c.config.globalOptions:
|
elif optTinyRtti in c.config.globalOptions:
|
||||||
bindTypeHook(c, turnFinalizerIntoDestructor(c, n[^1].sym), n, attachedDestructor)
|
# check if we converted this finalizer into a destructor already:
|
||||||
|
let t = whereToBindTypeHook(c, n[^1].sym.typ[1].skipTypes(abstractInst+{tyRef}))
|
||||||
|
if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == n[^1].sym:
|
||||||
|
discard "already turned this one into a finalizer"
|
||||||
|
else:
|
||||||
|
bindTypeHook(c, turnFinalizerIntoDestructor(c, n[^1].sym, n.info), n, attachedDestructor)
|
||||||
result = n
|
result = n
|
||||||
of mDestroy:
|
of mDestroy:
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -1603,6 +1603,15 @@ proc prevDestructor(c: PContext; prevOp: PSym; obj: PType; info: TLineInfo) =
|
||||||
msg.add "; previous declaration was here: " & (c.config $ prevOp.info)
|
msg.add "; previous declaration was here: " & (c.config $ prevOp.info)
|
||||||
localError(c.config, info, errGenerated, msg)
|
localError(c.config, info, errGenerated, msg)
|
||||||
|
|
||||||
|
proc whereToBindTypeHook(c: PContext; t: PType): PType =
|
||||||
|
result = t
|
||||||
|
while true:
|
||||||
|
if result.kind in {tyGenericBody, tyGenericInst}: result = result.lastSon
|
||||||
|
elif result.kind == tyGenericInvocation: result = result[0]
|
||||||
|
else: break
|
||||||
|
if result.kind in {tyObject, tyDistinct, tySequence, tyString}:
|
||||||
|
result = canonType(c, result)
|
||||||
|
|
||||||
proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
|
||||||
let t = s.typ
|
let t = s.typ
|
||||||
var noError = false
|
var noError = false
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: "nim c --gc:arc $file"
|
cmd: "nim c --gc:arc $file"
|
||||||
output: '''Foo(field: "Dick Laurent", k: ka, x: 0.0)
|
output: '''Foo(field: "Dick Laurent", k: ka, x: 0.0)
|
||||||
|
Nobody is dead
|
||||||
Dick Laurent is dead'''
|
Dick Laurent is dead'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -23,3 +24,8 @@ x.field = "Dick Laurent"
|
||||||
# reference to a great movie. If you haven't seen it, highly recommended.
|
# reference to a great movie. If you haven't seen it, highly recommended.
|
||||||
|
|
||||||
echo repr x
|
echo repr x
|
||||||
|
|
||||||
|
# bug #13112: bind the same finalizer multiple times:
|
||||||
|
var xx: Foo
|
||||||
|
new(xx, finalizer)
|
||||||
|
xx.field = "Nobody"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue