Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

Add @nogc attribute on types

Version 3
Created 2014-11-10
StatusDraft
Last modified 2014-11-10
Author Tomer Filiba

Abstract

This DIP proposes the addition of a compiler-enforced @nogc attribute on types. This means means such a type cannot be allocated by the GC, e.g., using operator new on such a type or appending such a type to a dynamic array, would result in compile-time errors.

It enforces separation between deterministic and non-deterministic finalization and lifetime of objects, which is crucial for proper RAII idiom.

Rationale

Implementing RAII properly requires deterministic resource management, thus objects managed by the GC cannot be safely used for such purposes. The GC offers little to no guarantees on when (or even whether) destructors be called, or the order in which resources are released. It is clear one cannot rely on GC-managed objects for RAII. It would be suggested, therefore, that objects implementing the RAII idiom be stack-allocated structs (rather than classes, etc), which is necessary but not sufficient – as long as one cannot enforce that such structs do not enter the GC heap.

The purpose of this DIP is exactly that – to designate structs (and possible other types, such as emplaced classes) as types that must not be allocated and managed by the GC. Any object with a non-deterministic life-time (i.e., GC-managed) will not be able to hold @nogc types, thus ensuring RAII is preserved.

Description

Like @nogc on functions, @nogc on structs is transitive (albeit in the reverse direction): if struct A holds a member of type B, and B is marked @nogc, then A inherits the @nogc. Pointers to such types are allowed in any context.

A complementary attribute, e.g., __traits(isNoGC, T) or __traits(getTypeAttributes, T) would be needed for reflection.

Usage

@nogc struct MyStruct {
    int x;
    string y;
}

void foo() {
    MyStruct ms;                 // compiles
    auto ms2 = new MyStruct();   // does not compile
    MyStruct[] arr; 
    arr ~= MyStruct();           // does not compile

    auto ms3 = cast(MyStruct*)malloc(MyStruct.sizeof);  // this is fine, of course
}

This document has been placed in the Public Domain.