Author Archives: Michael Parker

DLang News September/October 2021: D 2.098.0, OpenBSD, SAOC, DConf Online Swag

Digital Mars D logo

Version 2.098.0 of the D programming language is now available in the form of DMD 2.098.0 (the reference D compiler) and LDC 1.28.0 (the LLVM-based D compiler), D has come to OpenBSD, cool things are happening thanks to the Symmetry Autumn of Code, and DConf Online 2021 t-shirts are available for purchase.

Read on for the deets.

DMD 2.098.0

This release comes with 17 major changes and 160 fixed Bugzilla issues from 62 contributors across the core repositories. The number of fixed issues may well be a record high. The 2.097.0 release had 144, and the 2.094.0 release had 119, but a cursory look at several other major releases shows numbers ranging from the high 40s to under 100, with counts in the 50s showing up frequently. This is the sort of trend we were hoping to see when Razvan Nitu came on board as our Pull Request and Issue Manager, and we couldn’t be more pleased.

There are two items of note that I’d like to point out from the new release, and then I have a little more to say about the work Razvan is doing.

ImportC

The ImportC compiler is a major enhancement to D that allows the D compiler to directly compile C source code. Walter has been working on it for a few months now, and this is the first release in which it’s available. ImportC enables the compiler to inline C function calls and even evaluate them at compile time via CTFE. ImportC targets C11 and does not currently handle preprocessor directives, so any C source you do intend to compile must first be run through a preprocessor. It’s not yet complete, but if you have a use case for it, any help in finding and reporting ImportC bugs is welcome. Contributions to fix said bugs doubly so!

Fork-based garbage collector

This release also includes an optional concurrent garbage collector for Posix systems. This is cool in and of itself, but more so because the project came to fruition thanks to the Symmetry Autumn of Code. It was originally developed for D1 by Leandro Lucarella but was never included in an official release (using alternative GCs back then required more than just a simple command-line switch). In 2018, for the inaugural edition of SAOC, Francesco Mecca undertook to port the GC to D2. This resulted in a pull request to DRuntime that was ultimately merged in time for this release by Rainer Schuetze.

To use the new GC, provide the DRuntime option --DRT-gcopt=fork:1 on the command-line of any program compiled against DRuntime 2.098.0+ (this is not a compiler option, but an option to any program linked with DRuntime). It can also be configured programmatically via:

extern(C) __gshared string[] rt_options = [ "gcopt=fork:1" ];

See the D documentation for more GC configuration options.

Shrinking the pull-request queues

Razvan has been managing pull requests across several of our repositories, but he’s been laser-focused on reducing the number of PRs in the phobos and druntime repositories, with dmd his next target. This isn’t just about lowering the PR count. He’s been reviving old PRs with the original author where he can (he tells me he was surprised how many PR authors were responsive, even after no activity on a PR for a few years) and has tried to rebase and resolve those where he can’t. Here are some statistics he’s gathered on PR activity so far this year across the phobos, druntime, and dmd repositories:

  • phobos: 568 PRs created, 650 PRs closed
  • druntime: 283 PRs created, 311 PRs closed
  • dmd: 1140 PRs created, 1126 closed

At the time he sent me the stats on October 29th, the number of open PRs in phobos had gone down from 160 to 77 and druntime from 130 to 96. The number of open PRs in dmd has remained fairly constant at around 230.

We want to thank Razvan for all the work he is doing, Symmetry Investments for sponsoring his position, the volunteer members of the “strike teams” Razvan has assembled to squash as many bugs as possible, and every contributor who has donated and continues to donate their time and effort to improving our favorite programming language.

LDC 1.28.0

The latest release of LDC implements D 2.098.0 (D frontend, DRuntime, and Phobos) and is compatible with LLVM 6.0 – 12.0.

A major item in this release is that LDC now supports dynamic casts across binary boundaries. DLL support has long been a weak point in D, often requiring the programmer to resort to extern(C) functions that return handles (pointers, references) to D objects. Martin Kinkelin has worked to improve the situation in LDC, motivated primarily by the desire to provide the standard library and runtime as a DLL on Windows.

Thanks to Martin and all the LDC contributors for the work they do to keep LDC releases in sync with those of DMD. If you benefit from their efforts, please consider sponsoring Martin (and LDC by extension) on GitHub!

D on OpenBSD

The D ecosystem grows primarily because of the efforts of volunteers who step forward to fill in the blanks. New D projects pop up all the time, but it’s pretty rare to hear that someone has brought D to a new platform. Brian Callahan has done just that.

Brian has been on a mission to bring D to OpenBSD. In August of this year, he popped into the D forums with an announcement that GDC, the GCC-based D compiler maintained by Iain Buclaw, was now available in the OpenBSD ports tree as part of GCC 11. In early October, he let us know that DMD was coming to the platform. Then in late October, he had the same news about LDC. Instructions for installing DMD on OpenBSD are on the download page (and can be extrapolated to LDC and GDC).

We are grateful to Brian for the work he has done to make this happen. We’re looking forward to his upcoming DConf Online 2021 talk, Life Outside the Big 4: The Adventure of D on OpenBSD:

The journey of D from pie-in-the-sky to a package officially offered in the OpenBSD package repository serves as a model story for other platforms who want to offer D to their userbase. We will walk through the many interconnected parts required to get a D package on OpenBSD, what the future is like for D outside the Big 4, how you can get started with D on your platform, and how those of us who enjoy life outside the Big 4 can be a positive force for D and the D community.

SAOC News

The SAOC 2021 progress bar is past the 25% mark. The first milestone wrapped up on October 15, and the participants have been posting weekly progress reports in the General Forum. It’s always interesting to read about the challenges they encounter and their solutions. But the latest SAOC isn’t the only edition about which there is news to report.

I’ve written above about the SAOC 2018 forking GC project that has found its way into the latest release of DRuntime. I can’t begin to tell you how pleased I am that another SAOC project has come into its own.

For SAOC 2020, Adela Vais set out to implement a D backend for the venerable Bison parser generator. Not only did Adela successfully complete SAOC, she saw her project through to its ultimate goal. The D backend was officially released as part of Bison 3.81 in September.

We want to offer Adela our congratulations and a huge round of applause for a job well done! Getting a project of this scope accepted into a GNU codebase is no mean feat.

DConf Online 2021 T-Shirts

DConf Online 2021 is less than a month away. The D Language Foundation will be providing DConf Online 2021 swag to the DConf speakers and prizes to viewers asking questions in the post-talk live stream Q & A sessions. The cost of the items and their shipping are the only DConf Online expenses, and they’re covered by the D Language Foundation General Fund.

Direct donations to the General Fund and our more targeted funds are always appreciated, but you can also help support the D programming language and DConf Online by purchasing a DConf Online 2021 T-Shirt or other D swag in the DLang Swag Emporium. All proceeds go straight into the General Fund. You get some swag along with our gratitude, and we get a couple of bucks. That’s a pretty good deal!

Looking Forward

As we near the end of 2021, we are looking forward to 2022 and beyond. The D programming language, its ecosystem, and its community have come a long way from the gaggle of curious coders who first took an interest in a one-man project by the guy who had created the game Empire and the Zortech C++ compiler.

The primary means of contributing to the core D projects went from emailing patches to Walter, to posting patches on Bugzilla, to committing to a Subversion repository, to submitting pull requests on GitHub. The web site went from being a few basic HTML pages of the D spec on digitalmars.com maintained only by Walter, to a simple HTML site designed by a community member under the dlang.org domain, to the more complex collection of pages and scripts that today is maintained in Ddoc by multiple contributors. The ecosystem has gone from random libraries and tools hosted by individuals on myriad services, to centralized hosting at dsource.org, to the package repository at code.dlang.org.

These are just some examples of major changes over the years, each in response to growth: as the community grew in size, some of the processes and systems began to burst at the seams. To continue to grow, something had to change. Such improvements have nearly always been the result of community action: discussion and debate in the forums eventually would lead to a champion stepping forward to make it happen. Community action has been the driving force of D since Walter first announced the “D alpha compiler” in late 2001. That’s still true today. We have a handful of paid positions, but we are still primarily driven by volunteers.

The see-a-problem-and-fix-it philosophy that carried D to where we are today has served us well, and we hope it will continue to do so into the future. But that alone is no longer enough. We are bursting at the seams again, and have been for some time. In the monthly foundation meetings, we’ve been discussing specific issues, both low level and high, and how to solve them. But there’s one thing that’s been missing from the equation: organization.

Razvan Nitu’s position as Pull Request & Issue Manager grew out of an email discussion, prompted by Laeeth Isharc, and was a year in the making. We are grateful for every volunteer who has and continues to make themselves available to review pull requests. Razvan is here not to replace them, but to complement them. They can continue as they have done. What Razvan brings to the mix is organization. He’s there to make sure fewer issues and PRs fall through the cracks, to ensure that as many issues as possible that can be resolved are resolved.

In November, the D Language Foundation and a couple of contributors are meeting with a community member who has graciously volunteered his time and expertise to advise us on how to bring the disparate servers in the D community under Foundation management and multiple admins. The end goals are to eliminate the financial burden on the volunteers who maintain these services and, hopefully, reduce the response time when it comes to solving server-related issues or making changes. In other words, organization.

I’m in the middle of revising the Vision Document that we put together over the summer. I’m not just editing it, though. I’m expanding it. My vision of the vision document has evolved since we first discussed a “goal-oriented task list” in our June meeting. I said at the time that I didn’t “know what the initial version of the final list will look like”. I feel that what we came up with falls short of meeting the need it was intended to fill. Now, I’m pretty sure of what it needs to look like. At the moment, I’m swamped in preparations for DConf Online 2021, so I’ve put the document on the backburner. I plan to pick it up again in early December and present my revisions at the last foundation meeting of the year for approval. If all goes well, it should be published on dlang.org in January. This will be a living document, updated to reflect current priorities as time goes by.

