This week’s theme song is Willie Nelson’s “Midnight Rider”. There’s no clever reason behind it. It’s a great song, it brims with energy, and this was a week with energy to spare. Sometimes a theme is just a vibe, a feel. This one fits.
Calling C from Pony is usually easy. You write the FFI declarations, you call the function, you’re done. Sometimes it isn’t that easy: you need to call a macro, so there’s no symbol to bind to. Or you have to fill in a struct by hand before you can pass it in. Or the calling convention is one Pony’s FFI can’t express. C has all kinds of little oddities that don’t line up with Pony. When you hit one of those oddities, it is time to reach for a shim: a small piece of C between Pony and the library. Building it and shipping it has always been the hard part. Not anymore.
This week’s theme song is The Rubberbandits’ “Horse Outside”, and it’s completely brilliant. It’s a man at a wedding telling everyone to keep their cars. Fuck your Honda Civic, he’s got a horse outside. Pony spent the week in that exact mood. Fuck your external linker, it’s gone. Fuck your second build system, ponyc compiles your C shims itself now. That last one came together so fast it just felt good. Pony is the fucking horse outside.
This week’s theme song is Willie Nelson’s “Uncloudy Day”. Last week shipped with some brimstone in it, and this week the skies cleared. No releases went out, but main kept filling up, and the headline is that RFC 86 is implemented. The stdlib json package now has a way to turn any JsonValue back into a string.
This week’s theme song is 16 Horsepower’s “Black Soul Choir”, all banjo and brimstone, because we shipped a release with some brimstone in it. ponyc 0.64.0 is out. Three breaking changes, two long-standing compiler bugs put to bed, and the recursive type alias work all landed in one drop. The whole networking stack moved over with it. Red also shipped the first release of a timezone library.
Here’s how it is: for a few years, off and on, I went looking for a bug.
My aarch64 testing machine, a sturdy little Raspberry Pi, was the site of so very many segfaults. The same tests would fail run after run, and I could boil the crash down to a handful of lines of try and error. It came out of the machinery Pony uses to unwind the stack when error fires. So I’d pull that code up and compare it to the spec. It looked right. I’d run out of leads and put it down. Months later I’d pick it up and start over.
I never found it.
I kept coming back to it. I’d talk it through with Sylvan, and we’d end up in the same place. I’d talk it through with Joe, and we’d end up there too. The bug probably isn’t ours. It’s probably down in the guts of LLVM, somewhere we don’t own. Probably.
So I stopped chasing the bug and looked at where it lived: the stack unwinding. Pony doesn’t have to unwind the stack to raise an error. Take the unwinding away, and the bug has nowhere left to be. Soon, that’s how it’ll work — there’s a pull request open against the compiler that takes stack unwinding out of Pony’s errors, and that bug is part of why I wrote it. But only a part.
What comes around goes around. I’ll tell you why, why, why, why.
That is, near enough, how the Pony compiler’s subtype check works on a type that refers to itself. It follows the type down into its own structure, and for an ordinary self-referential type it soon comes back around to a pair it is already checking further up. That return is the exit. What comes around closes, and the check finishes.
This is a story about two types where the check went down and never came back around. One of them sent the compiler into a loop with no end. The other ran it off the end of its stack and knocked it over. One was reported in 2016, the other in 2021, and both closed in a single pull request.
One theme song wasn’t going to cover this week, so you’re getting three, and all of them are gospel. PR 5246 merged. Finite recursive type aliases are in ponyc, and the oldest open issue in the repository, eleven years on the books, is closed. I have been buried in this for weeks. It’s done. So we open with Johnny Cash, “It Was Jesus” and “Swing Low, Sweet Chariot”, and then the Blind Boys of Alabama, “Jesus Gonna Be Here Soon”. Hallelujah. It was a glorious week and I’m in the mood to celebrate.
There’s more than the merge. Three blog posts went up telling the whole story behind the alias work, and we put our stance on AI-assisted contributions in writing. An exploratory port of Pony to Haiku opened, which made two old BeOS hands very happy. And the old HTTP libraries are on their way out.
This is the third post in a short series on finite recursive type aliases in Pony. The first post told the story of the eleven years it took to allow them. The second post laid out the algorithm that decides which recursive aliases are legal.
That algorithm is correct. Correct isn’t enough. Past a certain size, a tangle of type aliases that all refer to each other sent the compiler’s type checker into exponential work. Slow at first. Then, on a bigger tangle, eleven minutes of churning with no end in sight. The compiler wasn’t rejecting these programs — the algorithm accepts them. It just couldn’t finish checking them in any reasonable time.
This is the second post in a short series on finite recursive type aliases in Pony. The first post told the story of why this took eleven years. As I write this, the pull request that adds the feature is open and in review on ponyc. It hasn’t merged yet. Details may shift before it does, but everything in this post is foundational. It should all hold.
So how does the compiler tell a finite recursive type alias from an infinite one?
The algorithm is Tarjan’s strongly connected components. I’ll walk through it. Then I’ll show you the two checks I built on top of it.