diff options
-rw-r--r-- | compiler/injectdestructors.nim | 4 | ||||
-rw-r--r-- | compiler/liftdestructors.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | doc/destructors.md | 37 | ||||
-rw-r--r-- | doc/manual.md | 2 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | tests/arc/tdup.nim | 2 |
7 files changed, 44 insertions, 7 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 9745fee81..7183aac4e 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -431,7 +431,9 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = let src = p(n, c, s, normal) result.add newTreeI(nkFastAsgn, src.info, tmp, - genOp(c, op, src) + newTreeIT(nkCall, src.info, src.typ, + newSymNode(op), + src) ) elif typ.kind == tyRef: let src = p(n, c, s, normal) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 85403586f..43e5baf08 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -8,7 +8,7 @@ # ## This module implements lifting for type-bound operations -## (``=sink``, ``=copy``, ``=destroy``, ``=deepCopy``). +## (`=sink`, `=copy`, `=destroy`, `=deepCopy`, `=wasMoved`, `=dup`). import modulegraphs, lineinfos, idents, ast, renderer, semdata, sighashes, lowerings, options, types, msgs, magicsys, tables, ccgutils diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 126d1aa65..f81423915 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1819,7 +1819,7 @@ proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) = of {attachedDestructor, attachedWasMoved}: t.len == 2 and t[0] == nil and t[1].kind == tyVar of attachedDup: - t.len == 2 and t[0] != nil and t[1].kind == tyVar + t.len == 2 and t[0] != nil of attachedTrace: t.len == 3 and t[0] == nil and t[1].kind == tyVar and t[2].kind == tyPointer else: diff --git a/doc/destructors.md b/doc/destructors.md index a37eade33..d924c7c4c 100644 --- a/doc/destructors.md +++ b/doc/destructors.md @@ -101,7 +101,7 @@ well as other standard collections is performed via so-called "Lifetime-tracking hooks", which are particular [type bound operators]( manual.html#procedures-type-bound-operators). -There are 4 different hooks for each (generic or concrete) object type `T` (`T` can also be a +There are 6 different hooks for each (generic or concrete) object type `T` (`T` can also be a `distinct` type) that are called implicitly by the compiler. (Note: The word "hook" here does not imply any kind of dynamic binding @@ -262,6 +262,41 @@ The general pattern in using `=destroy` with `=trace` looks like: **Note**: The `=trace` hooks (which are only used by `--mm:orc`) are currently more experimental and less refined than the other hooks. +`=WasMoved` hook +---------------- + +A `wasMoved` hook resets the memory of an object to its initial (binary zero) value to signify it was "moved" and to signify its destructor should do nothing and ideally be optimized away. + +The prototype of this hook for a type `T` needs to be: + + ```nim + proc `=wasMoved`(x: var T) + ``` + +`=dup` hook +----------- + +A `=dup` hook duplicates the memory of an object. `=dup(x)` can be regarded as an optimization replacing the `wasMoved(dest); =copy(dest, x)` operation. + +The prototype of this hook for a type `T` needs to be: + + ```nim + proc `=dup`(x: T): T + ``` + +The general pattern in implementing `=dup` looks like: + + ```nim + type + Ref[T] = object + data: ptr T + rc: ptr int + + proc `=dup`[T](x: Ref[T]): Ref[T] = + result = x + if x.rc != nil: + inc x.rc[] + ``` Move semantics ============== diff --git a/doc/manual.md b/doc/manual.md index 7fe9923f4..f3fe62c49 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -4155,7 +4155,7 @@ the operator is in scope (including if it is private). ``` Type bound operators are: -`=destroy`, `=copy`, `=sink`, `=trace`, `=deepcopy`, `=wasMoved`. +`=destroy`, `=copy`, `=sink`, `=trace`, `=deepcopy`, `=wasMoved`, `=dup`. These operations can be *overridden* instead of *overloaded*. This means that the implementation is automatically lifted to structured types. For instance, diff --git a/lib/system.nim b/lib/system.nim index e8664d7a4..e7b6ed7c3 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -350,7 +350,7 @@ proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = when defined(nimHasDup): proc `=dup`*[T](x: ref T): ref T {.inline, magic: "Dup".} = - ## Generic `dup` implementation that can be overridden. + ## Generic `dup`:idx: implementation that can be overridden. discard proc `=sink`*[T](x: var T; y: T) {.inline, nodestroy, magic: "Asgn".} = diff --git a/tests/arc/tdup.nim b/tests/arc/tdup.nim index 3f64061fb..b77f5c6eb 100644 --- a/tests/arc/tdup.nim +++ b/tests/arc/tdup.nim @@ -40,7 +40,7 @@ proc inc(x: sink Ref) = proc inc(x: sink RefCustom) = inc x.id[] -proc `=dup`(x: var RefCustom): RefCustom = +proc `=dup`(x: RefCustom): RefCustom = result.id = x.id proc foo = |