1. 43
  1.  

  2. 4

    To highlight the explicitness angle, because it’s the aspect that really stood out to me when I learned Rust:

    Swift and Rust both have a form of “automatic compile-time memory management” but the conversation with the compiler is quite different. In Swift you say where you want to be able to reference a thing and the compiler figures out the most efficient way to make sure it’s still there when you want it. In Rust you develop your own strategy for keeping the thing around and tell the compiler exactly what it is, then it verifies that what you told it to do makes sense.

    And of course with languages that have implicit GC, you do whatever you want and the runtime frees memory that it can prove you’ll never be able to reference.

    1. 4

      Hmff. “Static garbage collection” is a contradiction in terms. Garbage collection is dynamic. What the author is referring to is actually (the badly named) RAII, “resource acquisition is initialisation”, an idiom that has been an essential part of C++ since its inception and possibly pre-dates even that. (Yes, Rust adds a borrow checker, but this does not facilitate memory management, just prevents certain classes of logic error).

      Edit: let me elaborate a little. Rust’s borrow checker, though it performs an analysis that has similarities with escape analysis, is nothing to do with memory management - it checks that the program doesn’t violate certain rules, with the goal of memory safety. The actual lifetime of objects in Rust is determined by their scope, or (for heap allocated objects) via essentially the same RAII paradigm that is found in C++ - that is, the lifetime of Rust objects is not affected by the borrow checker. Rust memory management is actually very similar to that of C++.

      So, if you want to claim that “Rust has a static garbage collector”, you are really also claiming that C++ has a static garbage collector. I suspect people would be much more reluctant to accept that claim.

      I also suspect people are thinking, “but - Rust is memory safe! Like a garbage collected language!” and that is wrong, not because Rust isn’t memory safe, but because garbage collection does not actually imply memory safety - It is perfectly possible to have a language which uses garbage collection but which is no safer than C or C++, and in fact, it is possible to use a garbage collector in C or C++.

      So, the only way that “Rust has a static garbage collector” holds up is if you accept that “C++ also has a static garbage collector”. If you’re willing to take up that argument, well, I’m not willing to die on this particular hill; I’ll let you have your “static garbage collector” and wish you all the best with it.

      (Note that one fundamental difference between typical garbage collected systems and RAII-based systems is that GC’d languages typically don’t define the lifetime of objects by their scope. That is, it is perfectly possible for an object to remain alive, and referenced, once its scope has ended. In Rust, this isn’t true, and the compiler ensures it. This is another reason why I think “Rust has a gc” is a somewhat flawed claim).

      I don’t buy the arguments below that the article is tongue-in-cheek or just making the claim for illustrative purposes (and even if it was the latter, the illustration would be quite flawed, for reasons I’ve outlined above). Why not? Because it reads as a reasoned piece concluding reasonably firmly that the memory management of Rust is “proving [sic] out a new niche in the concept of garbage collection”.

      That’s my piece said. I wouldn’t have bothered but I know I’m getting downvotes and it seems likely that people didn’t really understand what I was saying, so here it is. Or maybe they just disagree - that’s fine; as my Grandad used to say, “you have the right to disagree, even if you are wrong”. :-)

      1. 5

        Hm, “garbage collection” is when the city pulls a truck up to my apartment every Monday to whisk away garbage I’ve used.

        It turns out that actual garbage trucks arrive on a schedule which one could say is statically determined. In some cities, you’re not allowed to put out trash unless it’s within 24 hours of garbage collection. Rust’s memory management maps on to actual real-world collecting-of-garbage a bit better than what we usually think of as GC.

        What I took away from (reading) the article is that there is middle-ground between “manual memory management” and “dynamic garbage collection.” In (safe) rust, you don’t manually allocate or free memory. You obey a set of rules for “owning” and “borrowing” data (one could say that the borrow checker is part of the type system…), and the compiled machine code includes code for allocating and freeing data. A program to allocate and free data at runtime sounds a lot like a garbage collector to me!

        1. 2

          Hm, “garbage collection” is when the city pulls a truck up to my apartment every Monday to whisk away garbage I’ve used.

          Reminds me of a friend who had to explain to relatives about how his PhD was on “garbage collection” :)

          In (safe) rust, you don’t manually allocate or free memory. You obey a set of rules for “owning” and “borrowing” data (one could say that the borrow checker is part of the type system…), and the compiled machine code includes code for allocating and freeing data. A program to allocate and free data at runtime sounds a lot like a garbage collector to me!

          So C++ also has a static garbage collector, then?

          (and yeah, I know that since C++11 it can theoretically have an actual dynamic garbage collector. But forget that for the moment).

          Because: there’s fundamentally no difference between how Rust manages memory and how C++ does (ignoring heap allocations via new and delete, which are generally considered non-idiomatic these days anyway).

          The borrow checker provides safety. It’s making sure you don’t get certain run-time errors. But it’s not affecting allocation or deallocation in any significant way. And static-vs-dynamic aside, there are some fundamental differences between how GCd languages typically handle object lifetimes compared to how Rust does. And that’s my real point: “garbage collection” actually has an established meaning that is far beyond just “allocates and frees data at runtime” (unconstrained dynamic liveness analysis is a big part of it).

          1. 1

            Because: there’s fundamentally no difference between how Rust manages memory and how C++ does (ignoring heap allocations via new and delete, which are generally considered non-idiomatic these days anyway).

            It’s a bit remarkable how, on the one hand, you’re derailing the comments on this blog post to insist on a trivial and nearly useless distinction-without-a-difference between “Garbage Collection” and “Automated Memory Management Which Does Not Involve a Runtime Tracking Component” which you feel the title doesn’t respect, and yet on the other hand wildly handwaving away the profound differences between a language that ensures that all heap allocations are deallocated once they cease to be alive and a language that absolutely does not do anything of the sort.

            Pick a lane, my friend. Are we being pedantic about the minutiae memory management, or are we throwing caution to the wind and equating distinctly different things based on broad similarities of concept?

            1. 0

              Pick a lane, my friend

              How about you stop being patronising?

              you’re derailing the comments on this blog post

              What, you mean I’m disagreeing with what other people are saying? What a terrible person I must be. Oh but wait, mine is the comment at the top of the chain; it was the people who disagreed with it that are “derailing” my comment, surely?

              to insist on a trivial and nearly useless distinction-without-a-difference between “Garbage Collection” and “Automated Memory Management Which Does Not Involve a Runtime Tracking Component”

              If the fundamental differences between garbage collection and other automatic memory management techniques are taken away, what’s left? Why even bother giving it a name, in that case? Let’s just say everything has garbage collection, that would be easier?

              It is totally wrong that the distinction is useless. Garbage collection has performance / heap size implications that are very significant, and for a “pure GC” language usually has implications on how lifetime is managed (as I’ve discussed in other posts). Most of all it implies that memory reclamation works via a particular technique with certain characteristics. I want “this language over here uses garbage collection” to retain some useful meaning.

              on the other hand wildly handwaving away the profound differences between a language that ensures that all heap allocations are deallocated once they cease to be alive and a language that absolutely does not do anything of the sort.

              It’s perfectly possible to have both GC-managed memory and non-GC-managed memory in one program. So the fact that you can do explicit heap allocations and deallocations - as well as RAII - in C++ just isn’t signficant to this discussion. If I make use of an unsafe crate in Rust which allows unchecked memory allocation and deallocation, does that now mean Rust no longer has a “static garbage collector”?

        2. 10

          The post attempts to examine what these terms really mean in practice and break down artificial silos of definition. It seems like this comment disregards the entire premise.

          Escape analysis is to the borrow checker, as “dynamic garbage collection” is to “static garbage collection”, AKA RAII.

          1. 6

            Escape analysis is to the borrow checker, as “dynamic garbage collection” is to “static garbage collection”, AKA RAII.

            But it’s not. From the article:

            instead of saying “oh, this escapes, so allocate it on the heap”, the borrow checker says “oh, this escapes, so error at compile time.”

            That’s key here; as I said, the borrow checker doesn’t facilitate memory management - it just prevents certain code structures (and in doing so prevents certain classes of errors).

            I don’t think the “artificial silos” of definition are artificial at all. Garbage collection has a clear meaning in the literature and RAII/scoped lifetime is clearly not it.

            1. 9

              Again, the entire disagreement just boils down to “garbage collection always means dynamic garbage collection”, which the original post disagrees with. What literature are you referring to?

              1. 6

                The past few decades of discussion around memory management in languages like, say, C++ versus Java, has contrasted “explicit memory management” using RAII, with “garbage collection” or “automatic memory management”, using a dynamic collector. You could argue that this dichotomy has always been incorrect. You could alternately argue that it was correct for C++/Java, but significantly different for rust. This post seems to hint in a 1-paragraph aside that its author believes the terminology has always been incorrect. But it doesn’t elaborate. If the argument is that people discussing C++ style memory management (in academia, industry, anywhere) have been using terms wrongly for decades, I would expect more digging into why that is, versus just flatly saying they were using the terms wrong.

                1. 6

                  This article is pretty clearly not waging a war on the established meanings of terms.

                  Taking some creative license with an article title is not the same as mounting an attack on terms with established meanings for decades.

                  1. 5

                    It’s not just the title, though:

                    Similar to the dichotomy between static and dynamic typing, I think that Rust is proving out a new niche in the concept of garbage collection. That is, historically, we think of GC as something dynamic, that is, it involves a run-time component that does stuff at runtime. However, the idea of automatic memory management doesn’t inherently mean that it has to execute at runtime.

                    The problem is that it’s conflating “memory management where deallocation does not require an additional construct in the program” with “automatic memory management”, a well-established term which refers to dynamic determination of liveness and subsequent clean-up of non-live objects. Yes, the first is memory management which is automatic, but it’s not what is meant by “automatic memory management” (or especially “garbage collection”).

                2. 4

                  What literature are you referring to?

                  Basically all literature on garbage collection refers to it as a dynamic determination of liveness. Even the wikipedia page (https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)) distinguishes “garbage collection” from “stack allocation” and “region inference”, the latter two of which arguably are what Rust actually provides.

                  (One of the experts in GC is Richard Jones, who as it happens I know personally. He maintains a page with links to some literature, here: https://www.cs.kent.ac.uk/people/staff/rej/gc.html).

                  If the original post disagrees with that, then I disagree with the original post. The difference is that there are years of literature which use the term to mean what I think it means…

            2. 3

              I’m pretty sure “static garbage collection” is being used in a tongue-in-cheek manner.

              1. 1

                I don’t think it is. From the article:

                However, the idea of automatic memory management doesn’t inherently mean that it has to execute at runtime.

                The argument is that Rust decides lifetimes statically, but there is no explicit manual deallocation necessary, so it’s still “automatic” memory management, where “automatic memory management” is synonymous with “garbage collection”. I take issue because “automatic memory management” (and “garbage collection”) has come to mean, over several decades prior, something more than just “does not require explicit deallocation by the program”.

                If you took the argument to its logical conclusion, even C has automatic memory management (for local variables): if you declare a local variable, it gets space allocated on the stack when the function is entered, and the space is freed when the function returns - “automatically”.

                1. 5

                  here “automatic memory management” is synonymous with “garbage collection”

                  I don’t think I’ve ever heard anyone say this rigidly. I’ve certainly heard folks talk about garbage collection as a form of automatic memory management, and I’ve heard the terms used interchangeably. But including region analysis in the umbrella of automatic memory management seems more than fair. See: http://www.memorymanagement.org/glossary/a.html#term-automatic-memory-management (Interestingly, that glossary draws a distinction between “automatic memory management” and “automatic storage duration,” which corresponds to what C does for stack allocation.)

                  It’s kind of like how in some circles, “garbage collection” has become synonymous with “tracing garbage collection,” even though there are more interesting particulars to tease out of those definitions. Usually the context makes it clear which is implied, but we Internet folk still can’t resist the urge to get into a good ol’ fashioned war over over definitions, which typically results in nothing but a giant waste of time.

                  Maybe it would be better to just use “region based memory management” to describe Rust. It is undoubtedly a more precise term. But I don’t think “automatic memory management” is outright wrong, certainly not to the extent that you’ve expressed.

                  1. 2

                    here “automatic memory management” is synonymous with “garbage collection”

                    I don’t think I’ve ever heard anyone say this rigidly

                    I meant “here” as in “in the context of the above quote from the article”. Because, from the article, emphasis added:

                    Historically, there has been two major forms of GC: reference counting, and tracing. The argument happens because, with the rise of tracing garbage collectors in many popular programming languages, for many programmers, “garbage collection” is synonymous with “tracing garbage collection.” For this reason, I’ve been coming around to the term “automatic memory management”, as it doesn’t carry this baggage.

                    That is equating “GC” with “automatic memory management”. Whether they are generally considered to be exactly the same thing is not really relevant to the point I was making, which was that “garbage collection” has an established meaning which doesn’t match the usage in the article.

                    But I don’t think “automatic memory management” is outright wrong, certainly not to the extent that you’ve expressed.

                    I think it is outright wrong if you take “automatic memory management” to mean “garbage collection”, which the article does, and if you accept the established meaning for “garbage collection”.

                    Edit: I’d be happier if it said “Rust has a form of automatic memory management” and never said anything about garbage collection. But then, it wouldn’t be anything special to Rust. The point that it almost (and probably should’ve) makes instead is that Rust, compared to other langeuages (such as C++) which give you the same form of “automatic memory management”, also gives you one of the main benefits also found in many garbage collected languages: memory safety. But that would hardly be news.

                    1. 3

                      That is equating “GC” with “automatic memory management”.

                      Uh, really? That’s now how I read it. That there exists a distinction is pretty clear if you keep reading:

                      Similar to the dichotomy between static and dynamic typing, I think that Rust is proving out a new niche in the concept of garbage collection. That is, historically, we think of GC as something dynamic, that is, it involves a run-time component that does stuff at runtime. However, the idea of automatic memory management doesn’t inherently mean that it has to execute at runtime.

                      So I’m not really sure what you’re getting at here… To be frank, when I first saw your top comment, I thought you just read the title, reacted negatively to it, and then commented. (I can’t stand those types of comments, which is why I commented in the first place. But I’ve failed spectacularly at that approach; I didn’t anticipate you digging in your heels.) Because the article never actually talks about what “static garbage collection” even is. It’s just a title with some creative license. Pointing out its “contradictory” nature is completely missing the point.

                      Like, can you imagine? Let’s say I’m talking with someone who isn’t familiar with Rust. I say, “yeah it’s like having a static garbage collector.” But then here’s @davmac, “WELL ACTUALLY, that’s a contradiction.” “Well… yeah, I’m just using the term for illustrative purposes.” See? No big deal. We aren’t upending established terminology. Just explaining concepts.

                      And hey, yeah, maybe terms change meaning over time. It happens. Try telling someone the definition of “regular expression” and how \b(\w+)\1\b is totally not a regex for finding repetitious words. ;-)

                      1. 2

                        Uh, really?

                        Uh, yeah? No need to get nasty here.

                        That there exists a distinction is pretty clear if you keep reading

                        I honestly don’t see the paragraph you quote as making any distinction between AMM and GC. In my eyes, it’s clearly using them synonomously.

                        So I’m not really sure what you’re getting at here…

                        I think I’ve made that clear, frankly.

                        Because the article never actually talks about what “static garbage collection” even is

                        It does, in the paragraph you yourself quoted. Where it says “Rust is proving out a new niche in the concept of garbage collection” it’s distinctly claiming that what Rust provides is a form of garbage collection (also indicated by the title). Where it says that “the idea of automatic memory management doesn’t inherently mean that it has to execute at runtime” it is making a static-vs-dynamic distinction. It is saying that “the form of memory management that Rust provides is static garbage collection” - both directly in the title, and more elaborately in that paragraph.

              2. 2

                All of this is addressed in the article, and is pretty much beside the point.

              3. 3

                All the resonant truths in this article lay waiting in the asides.

                The idea that it’s easy for me because I’m an amazing programmer is not an answer I’m willing to accept here, both because I don’t think that’s particularly true, but also because I’ve seen Rust have a pretty wide appeal to a fairly large group of people, and they can’t all be amazing programmers. It’s just math.

                Have you considered that it might greatly depend on the application domain?

                I should mention that C++ paved a lot of the path here too, so maybe the above is worded too strongly. I do think that Rust is significantly different here, but you may not. If you don’t, please replace the above with “Rust is continuing to prove out a niche pioneered by C++,” and that’s fine by me.

                I think I will. 😉

                I agree with much of u/davmac’s assessment of the article. From what I’ve seen, Rust’s memory management model primarily contributes memory safety (viz. borrowing) and lifetimes to C++’s minimalist RAII approach to memory management. Otherwise, it’s the same “static garbage collection” (scare quotes intended)—just with a prettier, more cohesive interface. No more or less static/dynamic.

                1. 1

                  I guess one complication here is that Rust also supports reference counting:

                  https://doc.rust-lang.org/book/second-edition/ch15-00-smart-pointers.html

                  So, it’s not completely static (in some sense)