The D Language Foundation's August 2025 monthly meeting took
place on Thursday, the 7th, and lasted about an hour and twenty
minutes.
## The Attendees
The following people attended:
* Rikki Cattermole
* Jonathan M. Davis
* Martin Kinkelin
* Dennis Korpel
* Mathias Lang
* Átila Neves
* Razvan Nitu
* Mike Parker
* Nicholas Wilson
## The Summary
Before we got underway, I had some admin details to discuss
related to SAOC projects and mentors, and reviewing DConf slides.
Once that was done, I noted that I'd only received two agenda
items, one from Nicholas and one from Walter, then I handed it
off to Nicholas.
### A new undeaD tag
Nicholas reported that Nick Treleaven needed a new release of
undeaD to fix something in Phobos. He wasn't entirely clear on
the process for undeaD releases.
I asked if undeaD even had releases. Jonathan thought the whole
point of undeaD was just that it was there and we weren't really
doing anything with it anymore.
I checked, and the last release tag was 1.1.8, created three
years ago by Petar Kirov. Mathias volunteered to create version
1.2.0 and call it a day, assuming the CI passed first. Nicholas
said he was happy to do it if nobody else did, though he wasn't
sure he had the privileges yet. I told him he should have full
privileges as the PR & Issue Manager and would make sure he had
them if he didn't.
__UPDATE__: _Mathias tagged 1.2.0, and Nicholas now has all the
privileges._
### Merging the Bitfields DIP
Walter said [the Bitfields
DIP](https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1051.md) had been approved, and there was a PR to pull it. The bugs that mattered most had been fixed, so it was time to merge it and get it over with.
Nicholas noted there were some outstanding library bugs related
to [printing bitfields with
writeln](https://github.com/dlang/phobos/issues/10840), but in
terms of language features, there was nothing blocking the merge.
Dennis disagreed. He thought it would be nice to fix the writeln
issue first. The situation to avoid was people reading that
bitfields worked, trying them out, then having writeln break and
thinking the feature was half-baked. That was an old complaint
about D, and he thought we should take it seriously. It was one
of the most basic things. If that didn't work, people would
consider the feature completely broken from the get-go. Átila
agreed.
Walter thought it was strange that it wouldn't work because the
result was an integer. Why couldn't writeln handle an integer?
Dennis explained that writeln saw the fields were overlapping,
like a union, and didn't know how to print unions because it
couldn't know which union member was active. In existing code
without special checking, it would see the fields like a union of
every bitfield.
Jonathan said it sounded like writeln had protection against
reading all the values in a union because that was bad news. When
it detected an overlap, it barfed. That same checking would
detect bitfields and barf for the same reason. Presumably,
whatever check was there for overlap would have to be altered to
recognize bitfields and print them properly.
Walter pointed out that you didn't actually pass a bitfield
anywhere because the compiler converted it to an integer value.
Jonathan said writeln had to do some level of introspection on
all the members. It sounded like it was checking offsets to make
sure there was no overlap because it didn't want to read multiple
members from a union. Bitfields would look the same even though
they weren't.
Jonathan thought it was probably an easy fix if you could find
the piece of code doing it. One of us would just have to take the
time to track it down and fix it. Dennis noted that Iain had
already posted a diff with a lazy fix with the caveat that it was
incomplete because it didn't account for every case.
Dennis thought a more general problem was that whenever you
wanted to generically iterate over the fields of a struct, and
you just iterated over its `.tupleof`, you wanted to assume that
it was safe to access every member. Currently, any code doing
that had to take special consideration for unions, because they
appeared as just members of the tuple. If you didn't check
`.offsetof` and `.sizeof`, you'd get weird things with overlap.
He often wrote that sort of code, assuming no unions.
He wondered if the compiler or library could provide a kind of
`.tupleof` that merged all overlaps into one special thing.
Walter said there were attributes to pick apart a bitfield.
Dennis argued that every call site would have to remember that
and take it into account that when just iterating over a
`.tupleof` you had to check the offset and the bitfields offset
and the `.sizeof`... You had to do this whole algebra to figure
out what you were actually looking at. Walter said he understood
the problem now.
Rikki proposed three new traits: one to get all methods, a second
to get all fields that didn't overlap, and a third to get all
fields that did overlap. Dennis asked why those were needed.
Rikki said it was all about taking an existing type and getting
only what you needed out of it. Right now, it was more expensive
than it needed to be. If you only needed a few fields, you could
just get those and do it more cheaply than now. That would solve
this problem because you could just ask for only the fields that
didn't overlap. No runtime checking or anything.
Dennis said that sometimes you did want everything. Like, writeln
wanted to go over all the normal and overlapping members in one
go. If you had two traits, that would be two for loops, and you'd
have to position things, try to figure out where the overlapped
fields were in relation to the normal ones.
Jonathan expanded on that, saying that `.tupleof` gave them in
order. If you had to have separate ones, then they wouldn't be in
order in the same way. He didn't know what a good solution would
be.
Walter thought maybe we could just make it a compile-time error
to call writeln on a union. Átila said that was probably too
draconian. Rikki noted that writeln had a fallback for unions,
where it just printed all the fields. The problem was that the
fallback didn't understand bitfields.
Rikki suggested we put them order-wise in an alias sequence of
alias sequences. Nicholas said you'd still have to intercalate
them.
Jonathan said the alias sequences would all just flatten out. You
couldn't have any depth to them. And arrays wouldn't work because
you needed them to be aliases. Rikki disagreed, saying they would
be strings, not symbols. Jonathan said that `.tupleof` gave you
aliases. `allMembers` gave you strings. Rikki said this would
replace `allMembers`. `.tupleof` was just an alternative way to
do it.
Jonathan said the issue here was `.tupleof`, not `allMembers`.
You already had to do all kinds of funky things with members. You
had to filter out all the different possibilities, like static
this and that, enum, whatever. `.tupleof` just gave you what was
directly in the struct. That was mostly simple, but unions
screwed with it because that gave you overlapping fields where
you might need to ignore some of them depending on the context,
or you might actually need to see all of them to, for example,
list them all out, but still be aware of the fact that they were
overlapping. With bitfields, you potentially didn't care, as they
were actually separate even if they overlapped. He didn't know
how easy it would be to abstract that in a way that you just
didn't care.
There was a bit more back and forth about anonymous unions,
writeln's implementation, potential fixes, etc. Ultimately, given
that Iain's fix was there, the consensus was to incorporate it
even if it wasn't perfect.
Walter said Adam would be rewriting much of this stuff for Phobos
v3 anyway. Jonathan said we were nowhere near the point where we
were ready to rewrite `writeln`, but it would have to be fixed at
some point.
I asked if Walter wanted to wait on merging the bitfields PR. He
said yes, at least until the writeln issue was fixed. There was
no big rush. Dennis said there were two PRs needed: one for
Phobos and one for DRuntime. Both of them would benefit from
having the writeln issue resolved. Walter agreed to put the merge
on hold until then.
__UPDATE__: _The PR was eventually merged and bitfields were
released in 2.112._
### Editions
I opened the floor to anyone with anything else to discuss.
Razvan asked what the situation with editions was looking like.
He'd understood that Rikki had been working on the
implementation, but had learned that wasn't the case.
Walter said Dennis had done some work to detect the edition in
the module declaration, then had a couple of cases where it
actually tested the edition. That seemed to be working fine.
Walter had made a change to pick the edition off the command line
and some other stuff related to that. The only thing left to
implement was the edition checks for individual features.
I asked if the DIP was ready to be merged. Átila said he'd
submitted the PR a couple of weeks ago. I said I'd take a look at
it over the weekend.
Walter said we should decide if the first edition was going to be
'2024' or '2025'. Átila did think that was important right now.
Razvan asked what the next step was. I said it was on me now. I'd
go through the DIP to revise it. Any major changes would need
Átila's approval as the author. Then once that was done, I'd
submit it to Walter, and it would be on him to give the thumbs up.
Walter said once it was approved, we could start getting rid of
crap in the language. Or at least declare some of it obsolete.
Átila agreed.
Walter said he'd love to have the docs blocking out obsolete
stuff and showing what was enabled in each edition. Razvan didn't
think things would get simpler from a complexity perspective.
Walter said they would from language point of view. Getting rid
of cruft was of major importance. Maybe we should have separate
doc pages for old editions.
Jonathan said there were multiple ways to run into it, depending
on what you were looking at. In some cases, projects like this
would have separate pages: a current one and then different ones
for older versions. In some cases, they'd say 'this changed in
this version or that version' throughout the docs.
I suggested we have a page for each edition listing the changes
it brings. Then, in the rest of the main spec, we could have
links to the edition pages where relevant. So if there were any
changes to a specific feature, or if a feature were added in an
edition, that edition page would be linked at that point in the
docs.
Walter said that would work, but obsolete features shouldn't be
in the main documentation so that users wouldn't be tempted to
use them. He thought that would simplify the spec.
Rikki said that, as a simple solution, we could use the HTML tag
that can hide or show a block. We could chuck obsolete stuff into
one of those and hide it by default. Then we didn't have to
completely overhaul the spec.
Walter said that sounded good.
__UPDATE__: _[The DIP was subsequently revised and
accepted](https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1052.md)._
### Tangeant: bitfields and bootstrapping
Martin asked if bitfields were going behind an edition. Walter
said they didn't need to as they were purely additive. Jonathan
noted they would break the introspection stuff in some cases. We
could argue that it was minimal enough that we didn't care, but
adding bitfields did change something.
Rikki said one clean split to decide if something should go
behind an edition was declarations. Any new declaration like
bitfields would go behind an edition. Otherwise, statements,
traits, etc. would go into the base language.
Átila didn't think we needed an edition for something that was
purely additive, that didn't exist before, only when we were
deleting or changing things. Or adding things that broke
something. Walter said editions were for breaking changes.
Jonathan agreed. The issue was that adding things sometimes would
break things. In terms of type introspection, that was kind of
true in general. Changes of any kind would risk breaking it. If
we were super worried about that, then we'd have to make an
edition for every change, and that was something we didn't want
to be doing. He didn't know if it was a big enough deal with
bitfields to care, but he could argue it was borderline. We could
go either way on it. The core question in general should be, is
this change going to break things if we introduce it without an
edition?
Martin noted that introspection changes might break serialization
frameworks. Bitfields in particular. They made a difference from
a compiler perspective as well. For LDC, it meant changing the
whole structure. We could no longer assume that every member had
a unique, distinct address. You couldn't address members on a
byte level now.
Rikki said we had to consider encouraging people to upgrade to
newer editions and accepting breaking changes. New features were
a way to do that. Átila agreed. I said that bitfields weren't
really a marquee feature that would motivate people to upgrade.
Walter was the one who wanted them most. Átila agreed again.
Martin noted we'd need to wait for years to use them in the
compiler code base because of the bootstrap compilers. Walter
lamented that it was frustrating being unable to use newer D
features in the compiler source because of the bootstrap
compiler. He said Iain was dependent on the bootstrap and asked
if Martin was, too.
Martin said it wasn't for him. It was for all the people
maintaining packages. They needed to be able to build the new
stuff, so they needed a D compiler to exist in the first place.
He'd been told that in most cases, they didn't use the version
from the previous release. They did it all from scratch. That was
why most of the time they depended on GDC, the old 2.076 version,
because it was still completely based on C++. They started with
that, because they only needed a C++ compiler, then they could
start building newer versions up to the latest bootstrap version.
So we couldn't just arbitrarily say, 'Oh, I want to use bitfields
now.' We'd have to bump up the boostrap compiler version, adding
an extra step to the process for the maintainers, which could be
quite tedious.
Walter said that meant we were stuck with it long term. Martin
said we weren't stuck. There just needed to be a good enough
argument to bump up the bootstrap version. We had to be really
careful about it.
Rikki said a permanent fix to the bootstrap compiler problem
would be dumping D out to C++. DMD was an excellent code base for
it. Martin said then we'd be no better than Zig or whatever that
started out transpiling to C and building with a C compiler.
Átila asked if Rikki was suggesting doing this just for the sake
of the bootstrap compiler. Rikki said it was just for DMD so that
we could create an updated bootstrap. Martin said no one needed
that. Package maintainers were using GDC or LDC, never DMD.
Mathias said we didn't have this sort of default for nothing.
He'd done the work to bootstrap on a new distribution, Alpine
Linux, and he'd been very glad to have GDC available at the time.
We couldn't use the shiniest D features in DMD, but he didn't
think that was the end of the world. The tradeoff was worth it
because it made it so much easier, so much more appealing, for
people outside of the community to work for it and maintain it.
Martin said converting the D codebase to C++ wouldn't
automagically make it able to target completely different
targets. We'd still be stuck with it only targeting x86, and that
was completely insufficient. Walter noted he was working on ARM
support. Martin said it was going to take time and would perform
very badly in the beginning. And anyway, there were other
relevant architectures that DMD did not support.
Rikki said he wasn't talking about the DMD backend, only the
frontend. Literally, just copy it over to a new target with the
LDC glue code, and you had an LDC. You didn't need a D compiler
to compile it.
Walter said the compiler could convert D code to C code, but it
wasn't capable of converting it to C++ automatically. You could
do it by hand, but who would want to make that effort?
We spent some more time discussing why transpiling the D frontend
to C++ was not a good idea (huge project, bugs, test suite, and
so on).
Getting back to the bootstrap version, I suggested it would come
down to Walter getting together with Iain to determine what would
be a good milestone at which we could upgrade.
Walter suggested we could go back to the bootstrap version and
add bitfields to it. He then said he could see us all shaking our
heads, and that we obviously hated the idea. Átila said he didn't
hate bitfields, but Walter was the only one who cared about them.
Rikki said he didn't see this ending well for us long term
without dumping to C++. Martin disagreed. Clang was definitely
written in C++. GCC was, too, nowadays. He doubted they came up
with an idea to transpile to C and fix all their bootstrapping
problems that way. Átila said they did not do that.
Martin speculated that Iain's answer to the bootstrapping thing
would be aligned with the release timeline of GCC. If we looked
at the currently supported major version of GCC, that should tell
us which frontend version was important. Mathias said the latest
GCC version was 12.5 in July and asked which frontend version it
targeted. Martin thought it was 2.110.
Jonathan said there were two approaches to bootstrapping. One was
to start with the oldest version and make subsequent builds
through some set of versions until you arrived at the newest, or
you had some sort of cross-compilation solution. He thought
cross-compilation would be ideal. Otherwise, we'd have to go too
far back eventually.
Martin said cross-compilation would have been his first
suggestion as well, but from what he'd been told by package
maintainers, they didn't work that way. They started on native
systems and needed that to work. They had a two-step process:
they started with 2.076, then built the current bootstrap. So if
we added in bitfields, that would be a third step.
Jonathan said he'd be afraid that eventually there'd be so many
issues cropping up, we'd be unable to build the old version
anymore. Because it was C++, it should continue to be buildable
in theory, but assuming you could continue to build something
that was going to become 10, 15, 20 years old, eventually that
became questionable. At which point, cross-compilation would be
better. If we had a clean way to do that, maybe we could get
people to do it more easily.
I said we weren't going to solve it in this meeting and suggested
we move on.
### The proposed new release branches
Martin said he wanted to better understand [Dennis’s proposal to
get rid of the stable
branch](https://forum.dlang.org/post/[email protected]) and move to release branches with backports. He asked how backporting would work in practice. Considering all the potential merge conflicts that something like this would entail, would it be a manual process? Would we have some automated machinery in place to take care of easy merge conflicts?
He gave an example of opening a PR for the master branch that
would need to be backported to 2.109, 2.110, and 2.111. So that
was four commits to at least four branches. Did we have an idea
of how to tackle it?
Dennis said that some cases would require manual merging, but the
idea wasn't that we would maintain 2.109, 2.110, and 2.111 with
continuous backports. It was just for the rare cases when there
was a critical bug to fix, like something breaks with a new macOS
release, or industry users are being hampered by something and
can't upgrade yet for some reason.
In theory, we would still be releasing at the same patch cadence.
The branch structure would just be different so that we didn't
have to continuously choose between master and stable and merge
them back and forth. It was currently a huge source of confusion.
Which branch to target depended on the time and the kind of bug
fix, and people had differing opinions.
Martin asked how it would be different. We'd been working on
2.112 for half a year now. Stable still hadn't been merged into
master. So if he wanted to pick something in 2.111, like the
performance regression for the array append in DRuntime, he'd
target stable, the latest. So what difference would the release
branches make?
Jonathan said that everything would go into master. Beyond that,
it was just a question of whether and where you backported it.
Martin got that, but who would do it?
Dennis said it would be the pull request managers. Or if the PR
author had his own idea, he could do it himself. But a normal
contributor who didn't know about any of this stuff could just
target master. If we thought it should target a prior release, we
could help them out and wouldn't have to ask them to rebase. That
was the sort of thing people new to contributing always messed up.
Martin said the thing that mattered most to him was the latency.
Most of the time when he was working on the DMD stable branch, it
was because he noticed a problem in LDC. Maybe he merged a new
frontend and noticed some issues. It was important for him that
this stuff landed quickly in the branch he was interested in.
Currently, he could target stable. As soon as it was merged, he
knew it was up to date, and he could merge it into LDC. He just
didn't want to be waiting weeks for something to get merged. He
worried that it would be more work for the PR managers now.
Dennis said he didn't have all the answers up front. He was
considering keeping stable as a pointer to the latest. He didn't
know how easy it would be to maintain, but the stable branch
might remain.
The most important issues to solve were the constant confusion,
the divergence between master and stable where we forgot to merge
stable back into master in time, and weird conflicts and issues
that sometimes cropped up. For example, in this release cycle, he
once attempted to build 2.112 and then couldn't make a patch for
2.111 again because stable had been merged into master, so there
was no branch to build 2.111.
Martin said that was no problem for LDC. Everything was based on
master. There was no stable branch. Then again, they only had a
couple of contributors, so it was no problem. This was where tags
would come in handy. You could always create a new branch for an
old release based on the latest tag.
One last thing Martin wondered about was that associating issues
fixed in a certain time frame with a specific release was kind of
hard. If it was master, then at what point was the master stable?
Dennis said his idea for that was to use milestones. Martin said
he could then use milestones to say he wanted a fix backported to
a certain version.
Rikki suggested that instead of backporting, Martin could do the
opposite and target the old branch, then have a tag to put it
into master. If he only had to go one release back, that seemed
like it would work better for him.
Martin said that was what we currently had with stable.
Periodically, we had these merges of stable into master, and that
was automatically forwarded.
Mathias asked Dennis if he was interested in hearing about the
release process that Sociomantic had. Dennis said he was open to
it. He wasn't experienced with the release process and was still
new to it. Iain was still taking it slow, so until someone else
stepped up, Dennis was figuring things out and listening to
feedback. If things didn't work, he wasn't trying to force one
approach or another. He was suggesting ways to solve existing
problems.
Regarding milestones, he wasn't thinking that every issue should
actively target a release. But occasionally, if, for example,
Walter said, 'Hey, I want bitfields in by 2.112,' then we could
make a milestone for that. And then we could prioritize the
issues we needed to fix before bitfields could be released and
make sure they were ready for 2.112. Right now, it wasn't clear
where we were with cases like that. Sometimes we had a train of
PRs working on one thing. If a release started in the middle of
that, then we'd end up with a half-baked release of that feature.
Martin asked how the changelog generator worked these days. He
had no idea how it had worked with the old Bugzilla system. Did
we select the version in some way?
Dennis said it was based on time. It collected all the issues
from a period and concatenated them into the changelog. Martin
said that, in that case, just working with the master branch as
the main branch to target PRs made sense.
Martin then veered off into a suggestion about automating the CI
artifacts for the release process, and he and Dennis discussed
some of those details for a few minutes.
### Fast DFA update
Rikki said the fast DFA he'd been working on had caught its first
production bug. Earlier in the day, he'd put his big 100k code
base through it, running at 4.2 seconds. That was the same amount
of time as without the DFA enabled.
Martin asked how he'd done that. Rikki said it was optimized.
Walter said he should post about it in the newsgroup. Rikki said
he would as soon as it was ready. There were still some bugs to
work out. He was hopeful it could be merged in the next month. It
hadn't been reporting any false positives. If any did come up, he
could fix them.
It was running at the right speed. He'd caught two segfaults
related to memory management. He thought one of them might be due
to memory fragmentation. He was wondering if we should give DMD a
new memory allocator for Windows to replace malloc.
Dennis asked if he'd tried running it on DMD's code, because
there were plenty of segfaults in there. Rikki said he had it on
the CI at the moment. It was currently ignoring the flag, but
when building DMD with it, it was passing. He wasn't all that
surprised by that, as the people working on DMD were generally
highly skilled.
Dennis said there were still many issues with null dereferences.
Was Rikki saying they were all gone? Rikk said no, the fast DFA
was not a 100% solution. It wasn't handling indirections. It was
so fast because it was just doing a small subset of things.
## Conclusion
We held our next monthly meeting on September 6th.
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.