www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to call destroy() in nogc?

reply cc <cc nevernet.com> writes:
```d
import core.memory;
import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;

T NEW(T, Args...)(auto ref Args args) /* nogc*/ if (is(T == 
class)) {
	enum size = __traits(classInstanceSize, T);
	void* mem = malloc(size);
	scope(failure) free(mem);
	return mem !is null ? emplace!T(mem[0..size], args) : null;
}
void FREE(T)(ref T obj)  nogc if (is(T == class)) {
	auto mem = cast(void*) obj;
	scope(exit) free(mem);
	destroy(obj);
	obj = null;
}

class Foo {
	~this()  nogc {}
}

void main() {
	auto foo = NEW!Foo;
	FREE(foo);
}
```
```
Error: ` nogc` function `nogctest.FREE!(Foo).FREE` cannot call 
non- nogc function `object.destroy!(true, Foo).destroy`
```

Is this not currently possible?  Found this thread:
https://forum.dlang.org/thread/zanuuhzmqxljadcexmgv forum.dlang.org?page=1
is it still unresolved?
May 23 2022
next sibling parent reply Tejas <notrealemail gmail.com> writes:
On Tuesday, 24 May 2022 at 02:29:38 UTC, cc wrote:
 ```d
 import core.memory;
 import core.stdc.stdlib : malloc, free;
 import core.lifetime : emplace;

 [...]
FWIW your code will compile if you add `extern(C++)` to `Foo`
May 23 2022
parent cc <cc nevernet.com> writes:
On Tuesday, 24 May 2022 at 02:55:06 UTC, Tejas wrote:
 On Tuesday, 24 May 2022 at 02:29:38 UTC, cc wrote:
 ```d
 import core.memory;
 import core.stdc.stdlib : malloc, free;
 import core.lifetime : emplace;

 [...]
FWIW your code will compile if you add `extern(C++)` to `Foo`
Interesting, thanks. I noticed something similar when trying to call malloc in a pure function... std.internal.memory: ```d extern (C) nogc nothrow pure private { pragma(mangle, "malloc") void* fakePureMalloc(size_t) safe; pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size) safe; pragma(mangle, "realloc") void* fakePureRealloc(return scope void* ptr, size_t size) system; } ```
May 23 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/23/22 10:29 PM, cc wrote:
 ```d
 import core.memory;
 import core.stdc.stdlib : malloc, free;
 import core.lifetime : emplace;
 
 T NEW(T, Args...)(auto ref Args args) /* nogc*/ if (is(T == class)) {
      enum size = __traits(classInstanceSize, T);
      void* mem = malloc(size);
      scope(failure) free(mem);
      return mem !is null ? emplace!T(mem[0..size], args) : null;
 }
 void FREE(T)(ref T obj)  nogc if (is(T == class)) {
      auto mem = cast(void*) obj;
      scope(exit) free(mem);
      destroy(obj);
      obj = null;
 }
 
 class Foo {
      ~this()  nogc {}
 }
 
 void main() {
      auto foo = NEW!Foo;
      FREE(foo);
 }
 ```
 ```
 Error: ` nogc` function `nogctest.FREE!(Foo).FREE` cannot call non- nogc 
 function `object.destroy!(true, Foo).destroy`
 ```
 
 Is this not currently possible?  Found this thread:
 https://forum.dlang.org/thread/zanuuhzmqxljadcexmgv forum.dlang.org?page=1
 is it still unresolved?
It's because destroy calls the destructor without any attribute requirements aside from nothrow. https://github.com/dlang/druntime/blob/bdeee862aaa125e75aebc3118a43d2d5e5ee954d/src/object.d#L4431-L4453 Here is the definition of `rt_finalize2`: https://github.com/dlang/druntime/blob/bdeee862aaa125e75aebc3118a43d2d5e5ee954d/src/rt/lifetime.d#L1402 Note it has no idea what the real object type is at this point, just that it is an Object (which does not have a nogc destructor). -Steve
May 24 2022
parent Adam Ruppe <destructionator gmail.com> writes:
On Tuesday, 24 May 2022 at 14:11:57 UTC, Steven Schveighoffer 
wrote:
 Note it has no idea what the real object type is at this point, 
 just that it is an Object (which does not have a  nogc 
 destructor).
It actually has nothing to do with Object. It doesn't have a destructor at all, so there's no problem calling it from any context. The real problem is that destructors don't actually use the virtual machinery and call super(), meaning it is impossible to tell at compile time what they're doing at all. I know I wrote at length about this somewhere but can't find it right now. Probably in the chatroom. But even if you know static type, you can't make assumptions about the dynamic type since destructors (for no good reason tbh) don't follow the same rules as other virtual methods, despite the spec saying they are virtual.
May 24 2022