It is possible to do things like string concatenation inside a destructor. That shouldn't be allowed to compile because it is not valid code. The compiler should treat destructors as @nogc whether they're marked that way or not.
Example code:
import std.stdio;
struct Predictable
{
string id;
this(string _id)
{
writeln("Constructor ", _id);
id = _id;
}
~this()
{
writeln("Destructor " ~ id);
}
}
void main()
{
Predictable[] result;
result ~= Predictable("1");
writeln("result: ", result);
}
Dies with
Constructor 1
result: [Predictable("1")]
core.exception.InvalidMemoryOperationError@src/core/lifetime.d(126): Invalid memory operation
Putting @nogc on the destructor, the compiler gives this message:
onlineapp.d(12): Error: `@nogc` destructor `onlineapp.Predictable.~this` cannot call non-@nogc function `std.stdio.writeln!string.writeln`
/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(4251): which calls `std.stdio.trustedStdout`
onlineapp.d(12): Error: cannot use operator `~` in `@nogc` destructor `onlineapp.Predictable.~this`
https://run.dlang.io/is/7fZepu
Comment #1 by elpenguino+D — 2023-09-15T17:02:09Z
I think this is the wrong way to approach the issue. It is perfectly valid for a destructor to allocate using the GC, as long as the struct itself is not allocated using the GC.
Example code:
```
import std.stdio;
struct Predictable
{
string id;
this(string _id)
{
writeln("Constructor ", _id);
id = _id;
}
~this()
{
writeln("Destructor " ~ id);
}
}
void main()
{
Predictable result = Predictable("1");
}
```
outputs two lines, 'Constructor 1' and 'Destructor 1' without issue.
I'd say it's better to simply forbid anything with a non-@noGC destructor from being used with new or array reallocation instead.
Comment #2 by robert.schadek — 2024-12-13T19:30:49Z