I'm trying to understand how the [lifetime-tracking hooks](https://nim-lang.github.io/Nim/destructors.html) work, but I'm not sure if I'm doing it correctly. The code below is an implementation of a slab (an array with reusable slots). It is almost an exact copy of the [example](https://nim-lang.github.io/Nim/destructors.html#motivating-example).
1. Inside the `=destroy` hook, I'm using a try/except because the compiler is indicating that ``=destroy`(self.data[i])` will raise an exception. 2. When will `=dup` be called instead of copy? 3. In the [example](https://nim-lang.github.io/Nim/destructors.html#motivating-example), the `=dup` hook is annotated with `{.nodestroy.}`. Is there any particular reason for this? type Key = distinct uint64 Slab*[T] = object len, cap: uint64 data: ptr UncheckedArray[T] available: seq[Key] highestKey: uint64 proc `=destroy`[T](self: Slab[T])= if self.data != nil: for i in 0..<self.len: try: `=destroy`(self.data[i]) except: discard dealloc(self.data) proc `=trace`[T](self: var Slab[T], env: pointer) = if self.data == nil: return for i in 0..<self.len: `=trace`(self.data[i], env) proc `=copy`[T](dest: var Slab[T], src: Slab[T]) = if dest.data == src.data: return `=destroy`(dest) wasMoved(dest) dest.len = src.len dest.cap = src.cap if src.data == nil: return dest.data = cast[typeof(src.data)](alloc(dest.cap * uint64(sizeof(T)))) for i in 0..<dest.len: dest.data[i] = src.data[i] proc `=sink`[T](dest: var Slab[T], src: Slab[T]) = `=destroy`(dest) wasMoved(dest) dest.len = src.len dest.cap = src.cap dest.data = src.data proc `=dup`[T](self: Slab[T]): Slab[T] = result.len = self.len result.cap = self.cap if self.data != nil: result.data = cast[typeof(result.data)](alloc(result.cap * uint64(sizeof(T)))) for i in 0..<result.len: result.data[i] = `=dup`(self.data[i]) proc len*[T](self: Slab[T]): uint64 = self.len proc capacity*[T](self: Slab[T]): uint64 = self.cap proc `[]`*[T](self: Slab[T], key: Key): lent T= self.data[uint64(key)] proc add*[T](self: var Slab[T], value: sink T): Key = if self.available.len > 0: return self.available.pop() result = Key(self.highestKey) inc self.highestKey self.data[uint64(result)] = value inc self.len proc remove*[T](self: var Slab[T], key: sink Key): T = result = self.data[uint64(key)] self.available.add(key) dec self.len proc clear*[T](self: var Slab[T]) = discard proc initSlab*[T](capacity: uint64 = 1024): Slab[T] = result.cap = capacity result.len = 0 result.data = cast[typeof(result.data)](alloc0(result.cap * uint64(sizeof(T)))) result.available = @[] result.highestKey = 0 iterator items*[T](self: var Slab[T]): lent T = for i in 0..<self.highestKey: yield self.data[i] Run
