The D Language Foundation’s July 2025 monthly meeting took place on Friday the 11th and lasted about an hour. Walter was unable to attend.

## The Attendees

The following people attended:

* Rikki Cattermole
* Jonathan M. Davis
* Timon Gehr
* Dennis Korpel
* Átila Neves
* Razvan Nitu
* Vladimir Panteleev
* Mike Parker
* Steven Schveighoffer
* Nicholas Wilson

## The Summary

### New release process

Dennis said the situation with master vs. stable branches creates friction in several ways. There were constant PR debates over which branch to target. Rebasing was kind of tricky, so it often went wrong and made history messy. It also meant that once we commited to merging master into stable, we couldn't make anymore patch releases. For example, once he tagged 2.112, he couldn't go back and tag 2.111.1.

He had looked into how other open source projects handled it and decided on a proposal for an alternative branching system where all contributions would just go into master. Maintainers or GitHub Actions could then backport into release branches based on labels. So we'd create a branch for 2.112, then every fix that needed to go there after the feature freeze could be backported from master.

This wouldn't automatically prevent merge conflicts, but would make it less likely that stable and master would diverge if, for example, we forgot to merge stable back into master.

He had put all the details in a document and wanted to get feedback in the forums, but first wanted to check with us to see if there was anything else he needed to account for. This was going to affect a bunch of things and he didn't want to miss anything.

Rikki had two suggestions. First, we should reserve point releases for LTS versions only. Second, we should start squashing commits by default. Dennis noted we already had the option to squash commits. Rikki said there was a setting to make it the default. Dennis had no problem changing that.

Jonathan asked what the specific benefit of making it the default would be. Rikki said it was mostly for convenience. When people had multiple commits, the reviewer didn't have to worry about squashing them.

Nicholas said he did that already anyway. But if the PR contained orthoganol sets of stuff, he'd leave the commits as-is and do a rebase. It didn't bother him either way, but he suggested checking with Martin and Iain.

Dennis then raised the question of cadence. His proposal suggested a minor release every three months and an LTS release every year. The LTS would be restricted to critical fixes, like when macOS broke everything, or wrong code fixes. There had been some requests for an LTS, and though he thought all the betas and release candidates we had were nice, very few people actually tested them. All the regression reports tended to come in after the release was pushed to the Linux packages. We always released and then saw the consequences.

Timon thought we should keep in mind all the heavy refactoring going on over the past year or so. That would impact this negatively if it continued at that pace, so maybe there should be some coordination there.

Dennis said that was why he was talking about limiting LTS to critical fixes. Maintaining all the stable bug fixes would be too much work. In certain cases, like if an industry user wanted a specific non-critical bug fix, but didn't want to go through the upgrade process, then we could add it to the LTS. Rikki agreed.

Dennis had hoped Martin or Iain could weigh in durin the meeting, but it was a holiday week for them. He said he’d post the proposal to the forums to get more feedback.

