HNHacker News
TopNewBestAskShowJobs

fluffybucktsnek

92 karma · joined March 11, 2026

submissionscomments
fluffybucktsnek··on Zig Structs of Arrays (2024)
I don't see how it is unrelated. If have a custom type `A` with an overload on `+`, it will only affect places I used custom type `A`. If there wasn't operator overloading, I would just have to use a different notation to call the same function, but with possibly worse ergonomics (which is also why I think your solution doesn't really satisfy that, it doesn't read like algebra which is kind of the point). Given that type A is presumed to be custom, I don't see how place Y would be unrelated since it deliberately uses type `A`.

If we include operator overloading for any types, then sure. i32 + i32 might suddenly start meaning something else. But I think that's beyond the scope of what is normally asked by operator overloading.

fluffybucktsnek··on Zig Structs of Arrays (2024)
I think both operator overloading and most operators themselves are syntactic sugars. Operator overloading happens to point towards specific functions, whereas arithmetic integer operators point to compiler intrinsics.
fluffybucktsnek··on Anti-social: It's fads, not friends, which now dominate social media feeds
That might imply USENET and mailing lists to be forms or primitive forms of social media.
fluffybucktsnek··on Moving beyond fork() + exec()
Conceptually, processes are more akin to units of isolation. Threads are closer to function calls.
fluffybucktsnek··on C constructs that still don't work in C++
I know. I mentioned C++ inheritance because it's its default dynamic dispatch mechanism that I'm aware of.
fluffybucktsnek··on C constructs that still don't work in C++
I feel like you are attacking a strawman here. My point isn't that it's impossible to optimize, but such optimizations are fickle and easy to break by programmer error and require adequate language expressivity (although low-level languages generally provide that).

You say that the compiler made the decision to not inline it because it judged it to be the most efficient, yet, by adding the "const", thus adding more info, it did inline it. Why did the heuristics change here, even though the logic remained the same? I argue it's not because the compiler decided it would be more performant to not inline, but that it was acting on the side of caution.

Finally, if giving the compiler more freedom to make choices is your goal, then forcing it to start by either type-erasure or monomorphization is the wrong answer. The compiler should be free to choose type-erasure/monomorphization from the start in such case. However, that introduces limitations to the language. Since the generic function is prohibited from knowing the type size at compile time, it can't allocate space for it in the stack. Long story short, I think you'd be forcing the programmer into an abstraction they might not need nor would necessarily help them, and then hoping the compiler to optimize appropriately.

Personally, I care about expressivity and transparency, thus I think having both natively supported is preferable. But if one must be chosen over the other, monomorphism should come first, as you can build a vtable with it (also, there are many ways to build vtables and dynamically diapatch).

fluffybucktsnek··on C constructs that still don't work in C++
How did it not lack of contextual info? By adding "const", you provided more info to the compiler, and it decided it was safe to inline, despite no actual behavior change. My point is, despite the possibility, these optimizations are easy to disable by mistake.

Also, there's no gish-gallop. You said the compiler can optimize type-erasure like monomorphization, but not monomorphization like type-erasure, and I said that's not true: the compiler can, in fact, do that. I simply addressed your argument. The rest simply elaborates on why languages why might not do it.

fluffybucktsnek··on C constructs that still don't work in C++
My issue isn't that the modification made it impossible to inline, more so how trivial it was: I just added a different type. Generally, optimizations are disabled not because the compiler finds them inneficent, but because it lacks enough contextual information/intelligence to safely add it. So similar to what you said, in theory, the compiler can optimize type-erasure just like monomorphism, but, in practice, it lacks info to do so. Either by programmer accident, language/compiler limitations, or both.

Also, monomorphization doesn't actually take the compiler freedom away (on its own) to optimize. Similar to how type-erasure can be optimized to behave like monomorphization through devirtualization, monomorphized calls can be virtualized (which Swift shows). The problem is that it takes away transparency from the programmer. It also changes the semantics of the call behind the scene (type-erasure is strictly pass-by-pointers, monomorphism is not). That wouldn't work well for a low-level language.

fluffybucktsnek··on C constructs that still don't work in C++
A bit of a nitpick, but I think this would be closer to a generic array: https://godbolt.org/z/cfdPWb6zz

Still, adding a different typed array already breaks inlining, https://godbolt.org/z/zavojE8xK (type-erasure) vs. https://godbolt.org/z/barroPfsP (monomorphized).

Aside from being heavily optimization-dependant, thinking through this, I've realized that type-erasure is a bit of a premature abstraction. It forces programmers to use indirection and pass-by-reference/pointer. It forces functions to be type size and alignment-agnostic. That's why type-erasure can't express monomorphism proper, whereas the reverse is not true.

fluffybucktsnek··on C constructs that still don't work in C++
I am not sure why either (I believe it is aliasing), here's an example: https://godbolt.org/z/9szhxoxrf

From the code, we can already tell all elements have the same type, but the compiler is already adding checks. One of the options would be to convert the array of fat pointers into a fat slice. But now you have to enlarge the slice's vtable with all possible item operations, even if we don't use them often. Alternatively, use monomorphism. Or use both.

fluffybucktsnek··on C constructs that still don't work in C++
You seem to be underestimating how easy it is to lose type information. Creating a array of type-erased is already enough to cause confusion, even if the surrounding code is enough to prove the array only has one type. If we are to assume perfect deductive ability for type-erasure, why not for monomorphism as well?

Monomorphization isn't premature optimizations either. It and type-erasure are semantically different. For instance, only monorphization can enable inlining of data structures (as devirtualizating an array of fat pointers involves dealing with ownership concerns, among other things). You either have to type-erase the array itself or box all the items, none of which are very ergonomic for a system-level programming. Also, in terms of performance, monomorphization generally makes the compiler's job easier overall in comparison to type-erasure (specially in Rust where types also encode lifetime), so I don't see the damage unless you are dealing with an extremely size-constrained environment or dealing with instruction cache misses (which is an indication of poor abstractions).

Finally, as stated elsewhere, it's trivial to implement any type-erasure polymorphism in a monomorphic system (save for very specific exceptions, related to hardware), but the reverse is not true. To do so reliably will require assistance of an external codegen tool, like the C macros, generally recreating monomorphism, but worse, as the compiler doesn't actually know the polymorphic code is related, making deduplication even harder.

fluffybucktsnek··on C constructs that still don't work in C++
Beg to differ. After musing for while, I realized Rust could only have chosen monomorphism for its goals, thus it's not a fundamental design mistake, but a necessary choice. One of the overall philosophies is zero-cost abstractions, and only designing a polymorphic system with monomorphism in mind may provide that, because the alternative requires pointers (different type sizes, vtable, etc.).

While, as discussed previously, devirtualization + inlining is a thing, it is not assured and relatively easy to disable. Writing a program relying on these optimizations would produce something bristle and error-prone, and building a polymorphic system around this would be antithetical to the Rust's ZCO philosophy.

Meanwhile, monomorphization can fit functions around the size of the type arguments and access method implementations directly, removing the need for any indirection in the first place. While indirection-based polymorphism can't reliably reimplement monomorphic polymorphism, the reverse is not true. You can reliably reimplement any indirection-based polymorphism with monomorphism, from fat pointers (in fact, Rust already has trait objects to help with that), class-based hierarchies, dynamic typing, etc.

fluffybucktsnek··on C constructs that still don't work in C++
Tbf, I'd say Rust's concepts of Trait Objects and Generics are better implementations (in general) of C++'s inheritance and templates, respectively, rather than entirely different things. I'd also add constexpr/const blocks to good ideas to add, or else generics/templates will be abused (yet again).
fluffybucktsnek··on C constructs that still don't work in C++
Not necessarily. In pure theory, yes. But in pure theory, monomorphized code can be deduplicated too.

Monomorphization often forces types information to flow, whereas type-erasure considers that a bonus. As such, a compiler may accidentally introduce opaque boundaries that hide type information. Even in cases where this is the programmer's fault and the type info is truly lost, in monomorphisation, that becomes an explicit error, while, for devirtualization, since it's just an optimization, the call is silently revirtualized (until someone notices it while profiling/decompiling). One has explicit intent, the other doesn't.

fluffybucktsnek··on C constructs that still don't work in C++
As I stated in my follow up, vtables can only be removed when the type information is still available, which, generally, aligns with specialization, except when dealing with libraries (even with LTO). You say the "vtable can be removed in all cases of monorphization", but that isn't guaranteed and often requires double guessing the compiler to ensure it still knows the type, where as monorphization makes it explicit when the compiler doesn't know the type anymore and that specialization must occur.

The problem with your suggestion about macros is that it misunderstands the reason why different techniques exist. While they may overlap, they have different primary niches: Rust macros provide codegen and inline DSL, Rust generics/C++ templates provide monomorphism, C++ constexpr/Rust const fn evaluate expressions in compile time, etc.

Extending preprocessor macros, aside from requiring integration into the C language proper, would likely create something much more complex and with poor DX. Specially so if it tries to fulfill all niches, as each of them often operate at different abstraction levels, with different ergonomic requirements that are often at odds with each other.

