diff options
-rw-r--r-- | compiler/liftdestructors.nim | 16 | ||||
-rw-r--r-- | tests/arc/t14383.nim | 66 |
2 files changed, 77 insertions, 5 deletions
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 943dd074e..45a66e795 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -42,6 +42,9 @@ proc at(a, i: PNode, elemType: PType): PNode = result[1] = i result.typ = elemType +proc destructorOverriden(t: PType): bool = + t.attachedOps[attachedDestructor] != nil and sfOverriden in t.attachedOps[attachedDestructor].flags + proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) = for i in 0..<t.len: let lit = lowerings.newIntLit(c.g, x.info, i) @@ -292,8 +295,10 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym = proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; field: var PSym): bool = if optSeqDestructors in c.g.config.globalOptions: - let op = field - if field != nil and sfOverriden in field.flags: + var op = field + let destructorOverriden = destructorOverriden(t) + if op != nil and op != c.fn and + (sfOverriden in op.flags or destructorOverriden): if sfError in op.flags: incl c.fn.flags, sfError #else: @@ -301,6 +306,10 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; onUse(c.info, op) body.add newHookCall(c, op, x, y) result = true + elif op == nil and destructorOverriden: + op = produceSym(c.g, c.c, t, c.kind, c.info, c.idgen) + body.add newHookCall(c, op, x, y) + result = true elif tfHasAsgn in t.flags: var op: PSym if sameType(t, c.asgnForType): @@ -909,8 +918,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; # register this operation already: typ.attachedOps[kind] = result - if kind == attachedSink and typ.attachedOps[attachedDestructor] != nil and - sfOverriden in typ.attachedOps[attachedDestructor].flags: + if kind == attachedSink and destructorOverriden(typ): ## compiler can use a combination of `=destroy` and memCopy for sink op dest.flags.incl sfCursor result.ast[bodyPos].add newOpCall(a, typ.attachedOps[attachedDestructor], d[0]) diff --git a/tests/arc/t14383.nim b/tests/arc/t14383.nim index 834c50def..7c63f7333 100644 --- a/tests/arc/t14383.nim +++ b/tests/arc/t14383.nim @@ -4,6 +4,21 @@ discard """ hello hello @["a", "b"] +--------------------- +plain: +destroying: ('first', 42) +destroying: ('second', 20) +destroying: ('third', 12) + +Option[T]: +destroying: ('first', 42) +destroying: ('second', 20) +destroying: ('third', 12) + +seq[T]: +destroying: ('first', 42) +destroying: ('second', 20) +destroying: ('third', 12) ''' """ @@ -47,4 +62,53 @@ proc freeJVMObject(o: JVMObject) = proc fromJObject(T: typedesc[JVMObject]): T = result.new(cast[proc(r: T) {.nimcall.}](freeJVMObject)) -discard JVMObject.fromJObject() \ No newline at end of file +discard JVMObject.fromJObject() + + +#------------------------------------------------------------------------------ +# Issue #15910 +#------------------------------------------------------------------------------ + +import options + +type + Thing = object + name: string + age: int + +proc `=destroy`(thing: var Thing) = + if thing.name != "": + echo "destroying: ('", thing.name, "', ", thing.age, ")" + `=destroy`(thing.name) + `=destroy`(thing.age) + +proc plain() = + var t = Thing(name: "first", age: 42) + t = Thing(name: "second", age: 20) + t = Thing() + let u = Thing(name: "third", age: 12) + +proc optionT() = + var t = Thing(name: "first", age: 42).some + t = Thing(name: "second", age: 20).some + t = none(Thing) + let u = Thing(name: "third", age: 12).some + +proc seqT() = + var t = @[Thing(name: "first", age: 42)] + t = @[Thing(name: "second", age: 20)] + t = @[] + let u = @[Thing(name: "third", age: 12)] + +echo "---------------------" +echo "plain:" +plain() +echo() + +echo "Option[T]:" +optionT() +echo() + +echo "seq[T]:" +seqT() +echo() \ No newline at end of file |