diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 788f7a470bde1..191e1c5c65d1c 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -84,7 +84,8 @@ proc cleanupTemp(p: BProc; returnType: PType, tmp: TLoc): bool = let dtor = getAttachedOp(p.module.g.graph, returnType, attachedDestructor) var op = initLocExpr(p, newSymNode(dtor)) var callee = rdLoc(op) - let destroy = if dtor.typ.firstParamType.kind == tyVar: + let destroy = if dtor.typ.firstParamType.kind == tyVar or + tfByRef in dtor.typ.firstParamType.flags: callee & "(&" & rdLoc(tmp) & ")" else: callee & "(" & rdLoc(tmp) & ")" diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index e6b6d5b42a33e..99db096662640 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -275,13 +275,16 @@ proc deepAliases(dest, ri: PNode): bool = return aliases(dest, ri) != no proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode = + let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or (isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or - isNoInit(dest) or IsReturn in flags: + isNoInit(dest) or IsReturn in flags or + (tfByRef in dest.typ.flags and getAttachedOp(c.graph, t, attachedSink) != nil and + sfError in getAttachedOp(c.graph, t, attachedSink).flags + ): # optimize sink call into a bitwise memcopy result = newTree(nkFastAsgn, dest, ri) else: - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if getAttachedOp(c.graph, t, attachedSink) != nil: result = c.genOp(t, attachedSink, dest, ri) result.add ri diff --git a/tests/arc/tarc_orc.nim b/tests/arc/tarc_orc.nim index f2c7de2fca410..99fdc61525741 100644 --- a/tests/arc/tarc_orc.nim +++ b/tests/arc/tarc_orc.nim @@ -99,7 +99,7 @@ type proc imageCopy*(image: Image): Image {.nodestroy.} -proc `=destroy`*(x: var Image) = +proc `=destroy`*(x: Image) = discard proc `=sink`*(dest: var Image; source: Image) = `=destroy`(dest) @@ -111,7 +111,7 @@ proc `=dup`*(source: Image): Image {.nodestroy.} = proc `=copy`*(dest: var Image; source: Image) = dest = imageCopy(source) # calls =sink implicitly -proc `=destroy`*(x: var EmbeddedImage) = discard +proc `=destroy`*(x: EmbeddedImage) = discard proc `=dup`*(source: EmbeddedImage): EmbeddedImage {.nodestroy.} = source @@ -184,3 +184,32 @@ block: # bug #24147 let oo = OO(val: "hello world") var ooCopy : OO `=copy`(ooCopy, oo) + +block: + type MyObj {.byref.} = object + value: int + + proc `=copy`(a: var MyObj, b: MyObj) {.error.} + proc `=sink`(a: var MyObj, b: MyObj) {.error.} + + proc createMyObj(value: int): MyObj = + result.value = value + + var x: MyObj + x = createMyObj(3) + +block: + type MyObj {.byref.} = object + value: int + + proc `=copy`(a: var MyObj, b: MyObj) {.error.} + proc `=sink`(a: var MyObj, b: MyObj) {.error.} + + proc createMyObj(value: int): MyObj = + result.value = value + + proc foo = + var x: MyObj + x = createMyObj(3) + + foo()