Open
Description
I get a cannot instantiate =destroy
in the following complex case. The workaround is to have a dummy global variable of the type that has the destructor or that contains it.
While it seems like a similar cross-module visibility issue that also involves mixin like the generic sandwich #11225, just exporting the =destroy
that had the mixin doesn't solve the issue so it's probably something else.
Tagging low priority as there are 4 workarounds:
- not using destructors
- not using concepts
- instantiating a dummy variable in the inner exports
- exporting the inner type that implements the concept (ensuring visibility of the container with destructors is not enough)
File 1: runtime.nim
Compile this to reproduce the problem
# runtime.nim
import ./context_thread_local
var localCtx* : TLContext
File 2: context_thread_local.nim
2 fixes are possible in this file, exporting "tasks" or instantiating a magic variable
# context_thread_local
import ./tasks, ./listdeques
export listdeques # Exporting the type with destructor doesn't help
# export tasks # solution 1. Exporting the inner type
type MagicCompile = object
dq: ListDeque[Task]
# var x: MagicCompile # solution 2. Instantiating the type with destructors
echo "Success"
type
TLContext* = object
deque*: ListDeque[Task]
File 3: listdeques.nim
Remove the concept and everything works as well
# listdeques
type
StealableTask* = concept task, var mutTask, type T
task is ptr
task.prev is T
task.next is T
task.parent is T
task.fn is proc (param: pointer) {.nimcall.}
allocate(mutTask)
delete(task)
ListDeque*[T: StealableTask] = object
head, tail: T
func isEmpty*(dq: ListDeque): bool {.inline.} =
discard
func popFirst*[T](dq: var ListDeque[T]): T =
discard
proc `=destroy`*[T: StealableTask](dq: var ListDeque[T]) =
mixin delete
if dq.isEmpty():
return
while (let task = dq.popFirst(); not task.isNil):
delete(task)
delete(dq.head)
File 4: tasks.nim
The base type, it just needs to implement the concept
# tasks.nim
type
Task* = ptr object
parent*: Task
prev*: Task
next*: Task
fn*: proc (param: pointer) {.nimcall.}
# StealableTask API
proc allocate*(task: var Task) =
discard
proc delete*(task: Task) =
discard