D’s Forty-Year Identity Crisis
Garbage collection, manual memory management, and metaprogramming were all offered as options rather than defaults. That flexibility was the entire pitch, and it is also the reason D never became what it was clearly capable of being.
D is older than Go, older than Rust, older than Swift and Kotlin. It had garbage collection, template metaprogramming, and native compilation years before any of those languages existed. And yet all four of them are household names among systems programmers today, while D remains the language most engineers have heard of but never used. The usual explanation is bad luck or bad marketing. The more interesting explanation is that D’s core strategy, offering a menu of options where its eventual rivals offered one firm answer, is precisely what kept it from ever fully arriving.
A Language Built to Offer Choices
Walter Bright began work on what he called Mars in late 1999 at Digital Mars, aiming to fix specific frustrations with C++ while keeping its performance. The language went public on December 8, 2001, reached a stable D1.0 on January 2, 2007, and released the more ambitious D2 five months later. Andrei Alexandrescu joined the design effort in 2007 and became its most visible voice, describing the language’s guiding principle less as minimalism and more as a favorable power-to-weight ratio: give programmers real choices about paradigm, safety, and performance rather than forcing one philosophy on everyone. D supported imperative, object-oriented, and functional styles from early on, and it treated garbage collection, manual memory management, and reference counting as coexisting options rather than a single settled answer.
The Great Fragmentation: Tango vs Phobos
Optionality did not stay confined to language features. It reached the standard library itself. D1’s official runtime and standard library, Phobos, left a meaningful part of the early community unsatisfied, and a group of contributors built an alternative called Tango with a different design philosophy, closer in spirit to Java’s batteries-included standard library than Phobos’s leaner approach. The problem was not that two libraries existed side by side, plenty of ecosystems tolerate that. The problem was that Tango redefined low-level runtime pieces, including the object model and garbage collector hooks, in ways that made it structurally incompatible with Phobos. A project had to commit to one or the other, and code written against one generally could not link against the other.
Contemporary discussion on the D forums captured the anxiety directly: community members worried openly that if Tango could not coexist peacefully with Phobos, it would divide an already small developer base, again. That fear proved accurate for years. The two camps did not fully reconcile until D2’s druntime effort gave both libraries a shared low-level foundation around 2010 and 2011, roughly four years after the split began, a long stretch for a young language trying to build momentum.
The GC That Was Never Quite Optional
The manual memory management side of D’s pitch had a similar gap between promise and delivery. In 2009, Andrei Alexandrescu wrote candidly on the D forums that the possibility of using D without its garbage collector had always been part of the sales pitch, something to point to when skeptics asked about performance, but that the promise had never actually been made seamless: ordinary operations like concatenating arrays, inserting into a hash table, or creating a class instance all silently called into the GC regardless of what the programmer intended. The fix, a compiler-enforced @nogc attribute that could actually guarantee a function never triggers garbage collection, was not proposed until 2014 as DIP60 and shipped in DMD 2.066 that same year, thirteen years after D’s first public release. For over a decade, “you can avoid the GC if you want to” was true in the loosest possible sense: technically permitted, never verified.
Three places optionality created cost instead of freedom:
- Two incompatible standard libraries splitting a small community for roughly four years
- A GC-optional pitch with no compiler enforcement for D’s first thirteen years
- Multiple valid paradigms and memory strategies meaning no single, one-sentence answer to “what is D for”
What the Market Chose Instead
Rust took the opposite bet on almost the same value proposition. Rather than offering a garbage collector as a default with an escape hatch, Rust shipped in 2015 with no garbage collector at all and exactly one enforced memory model: ownership and borrowing, checked entirely at compile time. There was no second standard library to choose between and no unchecked promise about safety, the borrow checker either accepted a program or it didn’t. Despite arriving fourteen years after D, Rust had a single sentence that explained what it was for, memory safety without a garbage collector, and that sentence turned out to travel much further than D’s broader menu of choices.

| Language | First public release | Memory model | TIOBE presence, late 2025 |
|---|---|---|---|
| D | 2001 | GC by default, manual and @nogc as opt-in paths | Outside the top 20 |
| Rust | 2015 (1.0) | Ownership and borrowing, enforced at compile time, no GC | Rank 16 |
None of this means D lost on technical merit. Its metaprogramming system, built on compile-time function execution and templates, is still regarded by many who have used it as more ergonomic than C++’s, and its concurrency and safety attributes were ahead of their time. What it lost was the ability to be described in one sentence, adopted by a team without a debate about which subset of the language to standardize on, and marketed against newer, narrower competitors who had exactly that.
What We Have Learned
D’s history is not a story about a language that made bad technical decisions. It is a story about a language that treated every hard tradeoff, garbage collection versus manual memory, one standard library versus community-driven alternatives, as a decision to defer to the programmer rather than resolve at the language level. That looked like generosity and flexibility from the inside. From the outside, to a team evaluating which systems language to bet a codebase on, it looked like ambiguity: which D are we actually choosing, and which parts of its own community already disagree about the answer. Rust’s narrower, harder commitment to a single memory model turned out to be easier to trust precisely because it left less to decide, and that is the ceiling D’s flexibility quietly built for itself.


