[HN Gopher] Garbage collection for Rust: The finalizer frontier
___________________________________________________________________
Garbage collection for Rust: The finalizer frontier
Author : ltratt
Score : 98 points
Date : 2025-10-15 12:08 UTC (10 hours ago)
(HTM) web link (soft-dev.org)
(TXT) w3m dump (soft-dev.org)
| king_terry wrote:
| The whole point of Rust is to not have a garbage collector while
| not worrying about memory leaks, though.
| GolDDranks wrote:
| The mechanisms that Rust provide for memory management are
| various. Having a GC as a library for usecases with shared
| ownership / handles-to-resources is not out of question. The
| problem is that they have been hard to integrate with the
| language.
| jvanderbot wrote:
| While you're of course correct, there's just something that
| feels off. I'd love if we kept niche, focused-purpose
| languages once in a while, instead of having every language
| do everything. If you prioritize everything you prioritize
| nothing.
| GolDDranks wrote:
| I agree specifically with regards to GC; I think that
| focusing on being an excellent language for low-level
| programming (linkable language-agnostic libraries, embedded
| systems, performance-sensitive systems, high-assurance
| systems etc.) should continue being the focus.
|
| However, this is 3rd party research. Let all flowers bloom!
| sebastianconcpt wrote:
| > If you prioritize everything you prioritize nothing
|
| Well...
|
| If you prioritize everything you prioritize generalism.
|
| (the "nothing" part comes from our natural limitation to
| pay enough multidisciplinary attention to details but that
| psychological impression is being nuked with AI as we speak
| and the efforts to get to AGI are an attempt to make
| synthetic "intelligence" be able to gain dominion over this
| spirit before us)
| virgilp wrote:
| No, they are quite identical. Both cases logically lead
| to "now everything has the same priority". There's
| nothing about generalism in there.
| bryanlarsen wrote:
| Just like when hiring developers, there's an advantage in
| choosing "jack of all trades, master of some".
| IainIreland wrote:
| One clear use case for GC in Rust is for implementing other
| languages (eg writing a JS engine). When people ask why
| SpiderMonkey hasn't been rewritten in Rust, one of the main
| technical blockers I generally bring up is that safe,
| ergonomic, performant GC in Rust still appears to be a major
| research project. ("It would be a whole lot of work" is
| another, less technical problem.)
|
| For a variety of reasons I don't think this particular approach
| is a good fit for a JS engine, but it's still very good to see
| people chipping away at the design space.
| quotemstr wrote:
| Would you plug Boehm GC into a first class JS engine? No?
| Then you're not using this to implement JS in anything
| approaching a reasonable manner either.
| zorgmonkey wrote:
| It looks like the API of Alloy was at least designed in
| such a way that can somewhat easily change the GC
| implementation out down the line and I really hope they do
| cause Boehm GC and conservative GC in general is much too
| slow compared to state of the art precise GCs.
| quotemstr wrote:
| It's not an implementation thing. It's fundamental. A GC
| can't move anything it finds in a conservative root. You
| can build partly precise hybrid GCs (I've built a few)
| but the mere possibility of conservative roots
| complicates implementation and limits compaction
| potential.
|
| If, OTOH, Alloy is handle based, then maybe there's hope.
| Still a weird choice to use Rust this way.
| ltratt wrote:
| We don't exactly _want_ Alloy to have to be conservative,
| but Rust 's semantics allow pointers to be converted to
| usizes (in safe mode) and back again (in unsafe mode),
| and this is something code really does. So if we wanted
| to provide an Rc-like API -- and we found reasonable code
| really does need it -- there wasn't much choice.
|
| I don't think Rust's design in this regard is ideal, but
| then again what language is perfect? I designed languages
| for a long while and made far more, and much more
| egregious, mistakes! FWIW, I have written up my general
| thoughts on static integer types, because it's a
| surprisingly twisty subject for new languages https://tra
| tt.net/laurie/blog/2021/static_integer_types.html
| quotemstr wrote:
| > We don't exactly want Alloy to have to be conservative,
| but Rust's semantics allow pointers to be converted to
| usizes (in safe mode) and back again (in unsafe mode),
| and this is something code really does. So if we wanted
| to provide an Rc-like API -- and we found reasonable code
| really does need it -- there wasn't much choice.
|
| You can define a set of objects for which this
| transformation is illegal --- use something like pin
| projection to enforce it.
| ltratt wrote:
| The only way to forbid it would be to forbid creating
| pointers from `Gc<T>`. That would, for example, preclude
| a slew of tricks that high performance language VMs need.
| That's an acceptable trade-off for some, of course, but
| not all.
| quotemstr wrote:
| Not necessarily. It would just require that deriving
| these pointers be done using an explicit lease that would
| temporarily defer GC or lock an object in place during
| one. You'd still be able to escape from the tyranny of
| conservative scanning everything.
| nitwit005 wrote:
| Once you are generating and running your own machine code,
| isn't the safety of Rust generally out the window?
| hedora wrote:
| Yeah; I wished they'd gone the other way, and made memory leaks
| unsafe (yes, this means no Rc or Arc). That way, you could pass
| references across async boundaries without causing the borrow
| checker to spuriously error out.
|
| (It's safe to leak a promise, so there's no way for the borrow
| checker to prove an async function actually returned before
| control flow is handed back to the caller.)
| dzaima wrote:
| Same as with GC, neither need be a fixed choice; having a GC
| library/feature in Rust wouldn't mean that everything will be
| and must be GC'd; and it's still possible to add unleakable
| types were it desired: https://rust-lang.github.io/keyword-
| generics-initiative/eval... while keeping neat things like
| Rc<T> available for things that don't care. (things get more
| messy when considering defaults and composability with
| existing libraries, but I'd say that such issues shouldn't
| prevent the existence of the options themselves)
| Manishearth wrote:
| Worth highlighting: library-level GC would not be convenient
| enough to use pervasively in Rust _anyway_. library-level GC
| does not replace Rust 's "point".
|
| It's useful to have when you have complex graph structures. Or
| when implementing language runtimes. I've written a bit about
| these types of use cases in
| https://manishearth.github.io/blog/2021/04/05/a-tour-of-safe...
|
| And there's a huge benefit in being able to _narrowly_ use a
| GC. GCs can be useful in gamedev, but it 's a terrible tradeoff
| to _need_ to use a GC 'd language to get them, because then
| everything is GCd. library-level GC lets you GC the handful of
| things that need to be GCd, while the bulk of your program uses
| normal, efficient memory management.
| zorgmonkey wrote:
| This is a very important point, careful use of GCs for a
| special subset of allocations that say have tricky lifetimes
| for some reason and aren't performance critical could have a
| much smaller impact on overall application performance than
| people might otherwise expect.
| James_K wrote:
| Actually, memory leaks are the major class of memory error for
| which Rust offers no protection. See the following safe
| function in Box:
|
| https://doc.rust-lang.org/std/boxed/struct.Box.html#method.l...
| gizmo686 wrote:
| Rust's memory safety guarantees do not insure the absence of
| leaks. However, Rust's design does offer significant
| protection against leaks (relative to languages like C where
| all heap allocations must be explicitly freed).
|
| The fact that any felt it nessasary to add a "leak" function
| to the standard library should tell you something about how
| easy it is to accidentally leak memory.
| umanwizard wrote:
| Not really, modern C++ already makes it about as hard to leak
| memory as it is in Rust.
|
| Rust has loads of other advantages over C++, though.
| ape4 wrote:
| If only there was a C++-like language with garbage collection
| (Java, C#, etc)
| reactordev wrote:
| Latest version of C# is a fantastic choice for this. Java too
| but I would lean more C# due to the new delegate function
| pointers for source-generated p/invoke. Thing of beauty.
| reactordev wrote:
| I also want to call out CppAst [0] and CppAst.CodeGen [1]
| projects. These two things have saved me years of my life if
| I were to roll these by hand. Kudos Alexandre Mutel, kudos.
|
| [0] https://github.com/xoofx/CppAst.NET
|
| [1] https://github.com/xoofx/CppAst.CodeGen
| jerf wrote:
| I can't be an expert in every GC implementation because there
| are so many of them, but many of the problems they mention are
| problems in those languages too. Finalizers are highly
| desirable to both the authors of the runtimes and the users of
| the languages, but are generally fundamentally flawed in GC'd
| languages, to the point that the advice in those languages is
| to stay away from them unless you _really_ know what you are
| doing, and then, to stay away from them even so if you have any
| choice whatsoever... and that 's the "solution" to these
| problems most languages end up going with.
|
| Which does at least generally work. It's pretty rare to be
| bitten by these problems, like, less-than-once-per-career
| levels of rare ( _if_ you honor the advice above)... but
| certainly not unheard of, definitely not a zero base rate.
| gwbas1c wrote:
| Before making criticisms that Garbage Collection "defeats the
| point" of Rust, it's important to consider that Rust has many
| other strengths:
|
| - Rust has no overhead from a "framework"
|
| - Rust programs start up quickly
|
| - The rust ecosystem makes it very easy to compile a command-line
| tool without lots of fluff
|
| - The strict nature of the language helps guide the programmer to
| write bug-free code.
|
| In short: _There 's a lot of good reasons to choose Rust that
| have little to do with the presence or absence of a garbage
| collector._
|
| I think having a working garbage collection at the _application_
| layer is very useful; even if it, at a minimum, makes Rust easier
| to learn. I do worry about 3rd party libraries using garbage
| collectors, because they (garbage collectors) tend to impose a
| lot of requirements, which is why a garbage collector usually is
| tightly integrated into the language.
| jvanderbot wrote:
| You've just listed "Compiled language" features. Only the 4th
| point has any specificity to Rust, and even then, is vague in a
| way that could be misinterpreted.
|
| Rust's predominant feature, the one that brings most of its
| safety and runtime guarantees, is borrow checking. There are
| things I love about Rust besides that, but the safety from
| borrow checking (and everything the borrow checker makes me do)
| is why I like programming in rust. Now, when I program
| elsewhere, I'm constantly checking ownership "in my head",
| which I think is a good thing.
| zamalek wrote:
| - Rust is a nice language to use
| gwbas1c wrote:
| Oh no, I'm directly criticizing C/C++/Java/C#:
|
| The heavyweight framework (and startup cost) that comes with
| Java and C# makes them challenging for widely-adopted
| lightweight command-line tools. (Although I love C# as a
| language, I find the Rust toolchain much simpler and easier
| to work with than modern dotnet.)
|
| Building C (and C++) is often a nightmare.
| hypeatei wrote:
| > The heavyweight framework
|
| Do you mean the VM/runtime? If so, you might be able to
| eliminate that with an AOT build.
|
| > I find the Rust toolchain much simpler and easier to work
| with than modern dotnet
|
| What part of the toolchain? I find them pretty similar with
| the only difference being the way you install them (with
| dotnet coming from a distro package and Rust from rustup)
| jillesvangurp wrote:
| Exactly, natively compiled garbage collected languages
| (like Java with Graal; or as executed on Android) don't
| have a lot of startup overhead. In Java the startup
| overhead is mostly two things that usually conspire to
| make things worse:
|
| 1) dynamic loading of jar files
|
| 2) reflection
|
| Number 1 allows you to load arbitrary jar files with code
| and execute them. Number 2 allows you to programmatically
| introspect existing code and then execute logic like
| "Find me all Foo sub classes and create an instance of
| those and return the list of those objects". You can do
| that at any time but a lot of that kind of stuff happens
| at startup. That involves parsing, loading and
| introspecting thousands of class files in jar files that
| need to be opened and decompressed.
|
| Most of "Java is slow" is basically programs loading a
| lot of stuff at startup, and then using reflection to
| look for code to execute. You don't have to do those
| things. But a lot of popular web frameworks like Spring
| do. A lot of that stuff is actually remarkably quick
| considering what it is doing. You'd struggle to do this
| in many other languages. Or at all because many languages
| don't have reflection. If you profile it, there are
| millions of calls happening in the first couple of
| seconds. It's taking time yes. But that code has also
| been heavily optimized over the years. Dismissing what
| that does as "java is slow" and X is fast is usually a
| bit of an apples and oranges discussion.
|
| With Spring Boot, there are dozens of libraries that self
| initialize if you simply add the dependency or the right
| configuration to your project. We can argue about whether
| that's nice or not; I'm leaning to no. But it's a neat
| feature. I'm more into lighter weight frameworks these
| days. Ktor server is pretty nice, for example. It starts
| pretty quickly because it doesn't do a whole lot on
| startup.
|
| Loading a tiny garbage collector library on startup isn't
| a big deal. It will add a few microseconds to your
| startup time maybe. Probably not milliseconds. Kotlin has
| a nice native compiler. If you compile hello world with
| it it's a few hundred kilobytes for a self contained
| binary with the program, runtime, and the garbage
| collection. It's not a great garbage collector. For
| memory intensive stuff you are better off using the JVM.
| But if that's not a concern, it will do the job.
| procaryote wrote:
| Hello world in java is pretty fast. Not rust fast but a lot
| faster than you'd expect.
|
| Java starting slowly is mostly from all the cruft in the
| typical java app, with springboot, dependency injection
| frameworks, registries etc. You don't have to have those,
| it's just that most java devs use them and can't conceive
| of a world of low dependencies
|
| Still not great for commandline apps, but java itself is
| much better than java devs
| kbolino wrote:
| Java's biggest weakness in this area is its lack of value
| types. It's well known, Project Valhalla has been trying
| to fix it for years, but the JVM just wasn't built around
| such types and it's hard to bolt them on after the fact.
| Java's next biggest weakness (which will become more
| evident with value types) is its type-erased generics.
| Both of these problems lead to time wasted on unnecessary
| GC, and though they _can_ be worked around with arrays
| and codegen, it 's unwieldy to say the least.
| pron wrote:
| Project Valhalla will also specialise generics for value
| types. When you say, "it's hard to bolt on", the
| challenge isn't technical, but how to do this in a way
| that adds minimal language complexity (i.e. less than in
| other languages with explicit "boxed" and "inlined"
| values). Ideally, this should be done in a way that tells
| the compiler know which types _can_ be inlined (e.g. they
| don 't require identity) and then letting the compiler
| decide when it wants to actually inline an instance as a
| transparent optimisation. The challenge would not have
| been any smaller had Java done this from the beginning.
| kbolino wrote:
| Maybe I picked the wrong wording--I don't mean to
| diminish the ambitions or scope of Valhalla--but I
| definitely think the decision to eschew value types at
| the start has immense bearing on the difficulty of adding
| them now.
|
| Java's major competitors, C# and Go, both have had value
| types since day one and reified generics since they
| gained generics; this hasn't posed any major problems to
| either language (with the former being IMO already more
| complex than Java, but the latter being similarly or even
| less complex than Java).
|
| If the technical side isn't that hard, I'd have expected
| the JVM to have implemented value types already, making
| it available to other less conservative languages like
| Kotlin, while work on smoothly integrating it in Java
| took as long as needed. Project Valhalla is over a decade
| old, and it still hasn't delivered, or even seems close
| to delivering, its primary goals yet.
|
| Just to be clear, I don't think every language needs to
| meet every need. The lack of value types is not a
| critical flaw of Java in general, as it only really
| matters when trying to use Java for certain purposes.
| After all, C# is very well suited to this niche; Java
| doesn't _have_ to fit in it too.
| pron wrote:
| > Java's major competitors, C# and Go, both have had
| value types since day one
|
| Yes (well, structs; not really value types), but at a
| significant cost to FFI and/or GC and/or user-mode
| threads (due to pointers into the stack and/or middle of
| objects). Java would not have implemented value types in
| this way, and doing it the way we want to would have been
| equally tricky had it been done in Java 1.0. Reified
| generics also come at a high price, that of baking the
| language's variance strategy into the ABI (or VM, if you
| want). However, value types will be invariant (or
| possibly extensible in some different way), so it would
| be possible to specialise generics for them without
| necessarily baking the Java language's variance model
| into the JVM (as the C# variance model is baked into the
| CLR).
|
| Also, C# and Go didn't have as much of a choice, as their
| optimising compilers and GCs aren't as sophisticated as
| Java's (e.g. Java doesn't actually allocate every `new`
| object on the heap). Java has long tried to keep the
| language as simple as possible, and have very advanced
| compilers and GCs.
|
| > If the technical side isn't that hard, I'd have
| expected the JVM to have implemented value types already,
| making it available to other less conservative languages
| like Kotlin, while work on smoothly integrating it in
| Java took as long as needed
|
| First, that's not how we do things. Users of all
| alternative Java Platform languages (aka alternative JVM
| languages) combined make up less than 10% of all Java
| platform users. We work on the language, VM, and standard
| library all together (this isn't the approach taken by
| .NET, BTW). We did deliver invokedynamic before it was
| used by the Java language, but 1. that was _after_ we
| knew how the language would use it, and 2. that was at a
| time when the JDK 's release model was much less
| flexible.
|
| Second, even if we wanted to work in this way, it
| wouldn't have mattered here. Other Java Platform
| languages don't _just_ use the JVM. They make extensive
| use of the standard library and observability tooling.
| Until those are modified to account for value types, just
| a JVM change would be of little use to those languages.
| The JVM comprises maybe 25% of the JDK, while Kotlin, for
| example, makes use of over 95% of the JDK.
|
| Anyway, Project Valhalla has taken a very long time, but
| it's making good progress, and we hope to deliver some of
| its pieces soon enough.
| pjmlp wrote:
| Currently it takes lots of boilerplate code, however with
| Project Panama API you can model C types in memory, thus
| kind of already using value types even if Valhala isn't
| yet here.
|
| To avoid manually writing all the Panama boilerplate, you
| can instead write a C header file with the desired types,
| and then run jextract through it.
| gizmo686 wrote:
| Testing on my machine, Hello World in java (openjdk 21)
| takes about 30ms.
|
| In contrast, "time" reports that rust takes 1ms, which is
| the limit of it's precision.
|
| Python does Hello World in just 8ms, despite not having a
| separate AOT compilation step.
|
| The general guidance I've seen for interaction is that
| things start to feel laggy at 100ms; so 30ms isn't a
| dealbreaker, but throwing a third of your time budget at
| the baseline runtime cost is a pretty steep ask.
|
| If you want to use the application as a short lived
| component in a larger system, than 30ms on every
| invocation can be a massive cost.
| zigzag312 wrote:
| App that actually does something will probably have even
| larger startup overhead in Java as there will be more to
| compile just-in-time.
| pjmlp wrote:
| Only when not using either AOT or JIT cache.
| 0cf8612b2e1e wrote:
| I recall that Mercurial was really fighting their Python
| test harness. It essentially would startup a new Python
| process for each test. At 10ms per, it added up to
| something significant, given their volume of work to
| cover something as complicated as SCM.
| guelo wrote:
| I'm trying and failing to imagine a situation where 30ms
| startup time would be a problem. Maybe some kind of
| network service that needs to execute a separate process
| on every request?
| tacticus wrote:
| 30ms is the absolute best case. Throw some spring in
| there and you're very quickly at 10s. rub some spring-
| soap and it's near enough to 60s
| ComputerGuru wrote:
| New AOT C# is nice, but not fully doable with the most
| common dependencies. It addresses a lot of the old issues
| (size, bloat, startup latency, etc)
| quotemstr wrote:
| Heavyweight startup? What are you talking about? A Graal-
| compiled Java binary starts in a few milliseconds. Great
| example of how people don't update prejudices for decades.
| pjmlp wrote:
| Only for those that don't know how to use AOT compilation
| tools for Java and C#.
| jraph wrote:
| GraalVM indeed do wonders wrt startup times and in
| providing a single binary you can call.
| jrop wrote:
| Just going to jump in here and say that there's another
| reason I might want Rust with a Garbage Collector: The
| language/type-system/LSP is really nice to work with. There
| have indeed been times that I really miss having enums +
| traits, but DON'T miss the borrow checker.
| tuveson wrote:
| Maybe try a different ML-influenced language like OCaml or
| Scala. The main innovation of Rust is bringing a nice ML-
| style type system to a more low level language.
| Yoric wrote:
| Jane Street apparently has a version of OCaml extended
| with affine types. I'd like to test that, because that
| would (almost) be the best of all worlds.
| nobleach wrote:
| I think you're referring to OxCaml. I'd love to see this
| make a huge splash. Right now one of the biggest
| shortcomings of OCaml, is one is still stuck implementing
| so much stuff from scratch. Languages like Rust, Go and
| Java have HUGE ecosystems. OCaml is just as old (even
| older than Rust since OCaml inspired Rust and its
| original compiler was written in OCaml) as these
| languages. Since it's not been as popular, it's hard to
| find well-supported libraries.
| umanwizard wrote:
| There are other nice things about Rust over OCaml that
| are mainly just due to its popularity. There are
| libraries for everything, the ecosystem is polished, you
| can find answers to any question easily, etc. I don't
| think the same can be said for OCaml, or at least not to
| the same extent. It's still a fairly niche language
| compared to Rust.
| nobleach wrote:
| I remember about 5 years ago, StackOverflow for OCaml was
| a nightmare. It was a mishmash of Core (from Jane Street)
| Batteries, and raw OCaml. New developers were confronted
| with the prospect of opening multiple libraries with the
| same functionality. (not the correct way of solving any
| problem)
| tayo42 wrote:
| What other language has modern features like rust and is
| compiled?
| procaryote wrote:
| it depends completely on what you put in "modern features"
| tayo42 wrote:
| Pattern matching, usable abstractions, non null types,
| tagged unions or w/e enums are, build tools etc
| munificent wrote:
| I'm not sure what you mean by "usable abstractions" and
| tagged unions are a little verbose because they are
| defined in terms of closed sets of subtypes, but
| otherwise Dart has all of those.
| tayo42 wrote:
| Nothing like "oh you can do that but with this weird work
| around" or if they're clunky to use
| procaryote wrote:
| This sounds more like "this is what I like in rust" than
| "features any modern language should have" though
|
| If you like rust, use rust. It's very likely the best
| rust
| pjmlp wrote:
| Standard ML from 1983, alongside all those influenced by
| it like Haskell, OCaml, Agda, Rocq,....
| cultofmetatron wrote:
| nim, zig and ocaml come to mind
| gizmo686 wrote:
| Also, the proposed garbage collector is still opt in. Only
| pointers that are specifically marked as GC are garbage
| collected. This means that most references are still cleaned up
| automatically when the owner goes out of scope. This greatly
| reduces the cost of GC compared to making all heap allocations
| garbage collected.
|
| This isn't even a new concept in Rust. Rust already has a well
| accepted RC<T> type for reference counted pointers. From a
| usage perspective, GC<T> seems to fit in the same pattern.
| zigzag312 wrote:
| Language where most of the libraries are without GC, but has
| an GC opt in would be interesting. For example only your
| business logic code would use GC (so you can write it more
| quickly). And parts where you don't want GC are still written
| in the same language, avoiding the complexity of FFI.
|
| Add opt-in development compilation JIT for quick iteration
| and you don't need any other language. (Except for user
| scripts where needed.)
| yoyohello13 wrote:
| I love the rust ecosystem, syntax, and type system. Being able
| to write Rust without worrying about ownership/lifetimes sounds
| great honestly.
| rixed wrote:
| In all honesty, there are three topics I try to refrain myself
| from engaging with on HN, often unsuccesfully: politics,
| religion, and rust.
|
| I don't know what you had to go through before reaching rust's
| secure haven, but what you just said is true for the vast
| majority of compiled languages, which are legions.
| quotemstr wrote:
| It's the fledging of a new generation of developers. Every
| time I see one of these threads I tell myself, "you, too,
| were once this ignorant and obnoxious". I don't know any cute
| except letting them get it out of their system and holding my
| nose as they do.
| James_K wrote:
| Go is probably a better pick in this case.
| victorbjorklund wrote:
| Also assuming one can mix garbage collection with the borrower
| (is that what its called in rust?) one should be able to use GC
| for things that arent called that much / that important and use
| the normal way for things that benefit from no GC interupts etc
| imtringued wrote:
| The problem with conventional garbage collection has very
| little to do with the principle or algorithms behind garbage
| collection and more to do with the fact that seemingly every
| implementation has decided to only support a single heap. The
| moment you can have isolated heaps almost every single problem
| associated with garbage collection fades away. The only thing
| that remains is that cleaning up memory as late as possible is
| going to consume more memory than doing it as early as
| possible.
| tuveson wrote:
| What problem does that solve with GC, specifically? It also
| seems like that creates an obvious new problem: If you have
| multiple heaps, how do you deal with an object in heap A
| pointing to an object in heap B? What about cyclic
| dependencies between the two?
|
| If you ban doing that, then you're basically back to manual
| memory management.
| grogers wrote:
| BEAM (i.e. erlang) is exactly that model, every lightweight
| process has its own heap. I don't see how you'd make that
| work in a more general environment that supports sharing
| pointers across threads.
| fithisux wrote:
| I really like your work
| jadenPete wrote:
| Rust's choice of constructs also makes writing safe and
| performant code easy. Many other compiled languages lack proper
| sum and product types, and traits (type classes) offer
| polymorphism without many of the pitfalls of inheritance, to
| name a few.
| torginus wrote:
| While I'm not ideologically opposed to GC in Rust I have to note:
|
| - the syntax is hella ugly
|
| - GC needs some compiler machinery, like precise GC root tracking
| with stack maps, space for tracking visted objects, type infos,
| read/write barriers etc. I don't know how would you retrofit this
| into Rust without doing heavy duty brain surgery on the compiler.
| You can do conservative GC without that, but that's kinda lame.
| taylorallred wrote:
| For those who are interested, I think that arena allocation is an
| underrated approach to managing lifetimes of interconnected
| objects that works well with borrow checking.
| worik wrote:
| > works well with borrow checking.
|
| Yes, because it defeats borrow checking.
|
| Unsafe Rust, used directly, works too
| celeritascelery wrote:
| It does not defeat borrow checking. The borrow checker will
| ensure that objects do not outlive the arena. It works with
| borrow checking.
| Archit3ch wrote:
| This. Arenas don't work when you don't know when it's okay
| to free. The borrow checker can help with that (or you can
| track it manually in C/Zig).
| haberman wrote:
| I agree, but in my experience arena allocation in Rust leaves
| something to be desired. I wrote something about this here:
| https://blog.reverberate.org/2021/12/19/arenas-and-rust.html
|
| I was previously excited about this project which proposed to
| support arena allocation in the language in a more fundamental
| way: https://www.sophiajt.com/search-for-easier-safe-systems-
| prog...
|
| That effort was focused primarily on learnability and
| teachability, but it seems like more fundamental arena support
| could help even for experienced devs if it made patterns like
| linked lists fundamentally easier to work with.
| Dwedit wrote:
| There was one time where I actually had to use object
| resurrection in a finalizer. It was because the finalizer needed
| to acquire a lock before running destruction code. If it couldn't
| acquire the lock, you resurrect the object to give it a second
| chance to destroy (calling GC.ReRegisterForFinalize)
| nu11ptr wrote:
| While it might be useful for exploration/academic pursuit/etc.,
| am I the only one who finds "conservative GC" a non-starter? Even
| if this was fully production ready, I had a use case for it, etc.
| I still would never ship an app with a conservative GC. It is
| difficult enough to remove my own bugs and non-determinism, and I
| just can't imagine trying to debug a memory leak caused due to a
| conservative GC not finding all used memory.
| ltratt wrote:
| If you've used Chrome or Safari to read this post, you've used
| a program that uses (at least in parts) conservative GC. [I
| don't know if Firefox uses conservative GC; it wouldn't
| surprise me if it does.] This partly reflects shortcomings in
| our current compilers and in current programming language
| design: even Rust has some decisions (e.g. pointers can be put
| in `usize`s) that make it hard to do what would seem at first
| glance to be the right thing.
| astrange wrote:
| Also most mobile games written in C# use a conservative GC
| (Boehm).
| Rohansi wrote:
| Not just mobile games - all games made with Unity.
| gwbas1c wrote:
| > Having acknowledged that pointers can be 'disguised' as
| integers, it is then inevitable that Alloy must be a conservative
| GC
|
| C# / dotnet don't have this issue. The few times I've needed a
| raw pointer to an object, first I had to pin it, and then I had
| to make sure that I kept a live reference to the object while
| native code had its pointer. This is "easier done than said"
| because most of the time it's passing strings to native APIs,
| where the memory isn't retained outside of the function call, and
| there is always a live reference to the string on the stack.
|
| That being said, because GC (in this implementation) is opt-in, I
| probably wouldn't mix GC and pointers. It's probably easier to
| drop the requirement to get a pointer to a GC<T> instead of
| trying to work around such a narrow use case.
| quotemstr wrote:
| Worse, conservatism in a GC further implies it can't be a
| moving GC, which means you can't compact, use bump pointer
| allocation, and so on. It keeps you permanently behind the
| frontier.
|
| I remain bitterly disappointed that so much of the industry is
| so ignorant of the advances of the past 20 years. It's like
| it's 1950 and people are still debating whether their cloth and
| wood airplanes should be biplanes or triplanes.
| gwbas1c wrote:
| The thing I don't understand is why anyone would pass a
| pointer to a GC'ed object into a 3rd party library (that's in
| a different language) and expect the GC to track the pointer
| there?
|
| Passing memory into code that uses a different memory manager
| is always a case where automatic memory management _shouldn
| 't_ be used. IE, when I'm using a 3rd party library in a
| different language, I don't expect it to know enough about my
| language's memory model to be able to effectively clean up
| pointers that I pass to it.
| GolDDranks wrote:
| Also, Rust is not going to have it for the long run that
| pointers can be, in fact, disguised as integers. There is this
| thing called pointer provenance, and some day, all pointers are
| required to have provenance (i.e. a proof where they did come
| from) OR they are required to admit that _POOF_ this is a
| pointer out of thin air, you can 't assume anything about the
| pointee. As long as there are no POOF magicians, the GC can
| assume that it knows every reference!
| celeritascelery wrote:
| > As long as there are no POOF magicians, the GC can assume
| that it knows every reference!
|
| creating pointers without provenance is safe, so the GC can't
| assume that a program won't have them also be sound. This
| always be an issue.
| MereInterest wrote:
| Even their so-called conservative assumption is also
| insufficient.
|
| > if a machine word's integer value, when considered as a
| pointer, falls within a GCed block of memory, then that block
| itself is considered reachable (and is transitively scanned).
| Since a conservative GC cannot know if a word is really a
| pointer, or is a random sequence of bits that happens to be the
| same as a valid pointer, this over-approximates the live set
|
| Suppose I allocate two blocks of memory, convert their pointers
| to integers, then store the values `x` and `x^y`. At this
| point, no machine word points to the second allocation, and so
| the GC would consider the second allocation to be unreachable.
| However, the value `y` could be computed as `x ^ (x^y)`,
| converted back to a pointer, and accessed. Therefore, their
| reachability analysis would under-approximate the live set.
|
| If pointers and integers can be freely converted to each other,
| then the GC would need to consider not just the integers that
| currently exist, but also every integer that could be produced
| from the integers that currently exist.
| vsgherzi wrote:
| No has seemed to call it out yet but swift uses a form of garbage
| collection but remains relatively fast. I was against this at
| first but the more I think about it, I think it has real
| potential to make lots of hard problems with ownership easier to
| solve. I think the next big step or perhaps an alternative would
| be to make changes to restrictions in unsafe rust.
|
| I think the pursuit of safety is a good goal and I could see
| myself opting into garbage collections for certain tasks.
| worik wrote:
| Swift uses reference counting
|
| Slows down every access to objects as reference counts must be
| maintained
|
| Something weird that I never bothered with to enable circular
| references
| marcianx wrote:
| Reference counted pointers can deference an object (via a
| strong pointer) without checking the reference count. The
| reference count is accessed only on operations like clone,
| destruction, and such. That being said, access via a weak
| pointer does require a reference count check.
| worik wrote:
| I have thought for years Rust needs to bifurcate.
|
| Asyc/await really desperately needs a garbage collector. (See
| this talk from Rustconf 2025:
| https://youtu.be/zrv5Cy1R7r4?si=lfTGLdJOGw81bvpu and this
| blog:https://rfd.shared.oxide.computer/rfd/400)
|
| Rust that uses standard techniques for asynchronous code, or is
| synchronous, does not. Async/await sucks all the oxygen from
| asynchronous Rust
|
| Async/await Rust is a different language, probably more popular,
| and worth pursuing (for somebody, not me) it already has a
| runtime and the dreadful hacks like (pin)[https://doc.rust-
| lang.org/std/pin/index.html] that are due to the lack of a
| garbage collector
|
| What a good idea
| sunshowers wrote:
| Hi -- I'm the one who presented the talk -- honored!
|
| I'm curious how you got to "async Rust needs a [tracing]
| garbage collector" in particular. While it's true that a lot of
| the issues here are downstream of futures being passive (which
| in turn is downstream of wanting async to work on embedded),
| I'm not sure active futures need a tracing GC. Seems to me like
| Arc or even a borrow-based approach would work, as long as you
| can guarantee that the future is dropped before the scope exits
| (which admittedly isn't possible in safe Rust today [0]).
|
| [0]: https://without.boats/blog/the-scoped-task-trilemma/
| fithisux wrote:
| Very important paper.
| sebastianconcpt wrote:
| I'm curious about the applicability.
|
| If memory management is already resolved with the borrow checker
| rules, then what case can make you want a GC in a Rust program?
| trueismywork wrote:
| Lock free programming..
| dajonker wrote:
| Implementing a doubly linked list without either unsafe or some
| very confusing code that could arguably win an obfuscation
| contest.
| FridgeSeal wrote:
| I don't understand the desire to staple a GC into Rust.
|
| If you want this, you might just...want a different language?
| Which is fine and good! Putting a GC on Rust feels like putting
| 4WD tyres on a Ferrari sports car and towing a caravan with it.
| You could (maybe) but it feels like using the wrong tool for the
| job.
| dajonker wrote:
| If I understand the article correctly it's for those cases
| where you want memory safety (i.e. not using "unsafe") but
| where the borrow checker is really hard to work with such as a
| doubly linked list, where nodes can point to each other.
|
| For the rest you'd still use non-GC rust.
| FridgeSeal wrote:
| I just foresee it become irrevocably viral, as it becomes the
| "meh, easier" option, and then suddenly half your crates
| depend on it, and then you're losing one of the major
| advantages of the language.
| zozbot234 wrote:
| A doubly linked list is not the optimal case for GC. It can
| be implemented with some unsafe code, and there are
| approaches that implement it safely with GhostCell (or
| similar facilities, e.g. QCell) plus some zero-overhead
| (mostly) "compile time reference counting" to cope with the
| invariants involved in having multiple references
| simultaneously "own" the data. See e.g.
| https://github.com/matthieu-m/ghost-collections for details.
|
| Where GC becomes necessary is the case where even static
| analysis cannot really mitigate the issue of having multiple,
| possibly cyclical references to the same data. This is
| actually quite common in some problem domains, but it's not
| quite as simple as linked lists.
___________________________________________________________________
(page generated 2025-10-15 23:00 UTC)