adds documentation for =wasMoved and =dup hooks and small fixes (#21827)

* adds documentation for `=wasMoved` and `=dup` hooks and small fixes

* Update doc/destructors.md

* Update doc/destructors.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
ringabout
2023-05-11 19:38:27 +08:00
committed by GitHub
parent fa5e7dc44a
commit 3b9999b93c
7 changed files with 44 additions and 7 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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
==============

View File

@@ -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,

View File

@@ -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".} =

View File

@@ -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 =