Re: Idea why this does not compile?
> need to define your destructor earlier Yes, my initial guess was indeed that, as it was done in that way in the earlier gintro code. But I became unsure if it would work really fine also that way. And it remains strange, as my fnew template should fully hide the use of the finalizer when we compile with --gc:arc. So I assume that both branches of the when construct are processed by the compiler and that confuses the compiler? In the same way as discarded code is always syntax checked? Unfortunately ordering the code is not that easy, as it is autogenerated from the gobject-introspection database, and for latest gtk 3.98.3 which will become 4.0 there are some serious changes. I can not just put the =destroy just after the type declaration, as =destroy calls low level procs like gdk_event_unref(self.impl) above. So carefully sorting will be necessary. Note that forward declarations like below do not compile: proc gdk_event_unref(self: ptr Event00) proc gdk_event_unref(self: ptr Event00) {.importc, libprag.} Run Error: pragmas are only allowed in the header of a proc; redefinition of 'gdk_event_unref' Run What should work is declaring a special unref function before declaring the =destroy and using that one in the =destroy like proc destroy_gdk_event_unref(self: ptr Event00) {.importc: gdk_event_unref, libprag.} Run
Re: Idea why this does not compile?
I know why it doesn't compile but my reply would be identical to the compiler's error message. You need to define your destructor earlier, like so: when defined(gcDestructors): proc `=destroy`*(self: var typeof(Event()[])) = if not self.ignoreFinalizer and self.impl != nil: echo "gdk_event_unref(self.impl)" self.impl = nil template fnew*(a: untyped; finalizer: untyped) = when defined(gcDestructors): new(a) else: new(a, finalizer) proc `ref`*(self: Event): Event = fnew(result, generic_gdk_event_unref) echo "result.impl = gdk_event_ref(cast[ptr Event00](self.impl))" proc generic_gdk_event_unref*[T](self: ref T) = if not self.ignoreFinalizer: echo "gdk_event_unref(self.impl)" Run
Idea why this does not compile?
I was just working a bit on gintro for latest GTK4 and got a really confusing error message. Luckely I was just able to generate a minimal example, but I have still no real idea what the problem may be. I guess there must be something special in this code, because I have used similar constructs before and it was working fine... type Event* = ref object of RootRef impl*: pointer ignoreFinalizer*: bool template fnew*(a: untyped; finalizer: untyped) = when defined(gcDestructors): new(a) else: new(a, finalizer) proc `ref`*(self: Event): Event = fnew(result, generic_gdk_event_unref) echo "result.impl = gdk_event_ref(cast[ptr Event00](self.impl))" proc generic_gdk_event_unref*[T](self: ref T) = if not self.ignoreFinalizer: echo "gdk_event_unref(self.impl)" when defined(gcDestructors): proc `=destroy`*(self: var typeof(Event()[])) = if not self.ignoreFinalizer and self.impl != nil: echo "gdk_event_unref(self.impl)" self.impl = nil proc main = var x: Event fnew(x, generic_gdk_event_unref) main() Run $ nim c --gc:arc t2.nim /tmp/hhh/t2.nim(21, 3) Error: cannot bind another '=destroy' to: Event:ObjectType; previous declaration was constructed here implicitly: /tmp/hhh/t2.nim(13, 3) Run $ nim -v Nim Compiler Version 1.3.3 [Linux: amd64] Compiled at 2020-05-11 Copyright (c) 2006-2020 by Andreas Rumpf git hash: 7c24250a575b4d441ba6d7301714cbb246425fb6 active boot switches: -d:release Run