Mathias Lang is working on a proposal to bring organization into even more of our processes. It’s a modified version of the governance proposal he brought to the September foundation meeting, the aim of which is to formalize a core team to oversee the day-to-day guidance and management of the D ecosystem. I hope that this will take what already happens in our monthly meetings to the next level. I see this as a means to establish a framework for creating workgroups that can oversee specific tasks and projects, bringing more opportunities for follow-up and follow-through. It should also help provide guidance and establish priorities (e.g., via revisions to the vision document) so that independent contributors can direct their efforts not just to the issues they care about, but those that are seen as a priority by the core team. (I want to emphasize that this is my personal view. Mathias has yet to complete the proposal. But my view is informed by what we discussed in the September meeting.)

With these and future steps aimed at better organizing our community, we intend to level up our ecosystem: motivate library development, improve the onboarding experience, increase retention, make it easier to contribute, and generally resolve the long-standing issues that tarnish the experience of using the best programming language we know. We ask our current volunteers to keep volunteering, and those who aren’t yet doing so to keep an eye out for the right opportunity to pitch in. Together, we can get to where we all want to go.

SAOC 2021 Projects

Digital Mars D logo

The applications have been reviewed, the results decided, and the applicants notified. Five coders will be participating in the 2021 edition of the Symmetry Autumn of Code, one of whom will be the first to take part in SAOC two times.

Following is a brief introduction to each participant and an equally brief summary of their projects. The project planning phase officially kicks off on September 1st, so any details I could provide from their applications would likely change by the time they finalize their initial milestones with their mentors. If you’re eager for more detail, please hold out a little while longer. The participants will start posting updates in the forums once their projects are underway. Their first updates should include more information.

Rethinking the default class hierarchy

If you followed SAOC 2020, you may recall that Robert Aron was a fourth-year student at University POLITEHNICA of Bucharest who worked on implementing D client libraries for the Google APIs, along with a tool to generate client libraries for said APIs (all of which can be found in his GitHub repositories). He also was a recipient of the final SAOC payment (one of two last year, where usually we have only one) and is owed a free trip to a future real-world DConf.

Robert is now working toward an MSc in Security of Complex Networks at the same university, and he’s back with us for SAOC 2021. His project this time around is a DIP for and implementation of the ProtoObject concept that Eduard Staniloiu described in his DConf 2019 talk. This will set a ProtoObject class as the root class of D’s object hierarchy and the ancestor of the existing Object class. It will allow users to opt-in to features currently provided by default through Object, such as the inclusion of a monitor to support synchronization.

Once again, Robert will be working with Eduard Staniloiu and Razvan Nitu as his mentors.

Welcome back, Robert!

Replace DRuntime hooks with templates

Teodor Dutu is also at university in Bucharest working on a master’s degree in Advanced Cybersecurity. He has experience in C and Java, and it’s the low-level experience he gained working on projects like a file system, a kernel module, and an asynchronous HTTP server that he wants to apply toward improving the D ecosystem. The D language grabbed his interest when he participated in Razvan and Edi’s D Summer School, and he is eager to help out where he can.

To that end, Teodor is entering SAOC to work on a change to DRuntime. Currently, certain operations in user code are rewritten to call functions in the runtime known as runtime hooks (if you’ve ever seen a linker error mentioning something like _d_newArrayT or a symbol with a similar name, that was a runtime hook). There are some significant downsides to this approach, such as code bloat (the entire DRuntime library is linked in when linking statically), negative performance impact (due to the use of TypeInfo to pass runtime information to the hooks), and code that’s hard to maintain (the hooks are inserted at the IR level, a component of the compiler that’s difficult to understand).

Teodor’s plan is to replace each of the runtime hooks with templates. Dan Printzell already did some work on this, and Teodor will be following in his footsteps intending to take it all the way.

Eduard Staniloiu and Razvan Nitu will be Teodor’s mentors.

Implement support for D in LLVM Debugger (LLDB)

Luís Ferreira has extensive experience with C, C++, and D. He has contributed to DMD, DRuntime, and Phobos, and has a WIP implementation of DIP 1029 (Add throw as a Function Attribute) underway.

One of the projects Luís has been working on in his free time is a rewrite of DRuntime’s demangler to avoid exceptions, taken on because of his interest in mangling and demangling. He also has an interest in LLVM. The combination sparked the idea for his SAOC project. His rough goals for the project are to add support to LLDB for demangling D symbols, recognizing D-specific data structures, and parsing D expressions.

Mathias Lang has taken on the role of mentor for this project.

Light Weight DRuntime (LWDR)

Dylan Graham made waves on this blog when he wrote about the custom gearbox controller he built, using D for its firmware. That project led him to a new one: D needs a runtime that is suitable for embedded, Internet of Things, and real-time operating systems. That’s when he started work on LWDR.

You can see from that link that LWDR is not a port of DRuntime, but “a completely new implementation for low-resource environments”, and you’ll find a list of features that are currently supported. For SAOC, Dylan will be working on expanding feature support, shoring up what’s already there and adding new features along the way.

Dylan is a university student in Australia, currently pursuing a Bachelor of Computer Science through Monash University. He’s been programming since he was 11 years old, starting with C on the Arduino Uno and BASIC on the Maximite. His courses have exposed him to several other languages, and he has shown he’s a good hand with D.

His mentor for SAOC 2021 is Adam D. Ruppe.

Improve DUB: solve dependency hell

Ahmet Sait Koçak is a Computer Engineering student from Turkey. He has a strong background in C#, but considers D his second-most comfortable language. Some might be familiar with his work maintaining bindbc-harfbuzz.

For his SAOC project, he made use of our Projects repository and settled on the idea of solving the “dependency hell” problem that can arise when using DUB. Essentially, if library A depends on libraries B and C, which in turn depend on two different versions of library D, dub will error out without any effort to resolve the version conflict.

In reviewing the application, the judges identified some issues with the project as proposed, but it was still accepted with the understanding that Ahmet may need to take a different approach. His project subsequently gained the distinction of being the first SAOC project application discussed in a D Language Foundation meeting. The goal was to determine if there might be another way.

Ahmet’s mentor is Max Haughton, who was present for the meeting. He will be working with Ahmet to investigate the solution arrived at in the meeting and, if that proves infeasible, to move forward with the initial idea. Either way, you’ll hear the details from Ahmet in his weekly forum updates.

Onward!

The SAOC judges (Átila Neves, Robert Schadek, and John Colvin) were impressed with the quality of the applications this year and are eager to see how the projects turn out. Please keep an eye out for the weekly updates that should start arriving in the forums around September 22nd, a week after Milestone 1 begins. This will help you keep abreast of the progress of each project and also provide an opportunity for suggestions that might help our SAOC 2021 coders along their paths.

Milestone 1 kicks off on September 15th, and Milestone 4 will end on January 15th. The D Language Foundation and our sponsors, Symmetry Investments, wish these five coders well in all they do over those four months. Their success is the D community’s success, so we hope everyone will join us in ensuring they have all the support and help they need to get through their four milestones and see this thing through to the end.

D News Roundup

Version 2.097.0 of DMD, the D programming language reference compiler, was released on June 5th in the middle of new GDC and LDC release announcements, while preparations for two major D community events were underway: the Symmetry Autumn of Code 2021 and DConf Online 2021. We’ll cover it all in this post, with a focus first on the events.

Symmetry Autumn of Code 2021

Symmetry Investments logo

As I write, Symmetry Investments employs in the neighborhood of 180 full-time workers and manages over US$8 billion of capital, and they’re always on the lookout for more employees, including programmers to work with D and other languages. They sponsored DConf 2019 in London and have sponsored the annual Symmetry Autumn of Code since 2018, in which a handful of programmers are paid to work for four months on projects of benefit to the D ecosystem.

This year marks the fourth annual SAoC, and we are now accepting applications. Participants will plan four milestones for projects that benefit the D ecosystem and will be expected to work at least 20 hours per week on each milestone. Each participant will be rewarded US$1000 for the successful completion of each of the first three milestones. At the end of the final milestone, the SAoC committee will review the overall progress of each of the remaining participants. One will be rewarded with a final $US1000 payment and a free pass to the next real-world DConf, with reimbursement for travel and lodging. In last year’s event, a second participant was also awarded a fourth US$1000 payment.

Participation in SAoC has led to jobs for some lucky coders and has generally been a valuable learning experience for those who have completed it. Students currently enrolled in graduate or postgraduate university programs will be given priority, but applications are open to all. The application deadline is August 18th. Project ideas can be found in the D community’s projects repository at GitHub. See the Symmetry Autumn of Code page here at the D Blog for all the details on how to apply as a participant or as a mentor.

DConf Online 2021

For the second consecutive year, we were unable to hold a real-world DConf. Last year we launched the first annual DConf Online. And when I say annual, I mean annual! We’re doing it again this year and will continue to do it going forward even after the real-world DConfs are back on.

DConf Online 2021 will take place November 20 and 21 on the D Language Foundation’s YouTube channel. Once again, we’re looking for pre-recorded talks, livestream panels, and livecoding sessions. If you’d like to propose something in one of those categories, the application deadline is September 5. Please visit the DConf Online 2021 homepage for all the details.

And if you haven’t seen them yet, the DConf Online 2020 and DConf Online 2020 Q & A playlists are available on the same channel. You can also find a full list of talks and all the links (talk videos, slides, and Q & A videos) on the DConf Online 2020 homepage.

New compiler releases

D 2.097.0 is live in the latest release of DMD and the beta release of LDC, the LLVM-based D compiler. The new version of GDC also came into the world as part of GCC 11.1 at the end of April.

DMD 2.097.0

Digital Mars D logo

This version of DMD comes with 29 major changes and 144(!) fixed Bugzilla issues courtesy of 54 contributors. Changes include a few deprecations and several improvements to the standard library. Two things stand out:

  • while(auto n = expression) has been on a few wishlists for a while. Now it’s a reality. The same syntax that was already possible with if statements is considered idiomatic in certain circumstances (such as when checking if an item exists in an associative array). Expect the while condition assignment to start popping up in open-source D projects soon.
  • std.sumtype is another wishlist item that is a wish no more. The new SumType is a replacement for std.variant.Algebraic. It’s a discriminated union that makes good use of Design by Introspection with a nice match syntax for those looking for that sort of thing. It’s been quite a while since the last time a new module was added to the D standard library. Many thanks to Paul Backus for putting in the effort to see it through, and a very big Congratulations!

LDC 1.27.0-beta1

LDC logo

On the same day the new DMD was released, the first beta of LDC 1.27.0, which also supports D 2.097.0, was announced in the D forums.

On top of 2.097.0 support, this version of LDC provides greatly improved DLL support on Windows. The prebuilt Windows packages ship with DRuntime and Phobos DLLs. This is big news for D developers on Windows. We’ve long had issues with D DLLs that have prevented heavy use outside of simple interfaces (with APIs exported as extern(C) being the most reliable).

There are some limitations to be aware of, such as the inability to directly access TLS variables across DLL boundaries (though it’s fine with accessor functions). Please see the release page for the details.

Thanks to Martin Kinkelin and all the LDC maintainers and contributors for their continued work on LDC. They aren’t getting paid for this. If you are a happy LDC user or just like the idea of the project, you can support their work by sponsoring Martin Kinkelin on GitHub.

GDC 11.1

In the GCC world, Iain Buclaw continues to make strides on the GDC compiler.

GDC 11.1 still uses the old C++ version of the D frontend, which feature-wise is mostly (see below) at D 2.076.1. There were significant issues in upstream DMD that prevented Iain from making the switch to the D version of the frontend in time to make the release window. He is currently aiming to make the switch in time for GDC 12. As a consolation, this release has support for three BSDs, Mac OS X, and MinGW!

Despite the older frontend, Iain has backported several fixes and optimizations, and even a few features, so it isn’t your grandfather’s D 2.076.1 that GDC supports. For example, the new bottom type that recently made its way through the D Improvement Proposal review process has found its way into this GDC release. See the forum announcement for details of all the new D goodness in GDC 11.1 and Please consider sponsoring his work on GitHub.

One-off donations

If you aren’t up for sponsoring Martin or Iain but would still like to support them financially, you can make one-time donations through the D Language Foundation. You can send money to the D General Fund, the D Open Collective, or to our PayPal account. Whichever method you choose, please be sure to leave a note that the donation is intended for LDC, GDC, or any D project you would like to support. We’ll make sure the appropriate person receives the money.

Other options for supporting the D programming language: visit the D Language Foundation donation page and donate to one of our funds, head to the DLang Swag Emporium and purchase any items that catch your eye (the D Rocket stuff rocks, and DConf Online 2021 swag will be available shortly), or consider using smile.amazon.com and selecting the D Language Foundation as your charity the next time you shop at Amazon.com (we are only available through the .com domain; browser extensions like SmartAmazonSmile for Firefox and AmazonSmileRedirect for Chrome make it easy to do).

Thanks to everyone who has, will, or continues to support the D programming language, either through donations of time or money. We’ve gotten where we are through community effort, and community effort will keep pushing us forward. D rocks!

Interfacing D with C: Strings Part One

Digital Mars D logo

This post is part of an ongoing series on working with both D and C in the same project. The previous two posts looked into interfacing D and C arrays. Here, we focus on a special kind of array: strings. Readers are advised to read Arrays Part One and Arrays Part Two before continuing with this one.

The same but different

D strings and C strings are both implemented as arrays of character types, but they have nothing more in common. Even that one similarity is only superficial. We’ve seen in previous blog posts that D arrays and C arrays are different under the hood: a C array is effectively a pointer to the first element of the array (or, in C parlance, C arrays decay to pointers, except when they don’t); a D dynamic array is a fat pointer, i.e., a length and pointer pair. A D array does not decay to a pointer, i.e., it cannot be implicitly assigned to a pointer or bound to a pointer parameter in an argument list. Example:

extern(C) void metamorphose(int* a, size_t len);

void main() {
    int[] a = [8, 4, 30];
    metamorphose(a, a.length);      // Error - a is not int*
    metamorphose(a.ptr, a.length);  // Okay
}

Beyond that, we’ve got further incompatibilities:

  • each of D’s three string types, string, wstring, and dstring, are encoded as Unicode: UTF-8, UTF-16, and UTF-32 respectively. The C char* can be encoded as UTF-8, but it isn’t required to be. Then there’s the C wchar_t*, which differs in bit size between implementations, never mind encoding.
  • all of D’s string types are dynamic arrays with immutable contents, i.e., string is an alias to immutable(char)[]. C strings are mutable by default.
  • the last character of every C string is required to be the NUL character (the escape character \0, which is encoded as 0 in most character sets); D strings are not required to be NUL-terminated.

It may appear at first blush as if passing D and C strings back and forth can be a major headache. In practice, that isn’t the case at all. In this and subsequent posts, we’ll see how easy it can be. In this post, we start by looking at how we can deal with NUL termination and wrap up by digging deeper into the related topic of how string literals are stored in memory.

NUL termination

Let’s get this out of the way first: when passing a D string to C, the programmer must ensure it is terminated with \0. std.string.toStringz, a simple utility function in the D standard library (Phobos), can be employed for this:

import core.stdc.stdio : puts;
import std.string : toStringz;

void main() {
    string s0 = "Hello C ";
    string s1 = s0 ~ "from D!";
    puts(s1.toStringz());
}

toStringz takes a single argument of type const(char)[] and returns immutable(char)* (there’s more about const vs. immutable in Part Two). The form s1.toStringz, known as UFCS (Uniform Function Call Syntax), is lowered by the compiler into toStringz(s1).

toStringz is the idiomatic approach, but it’s also possible to append "\0" manually. In that case, puts can be supplied with the string’s pointer directly:

import core.stdc.stdio : puts;

void main() {
    string s0 = "Hello C ";
    string s1 = s0 ~ "from D!" ~ "\0";
    puts(s1.ptr);
}

Forgetting to use .ptr will result in a compilation error, but forget to append the "\0" and who knows when someone will catch it (possibly after a crash in production and one of those marathon debugging sessions which can make some programmers wish they had never heard of programming). So prefer toStringz to avoid such headaches.

However, because strings in D are immutable, toStringz does allocate memory from the GC heap. The same is true when manually appending "\0" with the append operator. If there’s a requirement to avoid garbage collection at the point where the C function is called, e.g., in a @nogc function or when -betterC is enabled, it will have to be done in the same manner as in C, e.g., by allocating/reallocating space with malloc/realloc (or some other allocator) and copying the NUL terminator. (Also note that, in some situations, passing pointers to GC-managed memory from D to C can result in unintended consequences. We’ll dig into what that means, and how to avoid it, in Part Two.)

None of this applies when we’re dealing directly with string literals, as they get a bit of special treatment from the compiler that makes puts("Hello D from C!".toStringz) redundant. Let’s see why.

String literals in D are special

D programmers very often find themselves passing string literals to C functions. Walter Bright recognized early on how common this would be and decided that it needed to be just as seamless in D as it is in C. So he implemented string literals in a way that mitigates the two major incompatibilities that arise from NUL terminators and differences in array internals:

  1. D string literals are implicitly NUL-terminated.
  2. D string literals are implicitly convertible to const(char)*.

These two features may seem minor, but they are quite major in terms of convenience. That’s why I didn’t pass a literal to puts in the toStringz example. With a literal, it would look like this:

import core.stdc.stdio : puts;

void main() {
    puts("Hello C from D!");
}

No need for toStringz. No need for manual NUL termination or .ptr. It just works.