__UPDATE__: He posted [his request for feedback](https://forum.dlang.org/post/[email protected]) on July 15th.

### zlib dependency problems

Steve said he'd been working on the Rayib D binding. As part of that, he maintained an install script that unpacked the correct prebuilt Raylib library so users didn't have to guess what to download. He'd gotten a few reports from people trying it out saying the install script didn't work. Usually, it was a link error against libz. We were missing the `inflateEnd` symbol or something like that. This always puzzled him because we had libz compiled into Phobos.

Luna, who was doing some work on macOS, gave him a binary to try for something she was working on and it had a missing libz dependency. She told him she had to have a special libz dependency because of the way the compiler worked, but he thought that didn't make a lot of sense.

He'd also learned that Vladimir's ae library had an extra libz dependency if you included the compresison stuff.

The source of this problem was that Linux systems had a policy of stripping out libz dependencies from Phobos becaue they already had a libz, and you should be depending on that instead. As such, they'd been mucking with the build so that it didn't include the libz C code that we compiled and instead linked against the system libz library.

This was okay as long as you were using Phobos symbols that dependend on libz. With dynamic linking, you depended on Phobos, Phobos depended on libz, and it just worked. But if you used any of those zlib C functions directly, which he was doing in his install script via iopipe, then it wouldn't link. You ended up with the situation that if you installed the blessed compiler from the operating system, it didn't build code that normally built with our compiler releases.

He wanted to try to figure out what to do about it. His first thought was that we should make it standard practice to link against libz, since Phobos linked against it anyway. We should also consider removing it completely from Phobos v3. It had been there since D1, and it was the only C package we included like that. We had `std.net.curl`, but curl was loaded dynamically.

He brought this up because it had been bothering him for two years and he'd had no idea where people were finding a compiler that didn't have the proper build. It turned out it was just `apt install ldc`.

Átila agreed in principle that we should be linking with whatever was on the system. Steve asked if we should be telling these package maintainers to just add `-lz` into the compiler configuration? He thought that was the right answer. Átila wondered what Martin and Walter would say about it, but said it all made sense in principle.

Jonathan said that if there was no technical reason why we needed to include it in Phobos instead of linking externally, then we should just switch to using `-lz`. I noted that we couldn't expect it to be installed on Windows.

Rikki said that on POSIX, we definitely should not be shipping our own copy of zlib. On Windows, the situation was different. Jonathan thought that might be why Walter had included it, since he'd been working on Windows initially.

Steve said he’d see what he could do on the packaging side. Nicholas shuggested that Adam Wilson should be looped in on this for the Phobos v3 stuff.

### Vladimir’s industry feedback

Vladimir had been unable to join us for the quarterly meeting the week before, so he said he effectively had “two meetings worth” of feedback for us.

He described his current work as building a CRM-like system, including writing a GraphQL client library. That was a lot of business logic: rules, reporting, numbers, and all that stuff.

__The good__

He gave named arguments a huge thumbs up, saying they were a major boon for readability in business logic for both structs and functions. It replaced the builder pattern; that was gone. It replaced the flag template from `std.typecons`; that was gone. It was very nice, very readable. It was a huge thing he wished he could have had sooner, but he was glad it was there now.

He was thankful for the work to keep compilation times low, and especially that we had better tooling now. Using `-ftimetrace` on DMD was very cool. He’d used it on a few occasions to track down the root cause of some issues, including one dealing with a GraphQL-generated D file that was a megabyte in size. They'd run into some problems, but he could narrow them down so the compilation times were still very reasonable.

He'd seen some issues with error message locations. They may seem trivial, like the caret being one character to the left of where it should be, but they were very helpful and integrated into the editor. So if you were making a big refactoring, you could just jump to the next error and fix it, jump to the next and fix it. He was thankful those had been getting fixed.

Finally, he said he’d been using dub, and though historically he hadn’t been a dub user, he could see visible progress and found it much less annoying than it was years ago. He was thankful for that.

__The bad__

About once a month, he hit an issue that completely blocked him. Sometimes it was an ICE, sometimes a linker error. In a large application that was generating a lot of code, even understanding the problem could be time-consuming. He said it usually took him a day to either reduce it or even understand the cause and find a workaround.

He said he used to try reporting these bugs. He'd even created Dustmite to make reporting them more efficient. But experience had shown that if these bugs were easy to fix, they likely would have been fixed, so he expected they weren't easy to fix.

Producing a clean, reproducible test case, especially for a project that wasn't open source, was a serious time investment. The cost/benefit just didn't work out when he had to justify the time to the people paying for it, so he hadn't been doing it every time.

He noted that his team had switched to using LDC exclusively because that was what was used in production. He wasn't using DMD at all. One problem was that DMD's memory usage was higher than LDC's, so it ran out of memory compiling a program where LDC didn't. Second, there were some DMD-specific ICEs in its backend that he assumed didn't exist in LDC.

He'd had trouble with recursive attribute inference and assumed it was a familiar problem to the people in the meeting. (__NOTE__: It was. Martin has brought that up on several occasions.) Things either didn't compile or didn't link because the mangling was different. These were a big pain to deal with.

He'd been able to deal with what he'd found so far, but there was also the effect that he was being asked how he spent his time. So when he occasionally reported that he'd spent a day working around a problem that came from the D compiler, he'd get questions about why they were using D when developers in the same organziation working with a different language didn't run into stability issues.

Of course, the time saved from using D was less visible and less quantifiable. But these problems that he occasionally ran into were seen as a risk. So the sentiment about using D had been lukewarm in his corner of the organization. There was some movement toward considering other languages, TypeScript in particular since they were already using it on the front end.

__Exception types__

Vladimir had a wish list item, which he explicitly noted Walter would disagree with were he present.

Typically, when we talked about unexpected failures, like assertion failures, the argument was generally that the program had entered an invalid state and could not continue. He could agree with that for the typical definition of the program, but--

Rikki interrupted to say that this had been his first agenda item, but we'd put it aside given that Walter was absent. Vladimir said he'd keep it short in that case.

Essentially, he would like to have an error boundary so that we could somehow just assume that the program didn't have a global state. However, there were tasks that had their own state, and it was okay to terminate those tasks. So we could have an error boundary say, okay, an assertion was thrown, now throw away that fiber or whatever. Then we return an error page which we assume will work even if an assertion has been thrown.

There were only very few actually unrecoverable errors when looking at it from this perspective. And if the GC's state was corrupted, we had an optional exception for one and another exception type for the other.

Átila didn't think that was true. If an assertion failed, you didn't actually know what happened. It could be anything, from the things Vladimir had just said to cosmic rays through your hard drive.

Vladimir agreed, and said that was a problem. Without further information, he would just like to be able to assume that it was something local and could be handled. Átila said it couldn't be handled by definition.

Vladimir argued that definition wasn’t useful and should be changed. C#, Java, and pretty much every modern language could do it. D could not. Jonathan noted that bounds-checking errors were in the same boat.

He said there were people who argued that unwinding was just for your ability to report and you weren't going to try to recover, and people who argued that it was isolated enough at least some of the time that it was worth attempting to recover even if youd didn't necessarily want to do so in all cases.

Ultimately, if the errors did all the unwinding and cleanup correctly, the developer could choose to how to handle it. Right now, we had this weird halfway thing where Walter and several others argued it should just be killed. But we had this whole stack unwinding mechanism in place, which was just dumb if we weren't going to unwind properly. There had been arguments for making it configurable.

Rikki said it got worse. In 2018, the unwinding logic was changed in a way that prevented all finally statements from running all cleanup. It was an optimization the front end shouldn't be doing. He was going to recommend reverting that and making Walter's approach opt-in.

Átila said one of the big problems with that was that asserts were used by default in unit tests. How could you write a framework without catching `AssertError`? He thought out of bounds errors were a bad example, as you should probably always crash immediately in that case.

Rikki said those weren't the hard cases. The hard case was contracts. Átila agreed, saying they could be turned off.

Jonathan said that was the same with assertions in general. The biggest problem with contracts was inheritance because of all the muck it did to expand or tighten contracts. The language was forced to catch those assertions and then potentially not stop the program because, oh, this one was relaxed so we weren't supposed to skip it. So you couldn't really skip cleanup with `AssertErrors` at a minimum regardless of the rest.

He said we could make it configurable. Átila suggested we could make asserts and contracts not use `AssertError`. Jonathan said stuff relied on it working that way. Rikki said the problem wasn't that they threw `AssertError`, it was that they threw `Error`.

Átila's point was that he saw no reason we couldn't change them to use `Exception` instead of `Error`. Rikki said that as long as it was throwing `Error`, we weren't going to fix it without breaking the language, and that was worse than breaking user code. I noted that it couldn't be fixed without convincing Walter anyway.

Átila thought there was a conflation there, with asserts throwing `AssertError`. Normally, if you asserted something, it should never happen. If it did, then it should crash now because who knew how you got to that state. The problem was that we were also using them for unit tests and contracts. Rikki agreed and said we were over using asserts.

Timon said that an out of bounds error could just be a small off-by-one in a non-critical component. Getting an out-of-bounds error meant it had been caught. You could always argue that maybe the process had been compromised, but then maybe the assertion only passed because the process had been compromised. There was no information either way.

Átila asked how you'd be getting off-by-one errors in the language. How would you get there? Timon said maybe an intern wrote the non-ciritcal component. It was given to the intern because it was non-critical. And now it's taken down production. You could argue that all the requests should just run in a separate process on CGI. But he assumed that for some people, that wasn't the most performant option.

Other languages allowed you to do this. So basically you had the option of not using D, then you could get good performance without risking production going down for some stupid issue. Or you could use D and then you had to choose between isolating every request in its own process and risking that production would go down. And when people asked why, you'd have to say it was because you used D.

Átila thought the bounds thing was important. The most likely thing that happened was that the process was compromised. Again, how did you get there?

Nicholas noted that unit tests used a different assert than the regular assert, so we could configure that.

Jonathan said there were plenty of cases where he'd explicitly thrown `AssertError` all over the place because that was what you had to do as soon as you created a helper. Changing that so it wouldn't use `AssertError` would break things.

Rikki said that with assert, it shouldn't matter which function it was. It could be in a unit test or not. It was still going to work with the unit test runner as far as he was aware. It was all configurable, but it was just an assert. There shouldn't be any super codegen for unit tests.

Átila said he could argue that asserts in a unit test block should throw a `UnitTestException` and asserts in a contract should throw a `ContractException` instead. We knew so much about where exactly these things were, so should we overload assert? He didn't know.

At that point, I stepped in and said we weren’t going to resolve it in the remaining time, and suggested we schedule a dedicated meeting rather than trying to cram it into a monthly. We settled on Friday, July 25th, and I said I’d mark the calendar and add Vladimir to the invite list.

__UPDATE__: In the subsequent meeting, Walter approved the addition of a compiler switch to configure whether a thrown `Error` gets cleaned up in a finally block.

__Null pointer exceptions__

Vladimir said it would be nice if we had software null pointer checking that threw a normal exception instead of segfaulting. It would be okay if it were only in safe code. Null pointer exceptins were a solved problem in other languages and they were a pain in the behind to deal with in D.

Átila asked why they were a pain. Vladmir said you couldn't easily distinguish between a segfault from a null pointer or some kind of crazy memory corruption. You wanted to be able to catch one and let the other crash.

Átila wanted both to crash. And when that happened, which was rare, he just fired up gdb on the last core dump. Vladimir said that gdb didn't run in containers in production. Átila understood.

Rikki said he'd like some opt-in read barriers for null deref checks and throw an error there, or have a handler in DRuntime, whatever. This was prompted by segfaults he was getting for DMD in the CI that he couldn't debug.

Átila noted that would have performance problems. Running code on every deref woult be expensive. Rikki said it was no different than a bounds check.

Jonathan said we'd have to test it. OpenD had apparently implemented this, but he didn't know what kind of performance hit they'd seen. The only way to know exactly what would happen would be to implement it.

Rikki reiterated that he was suggesting this as opt-in. The point was to be able to turn it on for DMD in the CI, and users could turn it on for their stuff when they wanted.

Nicholas said that `etc.linux.memoryerror` could catch null dererences. Vladimir said it didn't work on LDC. Nicholas was surprised and said we should bring this up with Martin.

Dennis noted that `memoryerror` was Linux-only. He said there was also an alternative assertion handler which worked with both null dereference and stack overflow, but it wasn't catchable; it would print a stack trace and abort. It wasn't enabled by default because of limitations related to fibers, threads, and debug.

We talked a little about what the implementation of the null checks might look like. Then Timon pointed out that one risk of running optional options in CI that weren't running by default was that you might not catch an issue that only happened if the flag was off. Rikki had no concerns about it as long as it was easy to turn on temporarily while debugging.

## Memset hooks

Rikki said the memset hooks were not templated, and LDC had more of them than DMD, with the result that BetterC was broken.

Nicholas said he could look into that. He asked why LDC was doing that instead of using LLVM intrinsics. Rikki said they were type-specific memsets, usually for initializtion, and he wasn’t sure why.

Nicholas said he remembered seeing them somewhere. We could definitely template them.

Rikki added that the bug reports were for both LDC and DMD, but he didn't have a link. It was something that had come up in Discord.

Nicholas suggested it might be something for the GSOC student who was working on the templated runtime hooks project. Razvan said he would pass it on.

### Getting feedback from industry users

Rikki thought we should have some way to get feedback from industry users regarding language and compiler changes. Not all of them paid attention to the forums, GitHub discussions, etc.

Átila noted that we had quarterly meetings with industry reps for exactly that reason. Anyone who wanted to bring us feedback could attend. Rikki asked if we talked about planned features there. Átila said we sometimes did.

The discussion went around for a while, talking about the various ways we could get feedback from people who didn't pay attention to any of our normal methods of communication, and whether a heavily moderated 'Production' forum or mailing list would be helpful. Ultimately, Jonathan said the root of the issue was that anyone who wasn't paying attention to the existing sources of communication was unlikely to pay attention to anything new we came up with.

Átila noted how sometimes people would show up at DConf or in the forums and tell us they'd been using D in their projects for years and we'd never heard of them.

### Conclusion

Our next monthly meeting was on August 8th.

If you have something you'd like to discuss with us in one of our monthly meetings, feel free to reach out and let me know.

Reply via email to