mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-20 07:51:32 +00:00
@@ -383,7 +383,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||
# little hack for injectdestructors.nim (see bug #11350):
|
||||
#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.
|
||||
# Replace nkDerefExpr by nkHiddenDeref
|
||||
# nkDeref is for 'ref T': x[].field
|
||||
@@ -400,7 +400,9 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym): PSym =
|
||||
# result =
|
||||
|
||||
result = copySym(orig)
|
||||
result.info = info
|
||||
result.flags.incl sfFromGeneric
|
||||
result.owner = orig
|
||||
let origParamType = orig.typ[1]
|
||||
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs))
|
||||
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}:
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
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
|
||||
of mDestroy:
|
||||
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)
|
||||
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) =
|
||||
let t = s.typ
|
||||
var noError = false
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
discard """
|
||||
cmd: "nim c --gc:arc $file"
|
||||
output: '''Foo(field: "Dick Laurent", k: ka, x: 0.0)
|
||||
Nobody 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.
|
||||
|
||||
echo repr x
|
||||
|
||||
# bug #13112: bind the same finalizer multiple times:
|
||||
var xx: Foo
|
||||
new(xx, finalizer)
|
||||
xx.field = "Nobody"
|
||||
|
||||
Reference in New Issue
Block a user