Skip to content

[REG 2.103.0] GC never finalizes a class whose only destructors are field destructors #23979

Closed

Description

@flashburns

A class with no ~this() (or any base class) whose fields have destructors is allocated without BlkAttr.FINALIZE, so the GC never runs the field destructors, either on collection or at program exit. destroy and scope work correctly. Adding an empty ~this() {} to the class works around it.

import core.memory : GC;

__gshared int finalized;

struct R {
	int x;
	~this() {
		if (x) ++finalized;
	}
}

// no ~this(): only a field destructor
class C {
	R r = R(1);
}

void main() {
	assert(GC.getAttr(cast(void*) new C) & GC.BlkAttr.FINALIZE); // fails
	foreach (i; 0 .. 100) new C;
	GC.collect();
	assert(finalized > 0); // also fails: no C is ever finalized (comment out the first assert)
}

Fails with DMD64 D Compiler v2.113.0 and GDC 14.2 (frontend 2.108). Passes with LDC 1.43.0, which lowers new to its own _d_allocclass(ClassInfo).

Cause: core.lifetime._d_newclassT sets FINALIZE only if __traits(hasMember, T, "__dtor"). __dtor exists only for a user-declared destructor; a class whose destruction comes only from its fields has just __xdtor. typeid(C).destructor is set and ClassFlags.hasDtor is set, so the ClassInfo is correct.

Regression: This started in 2.103.0 with #14837, which turned _d_newclass into the _d_newclassT template. The old function checked ClassFlags.hasDtor, which includes field destructors; the template only checks for __dtor. I confirmed this by building both releases from their tags: 2.102.2 finalizes the class and 2.103.0 does not. GDC shows the same split between GDC 12 and GDC 13.

Related:

I have a patch ready, tho im not 100% sure its exactly whats needed.

Activity

  1. added 2 commits that reference this issue on Oct 6, 2026
    a5bbefe
    7a2b1cb
  2. added a commit that references this issue on Oct 7, 2026
    551b902
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions