<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: verdagon</title><link>https://news.ycombinator.com/user?id=verdagon</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Fri, 24 Apr 2026 01:53:27 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=verdagon" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by verdagon in "Nanopass Framework: Clean Compiler Creation Language"]]></title><description><![CDATA[
<p>I'm often skeptical of the desire to create a lot of passes. In the early Vale compiler, and in the Mojo compiler, we were paying a lot of interest on tech debt because features were put in the wrong pass. We often incurred more complexity trying to make a concept work across passes than we would have had in fewer, larger passes. I imagine this also has analogies to microservices in some way. Maybe other compiler people can weigh in here on the correct number/kind of passes.</p>
]]></description><pubDate>Sun, 19 Apr 2026 15:37:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=47825090</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=47825090</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47825090</guid></item><item><title><![CDATA[The Impossible Optimization, and the Metaprogramming to Achieve It]]></title><description><![CDATA[
<p>Article URL: <a href="https://verdagon.dev/blog/impossible-optimization">https://verdagon.dev/blog/impossible-optimization</a></p>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=45721846">https://news.ycombinator.com/item?id=45721846</a></p>
<p>Points: 9</p>
<p># Comments: 1</p>
]]></description><pubDate>Mon, 27 Oct 2025 15:07:19 +0000</pubDate><link>https://verdagon.dev/blog/impossible-optimization</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45721846</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45721846</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>This approach solves one borrow checking pain point (by allowing temporary mutable aliasing, even across function boundaries), but the post might actually be a bit conservative in saying it will influence our programs' data to look like trees.<p>As a thought experiment, I've been imagining how this would handle an architecture like e.g. Google Earth's, where a program's classes are divided into multiple "layers". For example, an upper "business logic" layer (DocumentManager, Document, CardManager, Card, StateManager) might have references to the more general "services" lower layer (NetworkService, FileService).<p>With Nick's system, we could have a group annotation on these various upper-layer classes, like e.g. `Document[s: group IService]`. With these annotations, these upper-layer classes can have references to the services themselves (though not their contents). This might let services' methods mutate the services' contents even though others have references to them (though not their contents). The services' methods would have to communicate that they're modifying the contents of the services (via a `mut` annotation), and the compiler would prevent holding references to the services' contents across those callsites. But also, those contents are private anyway, so the user wouldn't have those references anyway.<p>If that turns out to be true (Nick and I are still exploring it) then he's found a way to make borrowing work for some DAG-shaped program architectures, rather than just strictly tree-shaped architectures.<p>On top of that, if we compose this approach with linear types, I think we can get at least halfway towards compile-time-memory-safe back-references. TBD whether that works, but that would be pretty exciting.<p>TL;DR: My saying it only supports tree-shaped programs is me hedging and being conservative.<p>Still, until these things are proven to work, I should be more consistent in when I'm conservative vs optimistic. I'll update the article to address that. Thanks for pointing that out and helping me be more consistent!</p>
]]></description><pubDate>Thu, 28 Aug 2025 18:16:46 +0000</pubDate><link>https://news.ycombinator.com/item?id=45055246</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45055246</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45055246</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>Big fan of Verona, I love their memory safety approach as well. I wrote a bit about it in the Grimoire [0] too. IIRC they plan for the user to specify whether a region is backed by an arena allocator or GC, which sounds pretty nice. It's kind of hard to track down details though, most of my knowledge comes from reading David Chisnall's comments on lobste.rs.<p>[0] <a href="https://verdagon.dev/grimoire/grimoire" rel="nofollow">https://verdagon.dev/grimoire/grimoire</a></p>
]]></description><pubDate>Thu, 28 Aug 2025 17:49:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=45054958</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45054958</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45054958</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>Yep, adding or removing an element would invalidate existing pointers to any other element in the hash table. This is generally regarded as a good thing if your elements are stored contiguously in the hash table, because a resize would cause any existing pointers to dangle. This should be true for C, and might be true for C# if you're using `struct`s which put the data inline (memory's a bit fuzzy on C#'s rules for references to structs though, maybe someone can chime in).<p>This new approach still requires us to be mindful of our data layout. Not caring about data layout is still definitely a strength of GC and RC. I'm actually hoping to find a way to blend Nick's approach seamlessly with reference counting (preferably without risking panics or deadlocks) to get the best of both worlds, so that we can consider it for Mojo. I consider that the holy grail of memory safety, and some recent developments give me some hope for that!<p>(Also, I probably shouldn't mention it since it's not ready, but Nick's newest model might have found a way to solve that for separate-chaining hash maps where addresses are stable. We might be able to express that to the type system, which would be pretty cool.)</p>
]]></description><pubDate>Thu, 28 Aug 2025 14:13:06 +0000</pubDate><link>https://news.ycombinator.com/item?id=45052417</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45052417</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45052417</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>Great question! That's a big enough topic that I'd love to write a followup post about it. There's also a good thread on r/Compilers at <a href="https://www.reddit.com/r/Compilers/comments/1n2ay7g/comment/nb4mj9t/" rel="nofollow">https://www.reddit.com/r/Compilers/comments/1n2ay7g/comment/...</a> about how Nick's model should support that.<p>TL;DR: Mutability is tracked at the group level, so we can share an immutable group with any number of threads (especially good with structured concurrency) or lend a mutable group to a single other thread. References themselves are still aliasable, regardless of the group's mutability.<p>Taking an existing (mutable, aliasing) group and temporarily interpreting it as immutable has precedent (I did it in Vale [0]) so I like the approach, but I might be biased ;)<p>(This is from my memory of how Nick's proposal works, I'll ask him to give a better answer once morning hits his Australia timezone)<p>[0] <a href="https://verdagon.dev/blog/zero-cost-borrowing-regions-part-1-immutable-borrowing" rel="nofollow">https://verdagon.dev/blog/zero-cost-borrowing-regions-part-1...</a></p>
]]></description><pubDate>Thu, 28 Aug 2025 14:03:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=45052300</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45052300</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45052300</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>Hey all, this is a post explaining a new memory safety model by my friend Nick Smith (original proposal at <a href="https://gist.github.com/nmsmith/cdaa94aa74e8e0611221e65db8e41f7b" rel="nofollow">https://gist.github.com/nmsmith/cdaa94aa74e8e0611221e65db8e4...</a>)<p>It was interesting enough that I knew I had to write a post about it. Happy to answer any questions!</p>
]]></description><pubDate>Thu, 28 Aug 2025 13:53:29 +0000</pubDate><link>https://news.ycombinator.com/item?id=45052229</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45052229</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45052229</guid></item><item><title><![CDATA[New comment by verdagon in "Group Borrowing: Zero-cost memory safety with fewer restrictions"]]></title><description><![CDATA[
<p>Great point =) That's true for a lot of languages (including Mojo too), so I should have said "non-owning reference" there. I'll update the post to clarify. Thanks for catching that!</p>
]]></description><pubDate>Thu, 28 Aug 2025 13:51:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=45052194</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45052194</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45052194</guid></item><item><title><![CDATA[Group Borrowing: Zero-cost memory safety with fewer restrictions]]></title><description><![CDATA[
<p>Article URL: <a href="https://verdagon.dev/blog/group-borrowing">https://verdagon.dev/blog/group-borrowing</a></p>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=45051345">https://news.ycombinator.com/item?id=45051345</a></p>
<p>Points: 85</p>
<p># Comments: 86</p>
]]></description><pubDate>Thu, 28 Aug 2025 12:29:15 +0000</pubDate><link>https://verdagon.dev/blog/group-borrowing</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=45051345</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45051345</guid></item><item><title><![CDATA[Understanding SIMD: Infinite complexity of trivial problems]]></title><description><![CDATA[
<p>Article URL: <a href="https://www.modular.com/blog/understanding-simd-infinite-complexity-of-trivial-problems">https://www.modular.com/blog/understanding-simd-infinite-complexity-of-trivial-problems</a></p>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=42237938">https://news.ycombinator.com/item?id=42237938</a></p>
<p>Points: 257</p>
<p># Comments: 116</p>
]]></description><pubDate>Mon, 25 Nov 2024 17:08:09 +0000</pubDate><link>https://www.modular.com/blog/understanding-simd-infinite-complexity-of-trivial-problems</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=42237938</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42237938</guid></item><item><title><![CDATA[New comment by verdagon in "Pin"]]></title><description><![CDATA[
<p>I can imagine a Rust-like language where we have move-constructors (in TFA), and every generated Future subtype is opaque and also heap allocated for us.<p>I <i>think</i> the need for Pin could then disappear, because the user would have no way to destroy it, since it's opaque and elsewhere on the heap, and therefore no way to move it (because having move-constructors implies that moving is conceptually destroying then recreating things).</p>
]]></description><pubDate>Mon, 22 Jul 2024 04:58:36 +0000</pubDate><link>https://news.ycombinator.com/item?id=41031041</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=41031041</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41031041</guid></item><item><title><![CDATA[New comment by verdagon in "Reference Counting with Linear Types"]]></title><description><![CDATA[
<p>Good to see some more uses of linear types! Very few languages can use linear types, and their potential is <i>huge</i> IMO.<p>OP shows the benefits of a linear RC that tracks references dynamically, and one can even imagine a version where the compiler tracks the references instead.<p>For example (for those who are more familiar with Rust) imagine that it had linear types and that we used them for matthieum's static-RC [0] (like suggested by frank-king at [1] to prevent leaks) and you'd have a pretty good idea of linear static RC.<p>I also talked about a possible alternative linear static RC at [2] and [3] (I didn't explain it well at all, happy to elaborate), though lately I suspect that one would need to add a GhostToken-ish [4] substance to allow safely reading/writing the shared value, or perhaps a RefCell.<p>I <i>suspect</i> that something like GhostToken could also solve OP's restriction that types be opaque, if Haskell has something like GhostToken... I could be wrong on that though.<p>[0] <a href="https://github.com/matthieu-m/static-rc">https://github.com/matthieu-m/static-rc</a><p>[1] <a href="https://github.com/matthieu-m/static-rc/issues/7">https://github.com/matthieu-m/static-rc/issues/7</a><p>[2] "Linear reference counting" in <a href="https://verdagon.dev/grimoire/grimoire#the-list" rel="nofollow">https://verdagon.dev/grimoire/grimoire#the-list</a><p>[3] <a href="https://www.reddit.com/r/rust/comments/1d06gjo/comment/l61qmnw/?context=3" rel="nofollow">https://www.reddit.com/r/rust/comments/1d06gjo/comment/l61qm...</a><p>[4] <a href="https://www.reddit.com/r/rust/comments/p5f78s/ghostcell_separating_permissions_from_data_in_rust/" rel="nofollow">https://www.reddit.com/r/rust/comments/p5f78s/ghostcell_sepa...</a></p>
]]></description><pubDate>Sun, 23 Jun 2024 00:01:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=40763390</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40763390</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40763390</guid></item><item><title><![CDATA[New comment by verdagon in "Crossing the impossible FFI boundary, and my gradual descent into madness"]]></title><description><![CDATA[
<p>I've been looking into this, and I <i>suspect</i> that one actually needs surprisingly little to interoperate safely with Rust.<p>TL;DR: The lowest common denominator between Rust and any other memory-safe language is a borrow-less affine type.<p>The key insight is that Rust is actually several different mechanisms stacked on top of each other.<p>To illustrate, imagine a program in a Rust-like language.<p>Now, refactor it so you don't have any & references, only &mut. It actually works, if you're willing to refactor a bit: you'll be storing a lot of things in collections and referring to them by index, and cloning even more, but nothing too bad.<p>Now, go even further and refactor the program to not have any &mut either. This requires some acrobatics: you'll be temporarily removing things from those collections and moving things into and out of functions like in [2], but it's still possible.<p>You're left with something I refer to as "borrowless affine style" in [1] or "move-only programming" in [0].<p>I believe that's the bare minimum needed to interoperate with Rust in a memory safe way: unreference-able moveable types.<p>The big question then becomes: if our language has only these moveable types, and we want to call a Rust function that accepts a reference, what then?<p>I'd say: make the language move the type in as an argument, take a temporary reference just for Rust, and then move-return the type back to the caller. The rest of our language doesn't need to know about borrowing, it's just a private implementation detail of the FFI.<p>These weird moveable types are, of course, <i>extremely unergonomic,</i> but they serves as a foundation. A language could use these only for Rust interop, or it could go further: it could add other mechanisms on top such as & (hard), or &mut (easy), or both (like Rust), or a lot of cloning (like [3]), or generational references (like Vale), or some sort of RefCell/Rc blend, or linear types + garbage collection (like Haskell) and so on.<p>(This is actually the topic of the next post, you can tell I've been thinking about it a lot, lol)<p>[0] "Move-only programming" in <a href="https://verdagon.dev/grimoire/grimoire#the-list" rel="nofollow">https://verdagon.dev/grimoire/grimoire#the-list</a><p>[1] "Borrowless affine style" in <a href="https://verdagon.dev/blog/vale-memory-safe-cpp" rel="nofollow">https://verdagon.dev/blog/vale-memory-safe-cpp</a><p>[2] <a href="https://verdagon.dev/blog/linear-types-borrowing" rel="nofollow">https://verdagon.dev/blog/linear-types-borrowing</a><p>[3] <a href="https://web.archive.org/web/20230617045201/https://degaz.io/blog/632020/post.html" rel="nofollow">https://web.archive.org/web/20230617045201/https://degaz.io/...</a></p>
]]></description><pubDate>Mon, 17 Jun 2024 17:43:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=40708613</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40708613</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40708613</guid></item><item><title><![CDATA[New comment by verdagon in "Exploring Seamless Rust Interop for Newer Languages, Part 1"]]></title><description><![CDATA[
<p>Just did, thanks for the suggestion!</p>
]]></description><pubDate>Fri, 24 May 2024 23:25:00 +0000</pubDate><link>https://news.ycombinator.com/item?id=40471362</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40471362</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40471362</guid></item><item><title><![CDATA[Layer-wise inferencing and batching: Small VRAM doesn't limit LLM throughput]]></title><description><![CDATA[
<p>Article URL: <a href="https://verdagon.dev/blog/llm-throughput-not-ram-limited">https://verdagon.dev/blog/llm-throughput-not-ram-limited</a></p>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=40373188">https://news.ycombinator.com/item?id=40373188</a></p>
<p>Points: 2</p>
<p># Comments: 0</p>
]]></description><pubDate>Wed, 15 May 2024 22:29:58 +0000</pubDate><link>https://verdagon.dev/blog/llm-throughput-not-ram-limited</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40373188</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40373188</guid></item><item><title><![CDATA[New comment by verdagon in "Higher RAII and the seven arcane uses of linear types"]]></title><description><![CDATA[
<p>Thanks! And yeah I get that a lot >_> You're always welcome to swing by the discord where I can give a less arcane explanation! (<a href="https://discord.gg/SNB8yGH" rel="nofollow">https://discord.gg/SNB8yGH</a>)</p>
]]></description><pubDate>Wed, 15 May 2024 15:08:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=40367957</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40367957</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40367957</guid></item><item><title><![CDATA[New comment by verdagon in "Higher RAII and the seven arcane uses of linear types"]]></title><description><![CDATA[
<p>Hah I like this one!<p>PS. Congrats! <a href="https://verdagon.dev/blog/easter-egg-notes" rel="nofollow">https://verdagon.dev/blog/easter-egg-notes</a></p>
]]></description><pubDate>Wed, 15 May 2024 15:05:28 +0000</pubDate><link>https://news.ycombinator.com/item?id=40367905</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40367905</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40367905</guid></item><item><title><![CDATA[New comment by verdagon in "Higher RAII and the seven arcane uses of linear types"]]></title><description><![CDATA[
<p>It could, but then that List would have to be linear itself, and then the program would make sure that you eventually drain the list and destroy each element.<p>(One caveat is for linears in globals, which aren't implemented in Vale yet. We haven't decided which strategy we're going with there, but TFA talks about some)</p>
]]></description><pubDate>Wed, 15 May 2024 14:53:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=40367749</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40367749</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40367749</guid></item><item><title><![CDATA[New comment by verdagon in "Higher RAII and the seven arcane uses of linear types"]]></title><description><![CDATA[
<p>A really good question. In short, a linear List (or array, or hash map, etc) will only have two available destroyer functions:<p>1. drop_into(list, func): It consumes the list, calling the given `func` for each element.<p>2. expect_empty(list): Consumes the list, panicking if the list isn't empty.</p>
]]></description><pubDate>Wed, 15 May 2024 14:49:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=40367689</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40367689</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40367689</guid></item><item><title><![CDATA[New comment by verdagon in "Higher RAII and the seven arcane uses of linear types"]]></title><description><![CDATA[
<p>I've got some weird plans for variants. Basically, we'd represent an enum as a non-heap-allocated sealed interface with a struct for each "case". Basically, think of a Scala case class. Then, depending on where we put it (heap vs local/member/element), it will be compiled differently (a traditional interface vs a tagged variant, respectively). ...I don't expect that to make any sense.<p>Alas, I haven't started on sealed interfaces yet. Right now I'm occupied with the Rust interop; I'm hoping we can be able to seamlessly e.g. `import rust.std.collections.Vec<i32>;` and have it work. A <i>lot</i> of pieces have to fall into place for that to work though, especially since that's generic and Rust doesn't even have a stable ABI. It's kicking my ass, and I'm having a lot of fun with it!</p>
]]></description><pubDate>Wed, 15 May 2024 02:14:38 +0000</pubDate><link>https://news.ycombinator.com/item?id=40362387</link><dc:creator>verdagon</dc:creator><comments>https://news.ycombinator.com/item?id=40362387</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40362387</guid></item></channel></rss>