I want to emphasize that this only applies to string literals (of type string, wstring, and dstring) and not to string variables; once a string literal is included in an expression, the NUL-termination guarantee goes out the window. Also, no other array literal type is implicitly convertible to a pointer, so the .ptr property must be used to bind them to a pointer function parameter, e.g., `giveMeIntPointer([1, 2, 3].ptr).

But there is a little more to this story.

String literals in memory

Normal array literals will usually trigger a GC allocation (unless the compiler can elide the allocation, such as when assigning the literal to a static array). Let’s do a bit of digging to see what happens with a D string literal:

import std.stdio;

void main() {
    writeln("Where am I?");
}

To make use of a command-line tool particularly convenient for this example, I compiled the above on 64-bit Linux with all three major compilers using the following command lines:

dmd -ofdmd-memloc memloc.d
gdc -o gdc-memloc memloc.d
ldc2 -ofldc-memloc memloc.d

If we were compiling C or C++, we could expect to find string literals in the read-only data segment, .rodata, of the binary. So let’s look there via the readelf command, which allows us to extract specific data from binaries in the elf object file format, to see if the same thing happens with D. The following is abbreviated output for each binary:

readelf -x .rodata ./dmd-memloc | less
Hex dump of section '.rodata':
  0x0008e000 01000200 00000000 00000000 00000000 ................
  0x0008e010 04100000 00000000 6d656d6c 6f630000 ........memloc..
  0x0008e020 57686572 6520616d 20493f00 2f757372 Where am I?./usr
  0x0008e030 2f696e63 6c756465 2f646d64 2f70686f /include/dmd/pho
...

readelf -x .rodata ./gdc-memloc | less
Hex dump of section '.rodata':
  0x00003000 01000200 00000000 57686572 6520616d ........Where am
  0x00003010 20493f00 00000000 2f757372 2f6c6962  I?...../usr/lib
...

readelf -x .rodata ./ldc-memloc | less
Hex dump of section '.rodata':
  0x00001e40 57686572 6520616d 20493f00 00000000 Where am I?.....
  0x00001e50 2f757372 2f6c6962 2f6c6463 2f783836 /usr/lib/ldc/x86

In all three cases, the string is right there in the read-only data segment. The D spec explicitly avoids specifying where a string literal will be stored, but in practice, we can bank on the following: it might be in the binary’s read-only segment, or it might be in the normal data segment, but it won’t trigger a GC allocation, and it won’t be allocated on the stack.

Wherever it is, there’s a positive consequence that we can sometimes take advantage of. Notice in the readelf output that there is a dot (.) immediately following the question mark at the end of each string. That represents the NUL terminator. It is not counted in the string’s .length (so "Where am I?".length is 11 and not 12), but it’s still there. So when we initialize a string variable with a string literal or assign a string literal to a variable, the lack of an allocation also means there’s no copying, which in turn means the variable is pointing to the literal’s location in memory. And that means we can safely do this:

import core.stdc.stdio: puts;

void main() {
    string s = "I'm NUL-terminated.";
    puts(s.ptr);
    s = "And so am I.";
    puts(s.ptr);
}

If you’ve read the GC series on this blog, you are aware that the GC can only have a chance to run a collection if an attempt is made to allocate from the GC heap. More allocations mean a higher chance to trigger a collection and more memory that needs to be scanned when a collection runs. Many applications may never notice, but it’s a good policy to avoid GC allocations when it’s easy to do so. The above is a good example of just that: toStringz allocates, we don’t need it in either call to puts because we can trust that s is NUL-terminated, so we don’t use it.

To be very clear: this is only true for string variables that have been directly initialized with a string literal or assigned one. If the value of the variable was the result of any other operation, then it cannot be considered NUL-terminated. Examples:

string s1 = s ~ "...I'm Unreliable!!";
string s2 = s ~ s1;
string s3 = format("I'm %s!!", "Unreliable");

None of these strings can be considered NUL-terminated. Each case will trigger a GC allocation. The runtime pays no mind to the NUL terminator of any of the literals during the append operations or in the format function, so the programmer can’t trust it will be part of the result. Pass any one of these strings to C without first terminating it and trouble will eventually come knocking.

But hold on…

Given that you’re reading a D blog, you’re probably adventurous or like experimenting. That may lead you to discover another case that looks reliable:

import core.stdc.stdio: puts;

void main() {
    string s = "Am I " ~ "reliable?";
    puts(s.ptr);
}

The above very much looks like appending multiple string literals in an initialization or assignment is just as reliable as using a single string literal. We can strengthen that assumption with the following:

import std.stdio : writeln;

void main() {
    writeln("Am I reliable?".ptr);

    string s = "Am I " ~ "reliable?";
    writeln(s.ptr);
}

writeln is a templated function that recognizes when it’s being given a pointer; rather than treating it as a string and printing what it points to, it prints the pointer’s value. So we can print memory addresses in D without a format string.

Compiling the above, again on 64-bit Linux:

dmd -ofdmd-rely rely.d
gdc -o gdc-rely rely.d
ldc2 -ofldc-rely rely.d

Now let’s execute them all:

./dmd-rely
562363F63010
562363F63030

./gdc-rely
5566145E0008
5566145E0008

./ldc-rely
55C63CFB461C
55C63CFB461C

We see that dmd-rely prints two different addresses, but they’re very close together. Both gdc-rely and ldc-rely print a single address in both cases. And if we make use of readelf as we did with the memloc example above, we’ll find that, in every case, the literals are in the read-only data segment. Case closed!

Well, not so fast.

What’s happening is that all three compilers are performing an optimization known as constant folding. In short, they can recognize when all operands of an append expression are compile-time constants, so they can perform the append at compile-time to produce a single string literal. In this case, the net effect is the same as s = "Am I reliable?". LDC and GDC go further and recognize that the resulting literal is identical to the one used earlier, so they reuse the existing literal’s address (a.k.a. string interning). (Note that DMD also performs string interning, but currently it only kicks in when a string literal appears more than twice.)

To be clear: this only works because all of the operands are string literals. No matter how many string literals are involved in an operation, if only one operand is a variable, then the operation triggers a GC allocation.

Although we see that the result of an append operation involving string literals can be passed directly to C just fine, and we’ve proven that it’s stored in read-only memory alongside its NUL terminator, this is not something we should consider reliable. It’s an optimization that no compiler is required to perform. Though it’s unlikely that any of the three major D compilers will suddenly stop constant folding string literals, a future D compiler could possibly be released without this particular optimization and instead trigger a GC allocation.

In short: rely on this at your own risk.

Addendum: Compile rely.d on Windows with dmd and the binary will yield some very different output:

dmd -m64 -ofwin-rely.exe rely.d
./win-rely
7FF76701D440
7FF76702BB30

There is a much bigger difference in the memory addresses here than in the dmd binary on Linux. We’re dealing with the PE/COFF format in this case, and I’m not familiar with anything similar to readelf for that format on Windows. But I do know a little something about Abner Fog’s objconv utility. Not only does it convert between object file formats, but it can also disassemble them:

objconv -fasm win-rely.obj

This produces a file, win-rely.asm. Open it in a text editor and search for a portion of the string, e.g., "I rel". You’ll find the two entries aren’t too far apart, but one is located in a block of text under this heading:

rdata SEGMENT PARA ‘CONST’ ; section number 4

And the other under this heading:

.data$B SEGMENT PARA ‘DATA’ ; section number 6

In other words, one of them is in the read-only data segment (rdata SEGMENT PARA 'CONST'), and the other is in the regular data segment. This goes back to what I mentioned earlier about the D spec being explicitly silent on where string literals are stored. Regardless, the behavior of the program on Windows is the same as it is on Linux; the second call to puts doesn’t blow anything up because the NUL terminator is still there, one slot past the last character. But it doesn’t change the fact that constant folding of appended string literals is an optimization and only to be relied upon at your own risk.

Conclusion

This post provides all that’s needed for many of the use cases encountered with strings when interacting with C from D, but it’s not the complete picture. In Part Two, we’ll look at how mutability, immutability, and constness come into the picture, how to avoid a potential problem spot that can arise when passing GC-allocated D strings to C, and how to get D strings from C strings. We’ll save encoding for Part Three.

Thanks to Walter Bright, Ali Çehreli, and Iain Buclaw for their valuable feedback on this article.

D 2.096.0 Released and Other News

Digital Mars D logo

The latest version of DMD, the D reference compiler, is now available for download. The changelog notes 17 major changes and 81 resolved Bugzilla issues from 54 contributors. After we get into some notable items from the changelog, we’ll turn our attention to other items of note from the D community: a new release of LDC is right around the corner and one of GDC just beyond the horizon; the Symmetry Autumn of Code wrapped up with a surprise ending; and there are two sometimes forgotten places where anyone can go to find ways to contribute and sharpen their D coding skills.

DMD 2.096.0

This release of DMD is one of those where so many of the improvements are highlight-worthy that it’s difficult to decide which ones to focus on: there are more improvements to the experimental C++ header generation like those I highlighted in the previous release; support for DWARF debug info is surely important to a significant segment of the D community; and changing plain synchronized statements to use runtime-allocated mutexes fixes a critical issue.

The full changelog is there with all the details for anyone who wants them. The features below are a couple that I believe warrant a bit of exposition.

New C-compatible complex types

The complex types cfloat, cdouble, and creal (and their imaginary i-prefixed counterparts) have been a part of D for a very long time, but for much of that time they have been on the block to face future deprecation.

What became clear over time is that they are accompanied by a high maintenance cost, requiring special cases in the frontend to maintain compatibility with other language features. With that and their specialized nature, they have the wrong cost-benefit ratio. The std.complex module introduced the Complex type to shift that cost-benefit ratio in the other direction.

For several reasons, the built-in types have yet to be deprecated, but new D code should be written to use std.complex. One potential problem there is that the library type is not compatible with the C _Complex type, so anyone needing that compatibility has continued to reach for the built-ins.

This release introduces three new aliased types that are automatically configured at compile-time to be ABI compatible with C’s _Complex and should be used in place of the built-ins when interacting with C or C++: c_complex_float, c_complex_double, and c_complex_real. They are declared in the stdc.config module, which must be imported to use them (and which includes other aliased types that have ABI variations between C compilers, such as c_long and c_long_double).

Postblit and copy constructor priority

The postblit constructor has long been the second step in D’s approach to copy constructing struct instances:

  1. “blit” (copy) the fields from the source to the destination
  2. invoke the destination’s postblit constructor

The first step would always take place, the second only if the struct declaration included an implementation of this(this). The idea behind this is that the first step does a shallow copy, and the postblit constructor can take care of any extra work that is required, such as making “deep copies” (copying referenced data) or incrementing a reference count. The postblit constructor does not have access to the source object.

Unfortunately, time and usage uncovered issues with postblit, particularly in how it behaves in the presence of qualifiers like const, immutable, and shared. Changing the behavior of such a long-lived and deeply ingrained feature is problematic due to the impact on existing code. Instead, the approval of DIP 1018 introduced copy constructors to the language.

Now, newly written code should make use of copy constructors rather than postblits, but postblits are not deprecated and remain in the language. Consequently, the two features need to learn to play nice together.

Until now, when both a postblit and a copy constructor were present, priority was given to the postblit. Unfortunately, there was a corner case that slipped by.

The example in the changelog looks like this:

// library code using postblit
struct A
{
    this(this) {}
}

// new code using copy constructor
struct B
{
    A a;
    this(const scope ref B) {}
}

Because A implements a postblit, then given an instance b of B, the postblit of a should be invoked anytime a copy of b is made. Since the user defined no postblit for B, the compiler will generate one that, when invoked, will in turn invoke the postblit of a.

Now that postblit constructors have priority over copy constructors, the programmer who implemented B is expecting its copy constructor to run, but it never will.

With 2.096.0, the above code will result in a deprecation message informing the programmer that a generated postblit will be invoked instead of the copy constructor. The programmer then has three options:

  • disable the postblit with @disable this(this);
  • implement a postblit, which will then have priority over any copy constructors
  • remove all copy constructors from B in preference to the generated postblit

LDC

Up-to-date beta versions of the LLVM-based D compiler, LDC, tend to come not too long after DMD releases. As I write, the LDC maintainer Martin Kinkelin is working toward the next beta release, and that will support D 2.096.0. Keep an eye on the D Announce forum and the LDC release page for news of the release.

GDC

Using the current release of GDC, the D compiler which is distributed as part of the GNU Compiler Collection (GCC), the __VERSION__ constant reports 2.076. LDC and DMD moved on from that version with a D frontend that was ported from C++ to D, but to facilitate bootstrapping, GDC had to stick with the C++ version of the runtime for inclusion into GCC. Maintainer Iain Buclaw has been backporting some fixes and improvements from upstream, so the 2.076 of GDC is no longer at full bug/feature parity with DMD 2.076. Just one example of many, a performance boost to static foreach that was merged into DMD last year is also included in the GDC that shipped with GCC 10.2.1.

The upside of this is that GDC is rock-solid stable. The downside is that code that compiles on the latest DMD and LDC may fail to compile on GDC. But in between backporting bugfixes, his day job, and his normal life, Iain has been expending his free time on replacing the old C++ frontend with the newer D implementation. Given time constraints and the amount of work left to do, version 11 of GDC will remain on D 2.076. Once the GCC feature freeze is lifted in May, he will start laying the foundations for making the switch to the newer frontend in a future GCC release.

Symmetry Autumn of Code 2020

The latest edition of SAOC kicked off in September of 2020. With the sponsorship of Symmetry Investments, four students were to work through four milestones to complete projects that would benefit the D ecosystem. Upon successful completion of each of the first three milestones, each student would receive $1,000. At the end of the fourth milestone, the SAOC judges would award one of them with a final $1,000 payment and a free trip to the next real-world DConf.

All four students completed the first two milestones, but two of them were unable to continue past the third. Milestone 4 ended on January 15th. At the end of the month, the two remaining students submitted their final milestone reports and a summary of their experience working on their projects: what they learned, how reality compared to their expectations, and what their plans are going forward. With those documents and the mentors’ student evaluations in hand, the SAOC judges had to decide which of the two should be awarded the final payment.

Their decision was neither obvious nor easy. Both of the students did outstanding work throughout the event. Their milestone reports sufficiently documented their progress. They kept up with their forum updates as required. Their mentors gave them glowing reviews. There was very little to separate them. In the end, the judges looked at the state of both projects and determined that one would have a broader and more immediate benefit to the D community than the other, and so made a decision.

But they didn’t leave it there. The SAOC judges felt that both students had done so well that they both should be rewarded, but our sponsor had only allocated funding for one reward. The judges devised alternative scenarios and asked our sponsor which of the options they would support. They received an answer, and I informed the students in the last week of February (after they had patiently waited several days beyond our initial deadline).

Robert Aron was selected to receive the final payment and a free trip to the next real-world DConf. His project: implementing D clients for Google APIs. By the end, he had two fully functional libraries for talking to Google Drive and Google Calendar, and an in-progress library for interfacing with Gmail, all of which you can find on GitHub. He also has a work-in-progress template-based Google API generator. He intends to finish both it and the GMail client. He also plans to eventually generate libraries for Google APIs that use RPC.

The “runner-up” is Adela Vais. With Symmetry’s permission, she was offered a choice between a final $1,000 payment and a free trip to the next real-world DConf (I’ll leave it to her to tell folks which she chose). The initial goal of her SAOC project was to implement a D GLR parser for GNU Bison. After seeing the state of the existing D LALR(1) pull parser support in Bison, she shifted her goal to first implement its missing features and add support for a push parser before moving on to the GLR parser. By the end of the event, the push parser was 95% complete, and she intended to take it all the way and then turn to the GLR parser support.

Congratulations to both Robert and Adela! And a special thanks to Laeeth Isharc and Symmetry Investments for providing this opportunity to young programmers every year. Robert and Adela told us they learned more from this experience than they had expected to, and they were obviously proud of the work they had done.

D ecosystem projects and tasks

The DLang Project Idea Repository was created during DConf 2019 in London after a discussion among some of the attendees. Not only is it a solid source of project ideas for potential participants in Google Summer of Code and SAOC applicants, but it’s also useful for anyone looking to make a meaningful contribution to the D community.

The D Ecosystem Task List came about after discussions with representatives of companies using D in production. Any company that is willing to allow one of their employees at least one day per quarter to work on smaller tasks that benefit the D ecosystem can use the repository to get ideas and indicate which task they’re working on. Funkwerk, who have been using D in production since 2008, have been the only ones to take us up on this so far. Their employees have contributed improvements to D-Scanner, dfmt, and dub. We are grateful to them for all they’ve done.

The task list isn’t limited to company employees. It’s a list of broad categories, not specific tasks, for anyone who has an hour or two they’d like to spend on writing D code. So if you are looking for D experience or would simply like to contribute, and you don’t have time for a full-on project, the Ecosystem Task List is a great place to go for ideas. And if you have ideas for other broad task categories that can be added to the list, please submit a pull request!

Symphony of Destruction: Structs, Classes and the GC (Part One)

Digital Mars D logo

This post is part of a broader series on garbage collection in D. The motivation is to explore how destructors and the GC interact. To do that, we first need a bit of background. We do not go into a broader discussion on the ins and outs of object destruction, only what is most relevant to the interaction of destructors and the GC.

I’ve split the discussion into two blog posts. Here in Part One, we look at how deterministic and non-deterministic destruction differ, consider the consequences of having a single destructor for both scenarios, and finally establish two simple guidelines that will help us avoid those consequences. In Part Two, we’ll go further and explore how we can still write solid destructors when circumstances dictate that the guidelines don’t apply.

Deterministic destruction

Destruction is deterministic when it is predictable, meaning the programmer can, simply by following the flow of the code, point out where and when an object’s destructor is invoked. This is possible with struct instances allocated on the stack, as the compiler will insert calls to their destructors at well-defined points for automatic and deterministic destruction.

There are two basic rules for automatic destruction:

  1. The destructors of all stack-allocated structs in a given scope are invoked when the scope exits.
  2. Destructors are invoked in reverse lexical order (i.e., the opposite of the order in which the declarations appear in the source).

With these two rules in mind, we can examine the following example and accurately predict its output.

import std.stdio;
struct Predictable
{
    int number;
    this(int n)
    {
        writeln("Constructor #", n);
        number = n;
    }
    ~this()
    {
        writeln("Destructor #", number);
    }
}

void main()
{
    Predictable s0 = Predictable(0);
    {
        Predictable s1 = Predictable(1);
    }
    Predictable s2 = Predictable(2);
}

We see that both s0 and s2 are directly within the scope of the main function, so their destructors will run when main exits. Given that the declaration of s2 comes after that of s0, the destructor of s2 will run before that of s0.

We also see that s1 is declared in an anonymous inner scope between the declarations of s0 and s2. This scope exits before s2 is constructed, so the destructor of s1 will execute before the constructor of s2.

With that, we can expect the following output:

Constructor #0      // declaration of s0
Constructor #1      // declaration of s1
Destructor #1       // anonymous scope exits, s1 destroyed
Constructor #2      // declaration of s2
Destructor #2       // main exits, s2 then s0 destroyed
Destructor #0

Compiling and executing the example proves us accurate seers.

The programmer can implement deterministic destruction manually, as is necessary when destroying instances allocated on the non-GC heap, e.g., with malloc or std.experimental.allocator. In an earlier post, Go Your Own Way (Part Two: The Heap), I covered how to use std.conv.emplace to allocate instances on the non-GC heap and briefly mentioned that destructors can be invoked manually via destroy. That’s a function template declared in the automatically imported object module so that it’s always available. We won’t retread the allocation discussion, but an example of manual destruction isn’t out of bounds for this post.

In the following example, we’ll reuse the definition of the Predictable struct and a destroyPredictable function to manually invoke the destructors. For completeness, I’ve included functions for allocating and deallocating Predictable instances from the non-GC heap: allocatePredictable and deallocatePredictable. If it isn’t clear to you what these two functions are doing, please read the blog post I mentioned above.

void main()
{
    Predictable* s0 = allocatePredictable(0);
    scope(exit) { destroyPredictable(s0); }
    {
        Predictable* s1 = allocatePredictable(1);
        scope(exit) { destroyPredictable(s1); }
    }
    Predictable* s2 = allocatePredictable(2);
    scope(exit) { destroyPredictable(s2); }
}

void destroyPredictable(Predictable* p)
{
    if(p) {
        destroy(*p);
        deallocatePredictable(p);
    }
}

Predictable* allocatePredictable(int n)
{
    import core.stdc.stdlib : malloc;
    import std.conv : emplace;
    auto p = cast(Predictable*)malloc(Predictable.sizeof);
    return emplace!Predictable(p, n);
}

void deallocatePredictable(Predictable* p)
{
    import core.stdc.stdlib : free;
    free(p);
}

Running this program will result in precisely the same output as the previous example. In the destroyPredictable function, we dereference the struct pointer when calling destroy because there is no overload that takes a pointer. There are specializations for classes, interfaces, and structs passed by reference and a general catch-all that takes all other types by reference. Destructors are invoked on types that have them. Before exiting, the function sets the argument to its default .init value through the reference.

Note that if we were to give destroy a pointer without first dereferencing it, the code would still compile. The pointer would be accepted by reference and simply set to null, the default .init value for pointers, but the struct’s destructor would not be invoked (i.e., the pointer is “destroyed”, not the struct instance).

Inserting writeln(*p) immediately after destroy(*p) should print

Predictable(0)

for each destroyed instance. (The default .init state for a struct in D is the aggregate of the .init property of each of its members; in this case, the sole member, being of type int, has an .init property of 0, so the struct’s default .init state is Predictable(0). This can be changed in the struct definition, e.g., struct Predictable { int id = 1; }.)

destroy is not restricted to instances allocated on the non-GC heap. Any aggregate type instance (struct, class, or interface) is a valid argument no matter where it was allocated.

Non-deterministic destruction

In languages with support for objects and a garbage collector, the responsibility for destroying object instances allocated on the GC heap falls to the GC. This is known as finalization. Before reclaiming an object’s memory, the GC finalizes the object by invoking its finalizer.

Finalization, though convenient, comes with a price. In Java’s particular circumstances, the price was determined to be so high that its maintainers deprecated the Object.finalize method and left a scary warning about its use in the documentation. It’s worth quoting here:

The finalization mechanism is inherently problematic. Finalization can lead to performance issues, deadlocks, and hangs. Errors in finalizers can lead to resource leaks; there is no way to cancel finalization if it is no longer necessary; and no ordering is specified among calls to finalize methods of different objects. Furthermore, there are no guarantees regarding the timing of finalization. The finalize method might be called on a finalizable object only after an indefinite delay, if at all.

Finalization in D isn’t quite the bugbear it is in Java, but we do see a less dramatic warning about it in the D documentation:

The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Furthermore, the order in which the garbage collector calls destructors for unreferenced objects is not specified.

Although there’s no mention of “finalization” or “finalizers” here, that’s precisely what the text is referring to. The core message is the same in both warnings: finalization is non-deterministic and cannot be relied on.

Unlike structs, classes in D are reference types by default. Some consequences: the programmer never has direct access to the underlying class instance; instances declared uninitialized are null by default; the normal use case is to allocate instances via new. When a class is instantiated in D, it is usually going to be managed by the GC and its destructor will serve as a finalizer.

As an experiment, let’s change the definition of struct Predictable in our first example to class Unpredictable and use new to allocate the instances like so:

import std.stdio;
class Unpredictable
{
    int number;
    this(int n)
    {
        writeln("Constructor #", n);
        number = n;
    }
    ~this()
    {
        writeln("Destructor #", number);
    }
}

void main()
{
    Unpredictable s0 = new Unpredictable(0);
    {
        Unpredictable s1 = new Unpredictable(1);
    }
    Unpredictable s2 = new Unpredictable(2);
}

We’ll see that the output is drastically different:

Constructor #0
Constructor #1
Constructor #2
Destructor #0
Destructor #1
Destructor #2

Anyone familiar with the characteristics of the default DRuntime constructor can predict for this very simple program that all the destructors will be run when the GC’s cleanup function is executed as the D runtime shuts down, and that they will be executed in the order in which they were declared (an implementation detail; and note that destruction at shut down can be disabled via a command line argument). But in a more complex program, this ability to predict breaks down. Destructors can be invoked by the GC at almost any time and in any order.

To be clear, the GC will only perform its cleanup duties if and when it finds more memory is needed to fulfill a specific allocation request. In other words, it isn’t constantly running in the background, marking objects unreachable and calling destructors willy nilly. To that extent, we can predict when the GC has the possibility to perform its duties. Beyond that, all bets are off. We cannot predict with accuracy if any destructors will be invoked during any given allocation request or the order in which they will be invoked. This uncertainty has ramifications for how one implements destructors for any GC-managed type.

For starters, destructors of GC-managed objects should never perform any operation that can potentially result in a GC allocation request. Attempting to do so can result in an InvalidMemoryOperationError at run time. I use the word “potentially” because some operations can indirectly cause the error in certain circumstances, but not in others. Some examples: attempting to index an associative array can trigger an attempt to allocate a RangeError if the key is not present; a failed assert will result in allocation of an AssertError; calling any function not annotated with @nogc means GC operations are always possible in the call stack. These and any such operations should be avoided in the destructors of GC-managed objects. (The first seven items on the list of operations disallowed in @nogc functions are collectively a good guide.)

A larger issue is that one cannot rely on any resource still being valid when a destructor is called by the GC. Consider a class that attempts to close a socket handle in its destructor; it’s quite possible that the destructor won’t be called until after the program has already shutdown the network interface. There is no scenario in which the runtime can catch this. In the best case, such circumstances will result in a silent failure, but they could also result in crashes during program shutdown or even sooner.

What it comes down to is that GC-allocated objects should never be used to manage any resource that depends upon deterministic destruction for cleanup.

Designing for destruction

For the D neophyte, it can appear as if destructors in D are useless. Given that both struct and class instances can be allocated from memory that may or may not be managed by the GC, that destructors of GC-managed objects are not guaranteed to run, and that destructors are forbidden to perform GC operations during finalization, how can we ever rely on them?

In practice, it’s not as bad as it may seem. Issues do arise for the unwary, but armed with a basic awareness of the nature of D destructors, it turns out that it’s pretty easy to avoid having problems. This is especially true if the programmer adopts two fairly simple rules.

1. Pretend class destructors don’t exist

Class instances will nearly always be allocated with new. That means their destructors will nearly always be non-deterministic. Much of what one would want to do in a destructor is somehow dependent on program state: either the destructor itself expects a certain state (like writing to a log file that is expected to be open), or the program expects the destructor to have modified the program state in a specific manner (like releasing a resource handle).

Non-deterministic destruction means that all expectations about program state are thrown out the window. That log file might have already been closed, so the message will never be written (I hope it wasn’t important). That system resource handle may never be released until the program ends (I hope that particular resource isn’t scarce). Even if it seems through testing that a class destructor is working the way it’s intended, it’s quite likely down to the fact that the testing has not uncovered the case where it breaks. In a long-running program, that case will inevitably pop up at some point. Have fun debugging when your production game server starts randomly crashing.

So when using classes in D, pretend they have no destructors. Pretend that they are Java classes with a deprecated finalize method.

2. Don’t allocate structs on the GC heap when they have destructors

Since we’re pretending classes have no destructors, then we’re going to turn to structs for all of our destructive needs. Allocating structs as value objects on the stack will cover many use cases, but sometimes we may need to allocate them on the heap. When that situation arises, do not allocate any destructor-bearing struct with new. If we allocate a struct that has a destructor on the GC heap, it completely defeats our purpose of avoiding class destructors in the first place. That destructor we intended to be deterministic is now non-deterministic, so we may as well have just used a class.

As we have seen, struct instances can be allocated on the non-GC heap (e.g., with malloc) and their destructors manually invoked with the destroy function. If we need deterministic destruction and we absolutely must have a heap-allocated struct, then we cannot allocate that struct on the GC heap.

Guidelines schmuidelines

I’m sure someone is reading the above guidelines and thinking, “If I have to pretend that classes have no destructors, then why do classes have destructors?” Well, you don’t have to.

There is no One True Path to follow when deciding if an object should be implemented as a class or struct. Personally, I will always prefer structs over classes, and I will only reach for a class if I need something structs can’t give me easily (like a hierarchy) or efficiently. Other people will consider if the object they need to represent has an identity, e.g., an Actor in a simulation versus the Vertex that defines its 3D coordinates. POD (Plain Old Data) types should always be structs, but beyond that it’s largely a matter of preference.

My two guidelines are based on my experience and that of others with whom I’ve spoken. They are intended to help you keep the full implications of D’s distinction between classes and structs at the forefront of your thoughts when architecting your program. They are not commandments that every D programmer must follow.

Realistically, most D programmers will encounter circumstances at one time or another in which the guidelines do not apply. For example, when mixing GC-managed memory and manually-managed memory in the same program, it’s quite possible for a struct intended for stack use to wind up on the GC heap if the programmer is unaware of the circumstances. And some D programmers will always prefer classes over structs because that’s just the way they want it, and so will simply choose to ignore the guidelines. That’s no problem as long as they fully understand the consequences.

So what does that mean? How do you get over the non-deterministic nature of class destructors if your Actor class absolutely must have a destructor, or if you prefer to always follow The Way of the Class? How do you prevent structs intended for the stack from being GC-allocated? These are things we’ll be looking at in Part Two. See you there.

Thanks to Ali Çehreli and Max Haughton for their feedback. And to Adam D. Ruppe for his conversation on the topic in Discord and the title suggestion (it fits in more nicely with the series than the ‘Appetite For Destruction’ I had intended to go with)

A New Year, A New Release of D

Here in DLang Land we’re beginning the new year with a new release of the D reference compiler (DMD) and a beta release of the popular LLVM-based D compiler (LDC). D 2.095.0 is crammed full of 27 major changes and 78 fixes from 61 contributors. Following are some highlights that I expect some D programmers might find interesting, but please see the changelog for the full rundown. Those more interested in Bugzilla issue numbers can jump straight to the bugfix list

D 2.095.0

Digital Mars D logo

D’s support for other programming languages is important for interacting with existing codebases. C ABI compatibility has been strong from the beginning. Support for Objective-C and C++ came later. Though C++-compatibility is a bear to get right, it keeps improving with every compiler release. This release continues that trend and also enhances Objective-C support. We also see a number of QOL (quality-of-life) improvements throughout the compiler, libraries, and tools. DUB, the D build tool and package manager that ships with the compiler (and is also available separately), especially gets a good bit of love in this release.

C++ header generation

For a little while now, DMD has included experimental support for the generation of C++ header files from D source code, via the -CH command-line option, in order to facilitate calling D libraries from C++. For example, given the following D source file:

cpp-ex.d

extern(C++):
struct A {
    int x;
}

void printA(ref A a) {
    import std.stdio : writeln;
    writeln(a);
}

And the following command line:

dmd -HC cpp-ex.d

The compiler outputs the following to stdout (-HCf to specify a file name, and -HCd a directory):

// Automatically generated by Digital Mars D Compiler

#pragma once

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <math.h>

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template<typename T>
struct _d_dynamicArray
{
    size_t length;
    T *ptr;

    _d_dynamicArray() : length(0), ptr(NULL) { }

    _d_dynamicArray(size_t length_in, T *ptr_in)
        : length(length_in), ptr(ptr_in) { }

    T& operator[](const size_t idx) {
        assert(idx < length);
        return ptr[idx];
    }

    const T& operator[](const size_t idx) const {
        assert(idx < length);
        return ptr[idx];
    }
};
#endif

struct A;

struct A
{
    int32_t x;
    A() :
        x()
    {
    }
};

extern void printA(A& a);

This release brings a number of fixes and improvements to this feature, as can be seen in the changelog. Note that generation of C headers is also supported via -H, -Hf, and -Hd.

Default C++ standard change

Prior to this release, extern(C++) code was guaranteed to link with C++98 binaries out of the box. This is no longer true, and you will need to pass -extern-std=c++98 on the command line to maintain that behavior. The C++11 standard is now the default.

Additionally, the compiler will now accept -extern-std=c++20. In practice, the only effect this has at the moment is to change the compile-time value, __traits(getTargetInfo, "cppStd"), but new types may be added in the future.

Improved Objective-C support

Objective-C compatibility is enhanced in this release with support for Objective-C protocols. This is achieved by repurposing interface in an extern(Objective-C) context. Additionally, the attributes @optional and @selector help get the job done. Read the details and see an example in the changelog.

Improved compile-time feedback

Here’s a QOL issue that really became an annoyance after a deprecation in Phobos, the standard library: when instantiating templates, deprecation messages reported the source location deep inside the library where the deprecated feature was used (e.g., template constraints) and not the user-code instantiation that triggered it. No longer. You’ll now get a template instantiation trace just as you do on errors.

Another QOL feedback issue involved the absence of errors. The compiler would silently allow multiple definitions of identical functions in the same module. The compiler will now raise an error when it encounters this situation. However, multiple declarations are allowed as long as there is at most one definition. For mangling schemes where overloading is not supported (extern(C), extern(Windows), and extern(System)), the compiler will emit a deprecation message.

The mainSourceFile in DUB recipes

The mainSourceFile entry in DUB package recipes was a way to specify a source file containing a main function that should be excluded from unit tests when invoking dub test. However, when setting up other configurations where the file should also not be compiled, or where a different main source file was required, it was necessary to add the file to an excludedSourceFiles entry. This is no longer the case. If a mainSourceFile is specified in any configuration, it will automatically be excluded from other configurations.

Propagating compiler flags to dependencies

Not every existing compiler flag has a corresponding build setting for DUB recipes. The dflags entry allows for such flags to be configured for any project. For example, -fPic, or -preview=in. The catch is, it does not propagate to dependencies. Now, you can explicitly specify compiler flags for dependencies by adding a dflags parameter to any dependency entry in a dub.json recipe. For example:

{
    "name": "example",
    "dependencies": {
        "vibe-d": { "version" : "~>0.9.2", "dflags" : ["-preview=in"] }
    }
}

Unfortunately, it appears the implementation does not work for recipes in SDLang format (dub.sdl), so those of us who prefer that format over JSON will have to wait a bit.

LDC 1.025-beta1

LDC logo

This release of LDC brings the compiler up to date with the D 2.095.0 frontend, with the prebuilt packages based on LLVM v11.0.1. The biggest news in this release looks to be the new -linkonce-templates flag. This experimental feature causes the compiler to emit template symbols into each compilation unit that references them, “with optimizer-discardable linkonce-odr linkage”. The implementation has big wins both in terms of compile times when compiling with optimizations turned on and in cutting down on a class of template-related bugs. See the beta1 release notes for the details.

Happy New Year

On behalf of the D Language Foundation, I wish you all the very best for 2021. As a community, we weren’t affected much by the global pandemic. Sure, we were forced to cancel DConf 2020, but the silver lining is that it also motivated us to finally launch DConf Online in November. We fully intend to make this an annual event alongside of, not in place of, the real-world conference (when physically possible). Other than that, it was business as usual in D Land.

At a personal level, the lives of some in our community were disrupted last year in ways large and small. Please remember that, though the primary object that brings us together is our enthusiasm for the D programming language, we are all still human beings behind our keyboards. The majority of work that gets done in our community is carried out on a volunteer basis. All of us, as the beneficiaries, must never forget that the health and well-being of everyone in our community take top priority over any work we may want or expect to see completed. We encourage everyone to keep an ear open for those who may need to borrow it, and never be afraid to communicate that need when it feels necessary. Sometimes, an open ear can make a very big difference.

Thanks to all of you for your participation in the D community, whether as a user, a contributor, or both. Stay safe, and have a very happy 2021.

DConf Online 2020: How to Participate

DConf Online 2020
As I write, we are a little over 24 hours away from the start of DConf Online 2020, our first online version of DConf. All of the talks for Day One are uploaded, the livestreams are scheduled, and #BeerConf is almost ready to launch.

The details

All of the prerecorded talks will be accessible on our YouTube channel via the DConf Online 2020 playlist (look under the live chat box for the full playlist; you may have to scroll down). Use the live chat to ask questions during the talk. The speaker will be available to provide short answers in the chat box. Longer, more complex answers, and/or additional context, will be provided in the Q & A livestream. The speaker will let you know if he is providing more detail in the livestream. If you don’t want to tab over to the livestream and miss part of the talk, the livestream will be saved to our channel once it ends and you will be able to go back and watch any part of it you may be interested in.

Each day, the Q & A livestream will begin at 13:50 UTC. Each speaker will be in the livestream 5 minutes before his talk begins and will be available to answer questions for the duration of the talk and for up to 15 minutes after. As I said above, you may ask questions in the live chat of the talk, but you may also ask them in the live chat of the livestream (and will likely have to if you have questions after the talk ends). Depending on the amount of time available, the number of questions, and the speaker’s schedule, each speaker may stay longer than 15 minutes after the talk, but is not required to.

Please note that speakers are not expected to answer off-topic questions. It’s entirely up to them if they do so.

I’ll be hosting the livestream throughout each day. I’ll be chatting with the speakers about their talks and D in general to fill in the dead time when no one is asking questions. After the conference is over, I intend to chop up the livestream and upload the Q & A session for each talk as separate videos.

On Day One, we have an Ask us Anything session scheduled with Walter and Átila. This will take place in the Q & A livestream for that day. We also have a livecoding session by Adam Ruppe scheduled. That will take place in a separate livestream when the Day One Q & A livestream ends (links below). Adam will be monitoring the chat as he codes, so he will answer any questions you have.

The livestream links:

BeerConf

From 18:00 UTC November 20, we’ll be running a Jitsi Meet instance for our online version of BeerConf. Everyone is welcome to join, no alcohol required. If you aren’t familiar with BeerConf, you can read a brief description of it on the DConf Online 2020 website. You can also read about it here on the blog.

BeerConf will run all weekend long. You can come and go as you please, during talks, in between talks, day time, night time, anytime!

See this D forum thread for details on how to join.

The prizes

Throughout the event, I’ll be announcing different ways for viewers to win various prizes. We’ll be handing out t-shirts, coffee mugs, and other items from the DLang Swag Emporium (and maybe a DMan shirt or two). I’ll announce the details in the Q & A livestream and, if a talk is ongoing, in the talk’s live chat. Sometimes, winning the prize may involve tweeting, in which case I’ll announce the details on Twitter, so be sure to follow us if you aren’t already.

Additionally, everyone who asks a question to which a speaker provides an answer will be entered into at least two random drawings. There will be one random drawing at the end of each day which includes those eligible on that day. The winners of these drawings will receive a $50 Amazon eGift card. The winner of the two-day drawing will receive a $100 Amazon eGift card. If you win on Day One, you will not be eligible to win on Day Two, but both winners will be eligible to win the two-day drawing.

Funding for all prizes comes from the D Language Foundation General Fund. You can contribute by buying DConf Online 2020 swag or other items from the DLang Swag Emporium, by selecting the D Language Foundation as your preferred AmazonSmile charity and shopping through smile.amazon.com, or by donating directly to the General Fund.

Swag prize winners will be announced in a talk’s live chat and/or the Q & A livestream, depending on the nature of the prize task. For prize tasks that take place on Twitter, winners will not be announced, but will be notified through private message. Amazon eGift card winners will be announced in the livestream. Since YouTube apparently no longer allows private messages, winners on YouTube will be instructed on how to claim their prize when they are announced in the livestream.

Enjoy!

We want to thank all of our speakers for volunteering their time to put together these presentations and making themselves available for Q & A. Without them, this event would not be possible. We hope you enjoy DConf Online 2020!

D 2.094.0, DConf Online Schedule, and SAOC 2020

Digital Mars D logo

The end of September saw a new release of the reference D compiler, DMD 2.094.0, sporting the latest language features. That was followed not long after by a beta release of LDC, the LLVM-based D compiler, based on the same frontend version. The DMD 2.094.1 patch release entered into beta a few days before this post was published. Meanwhile, the first Milestone of the Symmetry Autumn of Code has come to an end, and the DConf Online 2020 schedule has been published.

DMD 2.094.0

This release of DMD incorporates 21 major changes and 119 fixed Bugzilla issues, thanks to the efforts of 49 contributors. Here are some highlights.

This ain’t your grandpa’s in parameter

Back in the days of yore, when DMD was still a pre-1.000 alpha, the D language supported in, out, and inout parameter storage classes. They had the following meanings:

  • in (input), the default, was the bog standard function parameter which is a mutable copy of its argument, i.e., the normal passed-by-value parameter.
  • out (output) parameters were passed by reference and, upon function entry, initialized to the default initializer value for the parameter type (e.g., 0 for int, float.nan for float, etc).
  • inout (input/output) parameters were passed unmodified by reference.

When D2 came along, there were some changes. inout was replaced by the ref keyword and out kept the same meaning, but now there was an explicit restriction that these parameters could only take lvalue references; rvalue references, commonly used in C++, were forbidden as arguments. With in, things became a little muddy. And that brings us to scope parameters, a D2 feature that has evolved over time.

For quite some time, it was not fully implemented and only affected parameters that were delegates: the compiler would only allocate a closure for a scope delegate if it absolutely needed to. The D2 version of in was intended to be equivalent to const scope, but it was never fully implemented and was effectively equivalent to const. Today, scope is intended to be applied to ref or out parameters to prevent them from escaping the function scope, and with DMD 2.092.0, in finally became equivalent to const scope. In DMD 2.094.0, in has been reimagined and extended to solve the rvalue reference issue.

The first thing to know about the new in is that it’s still equivalent to const scope, but now the compiler is free to choose whether to pass an in parameter’s argument by reference or by value. The second thing to know is that in parameters can now take rvalue references. All of this is implemented behind the -preview=in command line switch first introduced in 2.092.0.

Like any preview feature, the new in may or may not make it into the language proper, and if it does it might not be without changes. But for now, it’s there and waiting to be put through its paces. The more people using it, pushing it, and looking for holes, the sooner we can know if this is the in we’re looking for.

Ddoc Markdown support

Quite a while ago, Ddoc, D’s built-in documentation syntax, was enhanced to support some Markdown features. It was hidden beind a -preview switch. Now, that switch is no longer necessary—Ddoc supports Markdown out of the box.

Note that this is not full-on Markdown. For example, although asterisks are supported for italic and bold text, underscores are not. But Markdown-style links, code blocks, inline code, and images are supported. For the details, see the Documentation Generator documentation.

More speed please

Since the release of DMD 2.091.0, the DMD binaries in the Windows release packages are being compiled with LDC. This is a good thing because LDC has a better optimizer than DMD, which makes DMD’s fast compile times even faster. Now, LDC is used to compile binary releases on Linux, OSX, and FreeBSD. As a side effect, there are now no more 32-bit releases for FreeBSD, and additional binary tools are no longer included. If you need them, you can still pick them up from https://digitalmars.com/ or from older DMD releases.

Download

The latest release of DMD is always available for download at https://dlang.org/download.html. The latest Beta or Release Candidate can always be found there as well. You can also find links to download LDC and GDC, the GCC-based D compiler (which is now an official component of GCC). While you’re there, if you enjoy the D programming language, consider leaving a tip to the D Language Foundation.

DConf Online 2020 Schedule

DConf Online 2020 is coming together nicely. Over the two days of November 21 and 22, we have nine prerecorded talks, a livestream Q & A with the language maintainers, and a livecoding session. We’ll also be bringing our annual real-world BeerConf to the virtual world.

The talks

The prerecorded talks will be scheduled to premiere on our YouTube channel at the UTC times listed on the schedule. For the duration of each talk and for 15 minutes after, each speaker will be avalailable in a separate livestream for questions and answers related to the talk. We want to record the questions and answers verbally for posterity. The idea is that viewers of the prerecorded talk can ask questions in the video’s chat, or ask in the livestream chat during or up to 15 minutes after the talk. The speaker will read the questions out loud. Short answers will be provided both verbally and in the chat. Longer answers will be provided verbally only. Commenters asking questions during the talk will be notified in the chat if their questions were selected so that they don’t have to tab out to the Q & A and miss a portion of the talk. They can go back and watch the Q & A video later on our YouTube channel.

The livestream Q & A with the language maintainers will run on our YouTube channel. We’ll be streaming a video conference call and questions will be taken from the livestream chat. During the livestream, some viewers will be invited to join in on the conference call and ask their question directly in order to provide more opportunity for follow up and feedback. Details on how to participate will be released on the day of the livestream.

Throughout the weekend, we’ll be handing out prizes to random viewers. Eligibility details will be provided during the course of the event, so pay attention!

BeerConf

BeerConf is a real-world DConf tradition dating back to the first edition of the conference, though the name didn’t come around until Ethan Watson coined it a few years later. Every year, we designate a gathering spot where DConf attendees can mingle every evening to unwind. The DConf days are where we all wear our D programmer hats and spend our time talking about our favorite programming language, but BeerConf is our chance to be human. We still talk about D, but we also have the opportunity to go beyond the code and get to know each other on a more personal level.

So for DConf Online, we’re taking BeerConf online. On the evening (UTC) of Friday, November 20, we’ll open the BeerConf video conference to any and all, and we’ll leave it open all weekend. Despite the name, no alcohol is required to participate. All you need is an internet connection and a web browser, and you can come and go as you please. We’ve been running monthly BeerConf events since June of this year, so we know that, though it’s not quite the same as being in the same place, it’s still a lot of fun.

We hope to see you November 20–22 in BeerConf and DConf!

Symmetry Autumn of Code

We are currently running our third annual Symmetry Autumn of Code (SAOC). Sponsored by Symmetry Investments, the event provides an opportunity for D programmers to make a little money working on projects aimed at improving the D ecosystem. Particpants each get paid $1000 for the successful completion of each of three milestones. At the end of a fourth milestone, the progress of each participant will be evaluated by the SAOC committee, then one participant will be awarded a final $1000 payment, and receive free registration and reimbursement for transportation and lodging for the next real-world DConf.

We currently have four programmers coding away toward their goals. Milestone 1 has just come to an end and Milestone 2 is set to begin. The participants will soon be sending in their milestone reports, their mentors will send in progress evaluations, and the SAOC Committee will review it all to determine if everyone has put forth the effort required to continue through the event (we expect no issues on that front!). You can follow the progress of each participant, and perhaps provide them with some timely advice, through their weekly updates in the D General Forum. Search for “SAOC2020”.

Symmetry Investments and the D Language Foundation are Hiring

Digital Mars D logo

The D Language Foundation is hiring! Thanks to generous funding from Symmetry Investments, we are looking to fill two (mostly) non-programming positions geared toward improving the D ecosystem. Symmetry is also offering a bounty for a specific improvement to DUB, the D build tool and package manager. And on top of all of that, they are hiring D programmers.

D Pull Request/Issue Manager

A lot of good work goes into the D Programming Language GitHub repositories. Unfortunately, some of that good work sometimes gets left behind. A similar story can be told for our Bugzilla database, where some issues are fixed almost as soon as they’re reported and others fall victim to a lack of attention. Efforts have been made in the past to tidy things up, but without someone in a position to permanently keep at it, it’s a task that is never complete.

The D Language Foundation is looking for one or two motivated individuals to take on that permanent position, get the work done, and keep things running smoothly. Symmetry Investements is generously funding this role with $50,000 per year for one person, or $25,000 per year for each of two.

The ideal candidate is someone who:

  • is familiar with git, GitHub, and Bugzilla;
  • is familiar enough with D to be able to review simple pull requests;
  • is able to recognize when more specialized reviews are required and
  • is able to proofread English text (for reviewing documentation and web site pull requests).

Examples of the role’s responsibilities include:

  • ensuring all pull requests follow procedure;
  • reviewing simple pull requests;
  • finding appropriate reviewers for more complex pull requests;
  • ensuring that pull requests are reviewed in a timely manner;
  • reviving stale pull requests;
  • coordinating between pull request submitters and reviewers to prevent pull requests from going stale;
  • closing pull requests that are no longer valid;
  • identifying Bugzilla issues that are duplicates or invalid;
  • identifying Bugzilla issues that are candidates for bounties;
  • publicizing Bugzilla issues in need of a champion and
  • other related tasks.

We are hoping to hire from within the D community, though we will accept queries from anyone. If you are interested in taking on the role, please send your resume to social@dlang.org. You should also indicate if you are willing to do the job full time (just you) or part time (share the responsibilities with someone else).

Community Relations Assistant

I’ve been working with the D Language Foundation for the past three years. Much of what I do falls loosely in the category of Community Relations. These days, I’m in need of an assistant. Symmetry Investments is providing $600 per month for the role.

The job will involve a number of different activities as the need arises, such as:

  • seeking out guest authors and projects to highlight for the D Blog;
  • monitoring our social media accounts;
  • sending out messages from the D Language Foundation (such as thank you notes to new donors);
  • assisting with maintenance of pages at dlang.org and dconf.org;
  • assisting with the organization of events like DConf and SAOC and
  • any odd jobs that pop up now and again.

If you have good communication skills, an optimistic disposition, and enthusiasm for the D Programming Language, I’d like to talk to you. I don’t need a resume. Instead, please send an email to social@dlang.org explaining why you’re the right person for the job.

DUB Bounty

Symmetry Investments logoDUB has become a critical component in the D ecosystem. A significant number of projects depend on it and we need it to be able to meet a wide range of project needs. To that end, there are certainly improvements to be made. One such is in how DUB determines which of a project’s source files are in need of recompilation. Currently, DUB follows in the tradition of the venerable make and uses timestamp comparisons to make that determination.

A new generation of version control and build tools (git, buck, bazel, scons, waf, plz, and more) rely on file checksums to assess the need for action. This is a much more robust approach because it detects actual changes in file content. Timestamps can change in any number of irrelevant ways. Robustness is important if one is to depend on a build working properly even when files are moved, copied, and shared across people, machines, and teams. As hashes are fast to compute on modern hardware, the impact on speed is very low.

Symmetry Investments is offering a $2,000 bounty to the programmer who either converts DUB’s use of timestamp-dependent builds to use SHA-1 hashing throughout, or implements it as a global option to preserve the current behavior.

For inspiration, see this clip from Linus Torvald’s Google talk, and the article Build-Systems Should Use Hashes Over Timestamps. Note that shasum $(git ls-files) in Phobos takes 0.05 seconds on a warm SSD drive in a desktop machine.

Anyone interested in taking on this bounty should contact social@dlang.org beforehand. Anyone interested in contributing to the bounty amount can do so via the bounty card Support for Hash-Based Recompilation in DUB at our Task Bounties page.