fluffybucktsnek··on C constructs that still don't work in C++
I just noticed you said "The compiler can always specialize". That's indisputably false. That only happens if the compiler has enough information to infer the concrete type at the call point. Conditionals, collections, or anything that may throw doubt about original type info and their function implementations can (and normally will) disable specialization.
fluffybucktsnek··on C constructs that still don't work in C++
The inherent overhead of type-erasure is the vtable. Which is funny, because you said you prefer one over the other at the end, when they are basically synonymous. The compiler may choose to devirtualize and specialize, but that isn't guaranteed. If you want this behavior, &dyn does the exact same thing.

Specialization provides more opportunities for optimizations, whereas proper type-erasure (which bars specialization optimizations) doesn't due to lack of type information.

"C macros" are a part of the preprocessor, which runs before the actual C compiler. As such, it lacks all semantical information the C compiler would have at that point, such as function implementions. In practice, macros in C serve two purposes: manipulating C source code (which Rust macros can also do, but with more hygiene); specialization polymorphism, but worse (in which both Rust's generics and C++ templates do better).

fluffybucktsnek··on Performance of Rust Language [pdf]
Neither codegen nor macros (they are a part of the preprocessor) are really a part of C.

For the latter, the lack of integration becomes more noticeable if you try writing a macro in which the compare param can accept a function identifier. As the preprocessor doesn't have the knowledge of the contents of the referred function, it can't inline it. In C++ and Rust, their compilers do, so they can.

A codegen tool could overcome this, but you could also make a codegen tool to write Zig/D/C#/Swift in C, or any other language for that matter :). By this point, one could say you are programming in a superset of C, not strict C.

fluffybucktsnek··on C constructs that still don't work in C++
Type-erasure does have an inherent overhead. Sure, optimizations can be made, but they can be fickle and specialization is basically implicit monomorphization.

Using C macros to replicate Rust's monomorphism has several drawbacks: they are inherently unhygienic, even in comparison to Rust's own; you can't set type-bounds; they aren't even a part of C proper, etc.

I prefer Rust's approach with the choice between generics, macros, dyn and Any.

fluffybucktsnek··on Curly braces: An evolution of Unix and C
A pair of words requires more keywords (they also tend to be more verbose) and whitespace has ergonomy issues (specially with copy-pasting). Whitespace may come with intrinsic alignment, but formatting tools do short work of that.
fluffybucktsnek··on A Wayland Compositor in Minecraft
You speak as if this isn't neat in its own way.
fluffybucktsnek··on Moving away from Tailwind, and learning to structure my CSS
But it isn't a strawman. It summarizes the argument or, rather, the lack of argument, pretty nicely. Why is it a bad DSL? Why is it relevant that it was invented before the internet before the internet was widely used? These are just assertions without foundation. I think it's a lot more than "webshits" who didn't understand why it's bad.
fluffybucktsnek··on Hating AI Is Good
I don't think people value labor. Failed delayed games serve as examples.

I think it's more of the case that labor is correlated with uniqueness. And I think uniqueness is closer to what people are truly looking for in art.

fluffybucktsnek··on College students drown out AI-praising commencement speeches with boos
They might, but that isn't what they are addressing.
fluffybucktsnek··on Meta blocks human rights accounts from reaching audiences in Saudi Arabia, UAE
One of the points of consumer articulation is to prevent incentives to being "unable to file without facebook". And, where I live, taxis still exist, although as expensive as before.
fluffybucktsnek··on Moving away from Tailwind, and learning to structure my CSS
Who are you talking to?
fluffybucktsnek··on Moving away from Tailwind, and learning to structure my CSS
It should polyfills are basically a no-go for no-JS sites.
fluffybucktsnek··on Moving away from Tailwind, and learning to structure my CSS
TBF, Tailwind is more about optimizing CSS sizes via the utility classes approach IIRC.
fluffybucktsnek··on The people writing AI alignment policy are not whose work is being replaced
While their comment is abbrasive, that's a lot of assumptions about OP. Do you really know what their information source is?

The core point remains valid, you could've just skipped the play on "alt-man" and you wouldn't have muddied your argument.

fluffybucktsnek··on My graduation cap runs Rust
For starters, I'm talking about @Ferret7446's post, so I don't know why you are talking for them.

Still, if the lack of something of note was the main issue, just say that. Nitpicks like these are only informative to people who doesn't know how computers work. They can serve as fun tongue-in-cheeks, but that was seemingly not the intention here.

As it stands, in my eyes, this just a small fun project. How is the title even controversial? Because it has "Rust?"

← PreviousPage 3 of 6Next →