diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-01-13 15:47:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-13 15:47:17 +0100 |
commit | eadd1ba9ed38a1c8f48005443f60499b1f0200e3 (patch) | |
tree | 541eff4cc2be6b501faa08ac8ac724c83dd84bf0 /compiler | |
parent | abea80376a113fb218c22b6474727c279e694cd3 (diff) | |
download | Nim-eadd1ba9ed38a1c8f48005443f60499b1f0200e3.tar.gz |
fixes #13112 (#13127)
* improve line error information * fixes #13112
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semmagic.nim | 11 | ||||
-rw-r--r-- | compiler/semstmts.nim | 9 |
2 files changed, 18 insertions, 2 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index c259f0d7c..3b329c50c 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -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 diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f21f5122c..475ec32a4 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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 |