From doc page as well as from gobject-introspection we have
indicating that the variant is owned by the library and we must not free it. Most often we have [transfer none] for single instances of gtk, which are reused by the lib and so not have to be freed by user.
But for GVariant? I would really assume that they are allocated new on heap for g_variant_new_ calls, so we have to free then. OK, docs say they are floating, so when we would add them from plain C code to a container then we can forget about them as container will free them. But are we adding them always to container from C code? Compare that to plain gtk widgets – gtk_button_new() will give us also a floating widget, but that function is not marked with [transfer none], and so the nim GC handles that well, employing all the toggle_ref and finalizer stuff.
You cannot use toggle references with GVariant because GVariant is not a GObject.
The rules of thumb for the GVariant API are:
each function that constructs a GVariant returns a floating reference
each function that consumes a GVariant—e.g. takes a GVariant and places it somewhere else, like GVariantBuilder—sinks the floating reference, if any is found
The (transfer none) annotation is meant to be used as an indication that your language should not acquire a reference; the ownership of the GVariant instance is not transferred to the caller, because the only thing that can transfer the ownership is an explicit call to g_variant_ref_sink().
The suggestion for language binding is to treat GVariant as a special case, and always call g_variant_ref_sink() before returning from any constructor function, like for any GObject type that inherits from GInitiallyUnowned you’re encouraged to call g_object_ref_sink(). Basically: language bindings should not expose floating references at all—as they have always been a C convenience feature.
And yes, before you ask: floating references are painful, but their design predate (in the case of GObject) introspection and automated language bindings.