[HN Gopher] Does the Bronze Garbage Collector Make Rust Easier t...
       ___________________________________________________________________
        
       Does the Bronze Garbage Collector Make Rust Easier to Use?
        
       Author : ingve
       Score  : 103 points
       Date   : 2021-12-23 08:00 UTC (15 hours ago)
        
 (HTM) web link (arxiv.org)
 (TXT) w3m dump (arxiv.org)
        
       | akiselev wrote:
       | _> To see whether Bronze could make Rust more usable, we
       | conducted a randomized controlled trial with volunteers from a
       | 633-person class, collecting data from 428 students in total._
       | 
       | Well, this paper starts off with a bang.
       | 
       | A quick search on github returns this repo [1] by _mcoblenz_ who
       | I assume is the first author Michael Coblenz. Unfortunately
       | nothing but the readme has been updated in 10 months and I couldn
       | 't find a link to the latest source with a skim of the paper and
       | bibliography.
       | 
       | [1] https://github.com/mcoblenz/Bronze
        
         | rwmj wrote:
         | This (unfortunately) is rather typical in academia - finish the
         | paper and publish and move on to the next research topic. It
         | would be a shame if the version of Bronze related to the paper
         | forgot to be pushed, but I'm sure sending him a quick email
         | will resolve that.
        
       | redrobein wrote:
       | > ...indicated that ownership, borrowing, and lifetimes were
       | primary causes of the challenges that...
       | 
       | I thought this was kinda obvious. Reasoning about borrowing and
       | lifetimes is hard if you've never done it before. But the real
       | question is how long it takes users to learn it and what we can
       | do to improve that. I wonder how close the plain rust users'
       | times would get to bronze users over time as they keep doing
       | similar tasks.
        
         | CraigJPerry wrote:
         | >> I wonder how close the plain rust users' times would get to
         | bronze users over time as they keep doing similar tasks.
         | 
         | This is the real question for me. The rest is just
         | implementation detail. Someone is (usually) paying for the code
         | to be written. Are they getting more value for less spend over
         | time?
         | 
         | When you look at it through this lens though, there tend to be
         | bigger overriding factors a rust compiler (or any other choice
         | of language) can't really help with - e.g. is the design &
         | architecture of the code heading in the "ball of mud"
         | direction. I.e. is change velocity going to reduce over time?
         | 
         | With a garbage collector, yeah you most likely are getting more
         | productivity out of a developer. You've delegated one of the
         | hardest problems (when can i free this thing?) to the computer.
         | Because of the way rust is designed, it doesn't protect against
         | memory leaks. It protects against use after free but not that i
         | fail to release redundant memory. But unfortunately It's not
         | guaranteed that just adding a garbage collector will help with
         | this. With a sufficiently good developer though, they should be
         | able to move faster than if you make them Arc<> & lifetime
         | everything themselves. It's specifically the lifetime bit that
         | consumes time / developer productivity. Using Arc<> isn't hard
         | or arduous in any way.
        
       | jraph wrote:
       | If you add a garbage collector to Rust, you neutralize one of its
       | strength: the controlled lifetime of objects. You also make
       | memory leaks easier.
       | 
       | I'm convinced Rust is easier to write without the management of
       | lifetimes in a short time span. However, what about long term
       | maintenance, and application stability?
       | 
       | Rust with a GC probably has its uses (compiled language with
       | strong error checking), but one has to know what ship they are
       | boarding.
       | 
       | It also makes it quite closer to D, an "easier C++", compiled
       | language with a GC.
       | 
       | (I'm saying this as someone who tried Rust, and mostly uses GC'd
       | languages)
       | 
       | edit: thanks for the replies below. I hadn't though about this. I
       | guess one should better read my message as "If you remove Rust's
       | lifetime management, ..."
        
         | rwmj wrote:
         | Garbage collection and controlled object lifetimes are
         | important and orthogonal concerns. You can have both at the
         | same time. C# for instance lets you add a Dispose() method for
         | the times when you want to free the resources now. There are
         | even ways to ensure statically that objects aren't used after
         | the close/dispose is called. (Of which I would find the paper,
         | but my google-fu is failing me right now ...
         | https://okmij.org/ftp/Haskell/regions.html and
         | https://arxiv.org/abs/1803.02796 I think)
        
           | [deleted]
        
         | torginus wrote:
         | Tbh, I'm not sure about this GC-purism. I've encountered tons
         | of high-end C++ that's absolutely full of smart pointers, which
         | is a form of GC. Rust has Rc<> and Arc<> as well. Having a a
         | ref-counted GC instead of a tracing one doesn't seem like a
         | step up in 'purity' to me.
        
           | jeremyjh wrote:
           | Ref-counting provides consistent performance - the costs are
           | amortized smoothly over the operations. They aren't doing all
           | this work for "purity".
        
             | louthy wrote:
             | Ref counting can also lead to memory leaks with circular
             | references.
        
               | [deleted]
        
             | bjourne wrote:
             | Performance of ref-counting is proportional to the size of
             | the dead objects. Performance of tracing gc is proportional
             | to the size of the alive objects. In other words, there are
             | many real-world situations in which ref-counting pauses are
             | much longer than tracing gc pauses.
        
         | IshKebab wrote:
         | > I'm convinced Rust is easier to write without the management
         | of lifetimes in a short time span.
         | 
         | Yeah that's the problem with all these studies that use
         | students writing new code for a few hours.
         | 
         | 99% of coding isn't like that - it's reading other people's
         | code (including code you wrote ages ago and can't remember),
         | trying to figure out how it works, following complex call
         | chains, debugging etc.
         | 
         | If you only look at Advent of Code type problems you'll come up
         | with all sorts of strange conclusions, like static types don't
         | make a difference, comments aren't useful at all, it doesn't
         | matter if you exclusively use single character variable names,
         | goto is totally harmless, etc. etc.
         | 
         | Though in this particular case I guess they didn't have much
         | choice because there are no existing large programs written
         | using Bronze.
        
           | mcoblenz wrote:
           | We were particularly interested in learnability for this
           | study, which CAN be assessed in a study with students.
        
           | Farmadupe wrote:
           | I'm not 100% sure, but I think the OP was talking about the
           | overhead of lifetime management for objects that don't live
           | for a very long time. Or maybe objects that don't have
           | "interesting" lives.
           | 
           | One example in my head individual strings that need to be
           | constructed dynamically but live for the lifetime of the
           | application (better to leak it with Box::leak or lazy_static!
           | than pollute all code with lifetimes)
           | 
           | Another is writing in lifetimes for single purpose objects
           | that live on the stack and might only ever get passed by ref
           | into a single function and then get destroyed soon after.
           | 
           | Lifetimes are super important in rust and are a core part of
           | the language, but in such degenerate cases they take up a lot
           | of programmer effort for little benefit. In my head a
           | "automatic" solution such as GC /could/ have a home in the
           | language. Perhaps this would make rust a slightly better fit
           | for really complex monolithic GUI apps (word processing,
           | spreadsheets, CAD) where full GC would be performance-onerous
           | but data lifetimes would be too complex for rust's strictly
           | ordered lifetime concept
        
         | petre wrote:
         | > It also makes it quite closer to D, an "easier C++", compiled
         | language with a GC.
         | 
         | That's exactly why I loved D over C++ and Rust and had the
         | feeling that I was not fighthing the compiler from day one: the
         | GC, auto types, lack of annoying C preprocessor.
        
           | jraph wrote:
           | D also has the good characteristic of not needing to download
           | the entire Earth and compile half of it before starting a
           | project. You just apt install ldc2 or apt install gdc and
           | there you go (pun not intended).
           | 
           | This actually made me chose D over Rust for my last project.
        
             | p0nce wrote:
             | > those who [used the GC] required only about a third as
             | much time (4 hours vs. 12 hours).
             | 
             | This makes me happy to use D instead of Rust. D has a @safe
             | subset.
        
         | klodolph wrote:
         | Rust's type system doesn't guarantee that object lifetimes are
         | bounded from above (guaranteed to be destroyed), just that they
         | are bounded from below (guaranteed to exist when used). This is
         | why you have stuff like crossbeam--elaborate workarounds for a
         | lack of linear types in Rust.
        
           | [deleted]
        
           | staticassertion wrote:
           | It doesn't guarantee it under all circumstances, like if your
           | computer shuts off obviously destructors don't get called.
           | But you can rely on the behavior to be deterministic.
        
             | klodolph wrote:
             | You can rely on the behavior to be deterministic, but the
             | Rust type system provides no way on _relying_ on this
             | determinism. For example, if you have a stack variable and
             | pass a reference to a short-lived thread, Rust will just
             | throw an error, because there is no way for Rust to prove
             | that the lifetime of the borrow is short enough (bounded
             | from above) because Rust does not have linear types.
             | 
             | I want it to be exactly clear what I'm saying... While you
             | (the programmer) may understand when an object is
             | destroyed, and Rust (the compiler) will agree with you,
             | that information is not present in the type system and you
             | cannot use it in your programs. In this aspect, Rust has
             | the same problems as C++... but where C++ still lets you
             | write code, Rust will just throw an error and force you to
             | use "unsafe" here.
        
               | staticassertion wrote:
               | Yes, that's correct. I just want to be clear that it's
               | not like destructors in rust are unreliable in the way
               | that finalizers are in Java.
        
               | klodolph wrote:
               | To be clear, I definitely wasn't talking about that.
               | 
               | Since you can't use the type system to guarantee that an
               | object is destroyed, there are a few things in Rust that
               | are a major pain to get working. Like passing a reference
               | to a short-lived thread.
        
               | staticassertion wrote:
               | It's not that hard in my experience. You generally do it
               | by using a guarded scope where the user provides a
               | callback and doesn't manage the resource (like a thread)
               | themselves.
        
               | zozbot234 wrote:
               | > For example, if you have a stack variable and pass a
               | reference to a short-lived thread, Rust will just throw
               | an error, because there is no way for Rust to prove that
               | the lifetime of the borrow is short enough (bounded from
               | above) because Rust does not have linear types.
               | 
               | Rust has scoped threads for this use case. Generally this
               | uses closures as opposed to lifetimes to "bound borrows
               | from above" in a safe way.
        
               | klodolph wrote:
               | Rust has crossbeam, but it is not a complete solution to
               | the problem. Scoped threads were removed.
        
               | ssokolow wrote:
               | Would you mind elaborating?
               | 
               | It was removed from the standard library ages ago, but
               | `crossbeam::scope` appears to still be there in the
               | newest release of crossbeam and the git repo.
        
         | KptMarchewa wrote:
         | Can you use lifetimes for most objects, and use GC where it's
         | "hard"? Like, canonical example with double linked lists.
        
           | rtoway wrote:
           | You can do this in Rust today, with the standard library's
           | reference counter
        
             | klodolph wrote:
             | Also, one of the easiest ways to leak memory in Rust. My
             | understanding is that substructural typing systems are just
             | not quite powerful enough to represent the semantics of
             | double-linked lists, but I don't understand the math
             | myself.
             | 
             | Obviously it won't leak memory if you do it correctly, but
             | Rust will happily let you leak memory in an Rc<T>.
        
       | pshc wrote:
       | Is Bronze memory safe?
        
         | kobebrookskC3 wrote:
         | unfortunately, it's unsound
         | https://github.com/mcoblenz/Bronze/issues/2
        
           | codeflo wrote:
           | That's an evil problem to have. Let's say you derive two
           | references to a GC'd object (this can easily happen
           | accidentally in a graph-like data structure) and pass them
           | both as parameters to a function. I've looked at disassembled
           | Rust code before. Given how aggressively the compiler
           | optimizes based on the guarantees around & and &mut, I'd be
           | surprised if this system compiles any non-toy programs
           | correctly at all.
        
       | nestorD wrote:
       | Manish Goregaokar has a wonderful blog post on garbage collectors
       | in Rust, the current implementations, the trade-offs and where
       | they might be worthwhile:
       | https://manishearth.github.io/blog/2021/04/05/a-tour-of-safe...
        
         | moltonel3x wrote:
         | There are a lot of Rust GC approaches here, makes me wonder why
         | the study author didn't use one (or more) of the existing sound
         | GCs. Remove a glaring flaw of the study, and spend less time
         | writing throw-away code.
        
       | dathinab wrote:
       | The thing is rusts owner ship system doesn't "just" provide
       | memory handling, it provides reliable hard to get wrong resource
       | handling for all kinds of resources.
       | 
       | To some degree for me this is *more* important then the memory
       | handling aspects.
       | 
       | For example the whole "collection modified while iterating over
       | it" situation can easily become a nightmare, especially for new
       | programmers. It also does happen in non multi-threaded code all
       | the time (if there are some "cross-cutting" concerns). In many
       | GCed languages/libraries running into this situation is "safe"
       | but unspecified. Worse if it happens to work in some situations
       | (it often does) it's not rare for programmers to rely on this
       | behaviour. That is until it gets subtitle broken due to other
       | code changing, or the library changing. In rust this problem is
       | not a thing, the borrow checker prevents you from accidentally
       | running into it by accident. If you need it there are ways to
       | still get it, but now with well define characteristics. So while
       | this is initially more work, it is much much less bug prone and
       | easier to maintain.
       | 
       | And that's just one example.
       | 
       | The borrow checker might be more initial work, but it often makes
       | you write better, less buggy, easier to maintain code independent
       | of memory management.
       | 
       | That is if you don't get over-obsessed with never cloning, never
       | using Rc/Arc etc. then you are in for pain. Being over-obsessed
       | with only using borrows is a form of premature optimizations. (As
       | a side note even with clones/Rc/Arc the borrow checker still
       | helps you as it's not the same as replacing it with a GC).
        
       | [deleted]
        
       | adwn wrote:
       | This study, along with their GC library, is fundamentally flawed:
       | The Bronze garbage collector doesn't just provide automatic
       | memory management, it also allows _shared mutable references_!
       | This undermines one of the most critical principles of Rust, one
       | which is necessary for many of Rust 's safety guarantees: _There
       | is never have more than one live mutable reference to the same
       | memory location_. As soon as you create two mutable references to
       | the same memory location, you get _undefined behavior_ , even if
       | you don't dereference them.
       | 
       | That's why the entire approach is flawed: They didn't study "Rust
       | + GC", but effectively created a new language. See [1] for more
       | details.
       | 
       | Personally, as someone who uses Rust professionally, I believe
       | optional GC would be a great addition to Rust! The compiler would
       | provide support for GC, and the actual GC runtimes would be
       | library-based, similar to how _async /await_ is handled. However,
       | this GC would merely replace Arc/Rc, not Mutex/RefCell/Cell.
       | 
       | [1] https://users.rust-lang.org/t/bronze-gc-and-aliasing-
       | problem...
        
         | codeflo wrote:
         | I absolutely agree. There's prior art in that direction. It's
         | more or less abandoned now, but Microsoft developed an
         | extension to C++ that integrated the .NET runtime with it's
         | garbage collector called C++/CLI. The way it worked is that in
         | addition to C++'s native pointers and references (Foo* and
         | Foo&), you had a new kind of garbage collected reference,
         | written Foo^. There were some annoying limitations that a GC
         | built directly for this use case might have solved better, but
         | mostly, this worked really well.
         | 
         | And I think Rust would be a much better target language for
         | such a system than C++ was. For example, one of the interesting
         | problems was that the .NET GC is compacting -- it will move
         | objects around to improve cache locality and simplify the
         | allocation algorithm. To interact with ordinary C++ code, you
         | need native pointers into GC'd objects. But it was only safe to
         | take such a pointer while you told the GC to temporarily "pin"
         | the object in memory, otherwise, your pointer could be randomly
         | invalidated. Forgetting that step was a very evil source of
         | nondeterministic memory bugs. It's not hard to see how the
         | borrow checker would help there.
        
           | pjmlp wrote:
           | It isn't abandoned at all, it was one of the milestones for
           | .NET Core 3.1 release and is currently up to date with C++17.
           | 
           | Much easier than dealing with P/Invoke declarations or
           | dealing with COM over RCW/CCW layer.
        
       | alexchamberlain wrote:
       | Is a study based on students the best way to measure the
       | productivity of a language? It would be interesting to see what
       | Rust experts code do with and without, for example.
        
       | veltas wrote:
       | The short lifetime of most objects should be implicit from scope
       | and obvious to the programmer. It's usually easier that way, and
       | certain GC-based languages ended up adding special syntax to add
       | that level of control for objects when the programmer wants fine-
       | grained control over the destructor.
       | 
       | And on the other hand, optional GC is something non-GC languages
       | can end up adding too, like C++. Garbage collection is required
       | (or convenient) for some problems, cleaning up objects that would
       | be leaked by reference counting or weaker strategies.
       | 
       | EDIT: deemphasised universality of this rule, not really
       | important to my point anyway: that GC/non-GC memory management
       | are more orthogonal than they appear from language feature
       | discussions, in theory. I wasn't trying to imply literally "all"
       | such languages add these features, I have just noticed a number
       | of relevant cases.
        
         | barrkel wrote:
         | Short lifetime is not usually implicit from scope, _in
         | languages with GC_. Function return values are the problem and
         | solving this problem is the primary ergonomic of GC which in
         | turn affects the style of code written.
         | 
         | If you allocate a value to return, you don't in general know
         | how it will be deallocated because that depends on the caller.
         | The caller may use it for a short time (so stack allocation
         | could work) or store it in the heap where it will have
         | indefinite lifetime. This is why it's not implicit from the
         | scope.
         | 
         | Data flow compounds the problem: if references to arguments to
         | the function are stored in the allocated return value, then the
         | return value extends their lifetime, but again, the writer of
         | the function doesn't know by how much.
         | 
         | Simple refactoring which abstracts code into more reusable
         | functions will obscure local reasoning about allocation.
         | 
         | Working around these problems in the absence of GC or lifetime
         | analysis means adopting various ad-hoc fixes, like calling
         | conventions which pass the location for the return value as a
         | hidden parameter, or smart pointers which dynamically track
         | ownership, or coding conventions like caller always allocates,
         | or global conventions like zone allocation.
         | 
         | The big programming ergonomic side-effect of the presence of GC
         | is the ability to more freely write and refactor functions that
         | allocate and freely reuse them elsewhere. Conversely, code
         | written without GC will be less factored into reusable
         | functions.
         | 
         | Rust's lifetime management is somewhere in the middle. It
         | requires particular conventions and if you're able to follow
         | the conventions then ergonomics approach that of GC. But if you
         | want cyclic data structures, or to simply _pass data which
         | might enable the construction of cyclic data structures_ , you
         | need to think harder.
        
         | johnny22 wrote:
         | didn't they remove GC from C++?
        
           | veltas wrote:
           | I honestly don't know, maybe. There are libraries for it too
           | though. https://hboehm.info/gc/
        
         | josephg wrote:
         | Huh? Which languages are you referring to? Javascript, Lua,
         | Python and ruby are all GC based languages with (as far as I
         | know) no special syntax for short lived objects. Does Go have
         | syntax like that? The only GC language I can think of with
         | special stack variables is C#. Are there others? Does Java do
         | this now?
         | 
         | And on the other side, I've still never seen a production C or
         | C++ codebase which used a garbage collector. The closest I've
         | seen is refcounting - but that's a very different beast
         | compared to what V8, .net, Go, etc do internally to garbage
         | collect objects.
         | 
         | The only languages I've seen which mix GC and non-GC code are
         | D, Nim (I think), with an honourable mention for Obj-C /
         | Swift's ARC. But again, I'm not sure ARC belongs in the same
         | category as the generational GCs we see in the JVM and others.
         | 
         | With a few obscure exceptions, it seems to me that the gc/ non-
         | gc line is still pretty firm for most programming languages.
        
           | steerablesafe wrote:
           | If you replace "short-lived objects" with "short-lived
           | resources" then Go has defer, Python has context managers.
        
             | josephg wrote:
             | Is Go's defer used to optimize the GC? I thought it was
             | just syntax sugar to make sure people wouldn't forget to
             | close file handles and things like that..?
        
               | steerablesafe wrote:
               | It is for _deterministically_ release resources based on
               | scope (although Go 's defer is tied to function-scope for
               | reasons I can't understand). python's context manager is
               | similar. Much like destructors in C++.
               | 
               | You can probably say the same about heap allocated
               | memory, but GC'd languages make the choice the non-
               | deterministic release of heap allocations are fine. But
               | there are resources where you can't play the same game
               | (open files, connections, locks) and you need a way to
               | deterministically close them.
        
               | jatone wrote:
               | defer is tied to function scope because that is the
               | usecase it was designed for. go also has finalizers
               | executing right before deallocation.
        
           | veltas wrote:
           | Lua for instance has specific syntax added for it:
           | https://www.lua.org/manual/5.4/manual.html#3.3.8
           | 
           | Languages tend to have workarounds or conventions for this
           | kind of code where there isn't special syntax for it:
           | https://stackoverflow.com/a/865272 (Python)
           | 
           | Also just because C or C++ codebases don't use GC doesn't
           | mean it's not useful. I've never used it either, but I can
           | think of situations where I would use it. Like I've not used
           | most of the algorithms I learned at uni but I can still think
           | of where I might use them.
        
           | p_l wrote:
           | I can think of only Common Lisp, which has optional
           | optimization hint that specific object won't get passed
           | outside of current stack (declaring something DYNAMIC-EXTENT,
           | to be specific). Mind you, it's only a hint, and there were
           | specific techniques for writing "nonconsing" code (in Lisp
           | lingo, "non-allocating", thus not creating garbage)
        
           | hayley-patton wrote:
           | Note that "short lived objects" and "stack allocated objects"
           | aren't exactly the same set. Common Lisp has a dynamic-extent
           | declaration, which can be used to stack allocate [1]. Go and
           | Java implementations perform escape analysis. There can have
           | some wins if stack allocatability is tracked at runtime,
           | rather than compile-time [2]; Cliff Click reported roughly
           | doubling the number of stack-allocated objects by using
           | escape _detection_ rather than _analysis_ [3].
           | 
           | At least the Inkscape vector editor uses the Boehm garbage
           | collector [4]. There are several programming language
           | implementations which use Boehm and C, but one wonders if it
           | is still a "C codebase" then.
           | 
           | [1] http://www.lispworks.com/documentation/HyperSpec/Body/d_d
           | yna...
           | 
           | [2] Henry Baker, CONS should not CONS its arguments
           | https://www.cs.tufts.edu/~nr/cs257/archive/henry-
           | baker/cons-...
           | 
           | [3] https://youtu.be/5uljtqyBLxI?t=791
           | 
           | [4] http://inkscape.gitlab.io/inkscape/doxygen/namespaceInksc
           | ape...
        
             | josephg wrote:
             | Thankyou. I didn't know about Inkscape, or anything about
             | Common Lisp. Javascript (in V8) also has special detection
             | & processing for very short lived objects. I appreciate the
             | links!
             | 
             | But I was specifically responding to / confused by this
             | claim in the GP comment:
             | 
             | > GC-based languages _all_ ended up adding special syntax
             | to add that level of control for objects when the
             | programmer wants fine-grained control over the destructor.
             | (Emphasis mine)
             | 
             | And as you say, Java, V8 and Go do this with heuristics,
             | not syntax. And I'm not sure if Ruby or Python do this sort
             | of escape / generational analysis at all. On the flip side,
             | it looks like Lua has added something like this, and C# has
             | stack-allocated structs.
             | 
             | Lua + C# + CommonLisp falls very short of the "all GC
             | languages" claim.
        
               | veltas wrote:
               | Okay I have edited the post so it does not say "all".
        
               | masklinn wrote:
               | > And I'm not sure if Ruby or Python do this sort of
               | escape / generational analysis at all.
               | 
               | It would almost certainly be implementation specific (as
               | it is with js really, v8 is not a langage).
               | 
               | I would assume pypy does escape analysis, I'm almost
               | certain cpython does not.
        
           | pjmlp wrote:
           | > The only GC language I can think of with special stack
           | variables is C#. Are there others? Does Java do this now?
           | 
           | There are tons of languages that allow that, even if many of
           | them failed to gain mainstream adoption.
           | 
           | - Mesa/Cedar
           | (https://yahnd.com/theater/r/youtube/z_dt7NG38V4/)
           | 
           | - CLU
           | 
           | - Modula-2+
           | 
           | - Modula-3
           | 
           | - Oberon
           | 
           | - Oberon-2
           | 
           | - Oberon-07
           | 
           | - Active Oberon
           | 
           | - Component Pascal
           | 
           | - Oberon-V
           | 
           | - D
           | 
           | - Nim
           | 
           | - Swift (RC is a GC algorithm, chapter 5,
           | https://gchandbook.org/)
           | 
           | - Eiffel
           | 
           | - C++/CLI
           | 
           | - Unreal C++
           | 
           | - Linear Haskell (getting there still WIP)
           | 
           | - Pony
           | 
           | I kept Nim and Swift for completion as you already mentioned
           | it before.
        
       | symmetricsaurus wrote:
       | > A key tradeoff is that Bronze does not guarantee thread safety
       | 
       | Not having data races is one of the key benefits of using Rust,
       | "fearless concurrency" and all that. So by throwing away a key
       | guarantee of Rust (no aliasing mutable references), it can become
       | easier for learners to program in. It becomes a bit of an apples
       | and oranges situation at that point.
        
         | Fiahil wrote:
         | Usually, you don't start learning a new language with
         | multithreaded operations..
         | 
         | In that sense, adding a gc to rust for single threaded
         | programming, is almost useless : it's not helping that much and
         | you're not learning.
        
           | einpoklum wrote:
           | > Usually, you don't start learning a new language with
           | multithreaded operations..
           | 
           | Why not? I mean, maybe not your first ever programming
           | language, but - why should you not get used to doling out
           | work to all available threads to begin with?
        
             | Fiahil wrote:
             | If you already have the required experience for writing
             | working multithreaded programs, then learning Rust isn't
             | going to be an issue !
             | 
             | If you don't or are unsure about that, then stick to
             | simpler forms of programming or use type-hinted Python
             | instead.
             | 
             | This would the recommendation I would make to anyone asking
             | me that question !
        
             | smabie wrote:
             | Because multi-threaded programs are largely unnecessary for
             | solving many problems (as the popularity of python has
             | aptly demonstrated).
        
           | dystroy wrote:
           | Depends if it's your first language, probably.
           | 
           | For an already experienced programmer, it's hard not to think
           | about using multiple threads, even when just starting in the
           | language. I know my few first Rust programs were using
           | multithreaded constructs and I found that especially easy to
           | do safely in Rust (when I started, there was already
           | crossbeam and rayon, both making a lot of things easier).
        
           | timeon wrote:
           | > Usually, you don't start learning a new language with
           | multithreaded operations..
           | 
           | When I have started with rust I was not writing stuff with
           | Box/Rc/Arc... or even explicit lifetimes. Not saying that I
           | was cloning everything but for simple stuff you can come long
           | way with just moving and simple borrowing.
        
           | FpUser wrote:
           | Due to the type of software I do that is exactly how I look
           | at new language: How it handles concurrency, what kind of
           | synchronization primitives it offers, how it manages
           | lifecycle etc. etc. If it does not provide enough facilities
           | in comprehensible way then it essentially useless to me. I do
           | not learn languages just for the f.. of it.
        
         | hawk_ wrote:
         | Yes pretty much like taking a statically typed language, making
         | compile time type annotations optional and claiming victory
         | that it's easier for beginners. Now they would get runtime
         | exceptions instead.
        
           | rhdunn wrote:
           | There are two forms of optional type annotations:
           | 
           | 1. Using a placeholder (let/var/val/auto/...) -- e.g. in
           | modern C#/Java/C++/Kotlin -- and letting the compiler figure
           | out the type, but keep the actual type known at compile time.
           | This will give you compile time errors when using the wrong
           | types, and keeps the variables of a fixed type.
           | 
           | 2. Effectively making all types variant types that can hold
           | any value and can change their type -- e.g. in
           | JavaScript/Python/Ruby -- such that they are dynamically
           | typed. This can lead to runtime errors.
           | 
           | For languages like C#, Java and the derivatives, they have
           | the concept where all objects are instances of a common type.
           | If you use this -- especially in collections -- you can also
           | get runtime errors. As long as you stick to the generic
           | versions of these, the compiler will enforce the type safety.
           | 
           | The statically typed languages have been making types
           | optional where the compiler can deduce them to avoid
           | redundancy and duplication. If there is an ambiguity, the
           | compiler will omit a compiler error. This is the best of both
           | worlds -- type safety without the noise of annotating types
           | everywhere.
        
             | hawk_ wrote:
             | My point here was that this was equivalent to using Object
             | type in Java/C#. Here the data race guarantees of rust type
             | system are elided due to this GC.
        
           | vegai_ wrote:
           | Rather it's like taking a statically typed language and
           | making all type annotations inferrable.
        
             | hawk_ wrote:
             | If they were made inferrable, it wouldn't cause runtime
             | exceptions. Here the data race guarantees of rust type
             | system are elided instead.
        
           | anaisbetts wrote:
           | It's still valuable to have a language that has better
           | semantics and a more modern standard library than C++, even
           | if it didn't get the benefits of strict memory management.
           | That's still a Useful Thing.
        
             | notriddle wrote:
             | Isn't that language called D?
        
             | jeremyjh wrote:
             | Once you introduce a garbage collector there are plenty of
             | other languages that provide that while still having
             | expressive type systems and modern features, like Kotlin or
             | C#.
        
               | neutronicus wrote:
               | Yeah, Rust's entire value proposition is that it doesn't
               | lock you into GC
        
               | dathinab wrote:
               | Rusts ownership system has benefits beyond memory
               | management.
               | 
               | If I'm a situation where having a GC is ok and there is
               | no "major library ecosystem benefit" (or simlilar) for
               | one of the languages I still would choose rust over
               | Python, JS, TS, Java, Kotlin, Dart, Scala (probably C#,
               | idk. as I haven't used it).
               | 
               | The borrow checker is something which cost you once time
               | to learn but if you are fairly familiar with it it
               | normally won't cost you much time (if any). Sure there
               | are still situations in which it can be tricky. But most
               | times they are pretty clear and you can just throw a
               | Clone/Rc/Arc at it and it's normally just fine (the
               | borrow checker is still useful even with managed
               | pointers/collections like Rc/Arc, in a certain way it
               | makes them less error-prone to use, especially in case of
               | more complex types like some thread safe Cow optimized
               | manage pointer type you might find in a library).
        
               | nesarkvechnep wrote:
               | Or... OCaml.
        
         | civilized wrote:
         | Doesn't it seem useful to have one language that can be used at
         | several levels of sophistication?
        
           | jacobr1 wrote:
           | Depends on the tradeoffs.
           | 
           | Having different levels of abstraction within the same
           | language can be really useful.
           | 
           | But you don't want to overcomplicate the language to support
           | that, especially if it makes operating at different levels
           | more complicated.
           | 
           | In this case, it seems like an odd tradeoff to make. The less
           | sophisticated user is exactly the same kind of user that is
           | more likely to foot-gun themselves with a memory or thread-
           | safety issue. The "right" answer is probably a thread-safe
           | garbage collector, but that has its owns set of usability and
           | implementation tradeoffs.
        
             | civilized wrote:
             | How does Bronze overcomplicate Rust as a language? It's an
             | optional library, not a language extension.
             | 
             | I think it's often pretty easy to not footgun yourself with
             | thread or memory issues, because these issues simply don't
             | exist in wide swaths of application.
        
               | dathinab wrote:
               | It's locking you into single threaded usage, but you
               | might very easy run into a library which requires Send
               | bounds, as it uses e.g. rayon internally.
               | 
               | And for the cases where having managed pointers are
               | better, Rc/Arc are often (not always) good enough.
        
         | fearless_monkey wrote:
         | This reminds me of C# sharp and their introduction of the
         | unsafe keyword. gc for everything until you need to manage your
         | own pointers for speed or something.
        
         | pjmlp wrote:
         | Data races across threads, Rust type system does nothing to
         | prevent data races across processes.
        
           | adwn wrote:
           | That's not entirely correct, or at least misleading. Rust
           | will provide the same guarantees for variables in memory
           | shared between processes as for variables in memory shared
           | between threads. But you have to make sure that any locking
           | datastructures you're using (like mutexes or read-write-
           | locks) are able to work across processes.
           | 
           | (There are limits, though: if you map the same physical
           | addresses to different virtual addresses, Rust can't help
           | you. However, that is independent of threads/processes,
           | because you can also do that in single-threaded programs.)
        
             | pjmlp wrote:
             | Which is a different story that just asserting fearless
             | concurrency no matter what, also misleading.
             | 
             | Hence why I try to make a point that comes with a footnote.
             | 
             | Rust is after all supposed to target all kinds of system
             | programming scenarios.
        
               | adwn wrote:
               | > _Which is a different story that just asserting
               | fearless concurrency no matter what, also misleading._
               | 
               | Frankly, you're being a bit disingenious. Nobody claimed
               | that Rust can or will solve all conceivable concurrency
               | problems. "Fearless concurrency" is generally understood
               | to mean "...within a single program", not "...across
               | different processes/machines/networks". By the time you
               | understand what _interprocess shared memory_ is, you 're
               | well able to correctly interpret Rust's "fearless
               | concurrency" slogan.
        
               | pjmlp wrote:
               | Understood by most on the Rust community, not by others.
               | 
               | Most outside of the community aren't aware that nomicon
               | points out exactly this.
               | 
               | By the way, there are also ways to cause havoc within a
               | single program, example using a file as backing store
               | being accessed by multiple threads concurrently, or
               | accessing database data without transactions.
               | 
               | My goal is not to bash Rust, rather to trigger
               | discussions around these kind of problems.
        
               | noctune wrote:
               | Both those situations are race conditions, but neither
               | are data races. Rust only prevents data races, which is a
               | specific kind of race condition, but it does not prevent
               | race conditions in general.
        
               | pjmlp wrote:
               | It is the "in general" I care about and think it gets too
               | little discussion on the community, because just like
               | some RIR threads, the details get lost in the discussion.
        
           | berkes wrote:
           | When can data races across processes happen?
           | 
           | Are you talking about databases, services or IO and such?
        
             | pjmlp wrote:
             | That and kind of data structure that can be shared via IPC
             | mechanisms, some of them even transparent for the
             | processes.
        
             | SAI_Peregrinus wrote:
             | Environment variables.
             | 
             | Locales.
             | 
             | Quite a few other POSIX bits, really.
        
               | Kranar wrote:
               | It is not possible to have a data race with environment
               | variables across multiple processes. Every process has
               | its own copy of environment variables (in fact they have
               | their own copy of the entire environment).
               | 
               | I'm not sure what data race is possible across processes
               | with locales, that's too vague of a claim to make.
        
             | knuthsat wrote:
             | I guess the simplest example is shared memory between
             | processes.
             | 
             | Even Python has it: https://docs.python.org/3/library/multi
             | processing.shared_mem...
        
               | KptMarchewa wrote:
               | >Even Python
               | 
               | It's not "even". Python specifically has it because it
               | has no real threading.
        
               | bjourne wrote:
               | Python has cooperative threading. It's the same threading
               | model used in the Erlang VM, Julia and many other
               | dynamically typed languages. But preemptive threading vs.
               | cooperative threading is orthogonal to whether data races
               | can happen. Java threads are preemptive but data races
               | can still happen.
        
               | nesarkvechnep wrote:
               | The Erlang VM does preemptive scheduling.
        
               | bjourne wrote:
               | No it doesn't.
        
               | grogers wrote:
               | While this is technically true it's quite misleading. The
               | VM itself uses cooperative scheduling, but the Erlang
               | compiler emits something akin to yields appropriately,
               | such the net effect is preemptive scheduling. You can
               | break it by calling a NIF that doesn't do the yields
               | appropriately, but that's not the norm.
        
               | knuthsat wrote:
               | SharedMemory is a new thing in Python. Not even supported
               | by all 3.x versions.
        
               | dangerbird2 wrote:
               | Python does have real threading. The `threading` module
               | provides os-level threads and synchronization primitives.
               | The only difference between this and multithreading in C
               | or Java is that CPython's GIL prevents more than one
               | thread executing bytecode at a time. This prevents
               | parallelism, but not concurrency.
               | 
               | Note this does _not_ mean that python code is thread-safe
               | by default. At most, you can theoretically rely on
               | bytecode operations to be atomic, which means you 'll
               | need to synchronize multi-threaded code with mutexes,
               | semaphores and higher-level synchronization constructs.
        
               | SCHiM wrote:
               | Access to raw memory is locked behind the unsafe keyword
               | though. Rust officially already does not guarantee any
               | safety in that scenario even within 1 process.
        
               | pjmlp wrote:
               | There is always unsafe at some level on the standard
               | library.
               | 
               | The point is that it doesn't protect the user of a crate
               | that only exposes a fully safe API, unless they do
               | digging to validate overall architecture safety.
        
         | luckystarr wrote:
         | True, yet in the context of the experiment that part of the
         | language was not used, so they could compare the two
         | approaches.
         | 
         | I think this research highlights a important strategy to make
         | all software safer.
         | 
         | A quote from the discussion section:
         | 
         | > Encouraging adoption of safer languages by reducing stress.
        
           | MaulingMonkey wrote:
           | It appears in this case that they're encouraging adoption of
           | safer languages by making them unsafe and unsound:
           | https://users.rust-lang.org/t/bronze-gc-and-aliasing-
           | problem...
        
       | elzbardico wrote:
       | Why do we need to make everything easier to beginners? Are the
       | beginners supposed to stay as beginners forever?
        
         | keymone wrote:
         | Valid point, but if a good system deters beginners by being too
         | complex and hard to use - adoption will suffer. We want good
         | systems to have high adoption.
        
       | ummonk wrote:
       | I think providing a garbage collector as training wheels as the
       | authors are proposing would be counterproductive to helping
       | beginners truly learn Rust.
        
       | booleandilemma wrote:
       | I'm saddened to think that because this industry has an obsession
       | with making programming accessible to the lowest common
       | denominator, expressive and innovative languages like Rust will
       | fall by the wayside, and we'll all be writing code in languages
       | like Go and Python in the future because they're "easy" and even
       | high schoolers can learn them in a couple days.
       | 
       | It reminds me of the longbow vs crossbow.
       | 
       | One is a technology that anyone can learn to use easily, the
       | other is one that takes longer to master, but is a more efficient
       | weapon in the hands of a skilled soldier.
       | 
       | The analogy isn't perfect but the parallels are there.
       | 
       | http://www.thebeckoning.com/medieval/crossbow/cross_l_v_c.ht...
        
         | zaptheimpaler wrote:
         | im not a great programmer but having used Rust and
         | Python/Scala/Java, i have a hard time believing anyone can be
         | _as_ productive in Rust as they would be in a GCed language for
         | many /most applications. Say building a typical backend or
         | prototyping some linear algebra/ML, the memory management is
         | just a very low level that is likely not a concern and takes
         | away focus from the higher level.
        
           | staticassertion wrote:
           | I am much more productive in Rust vs Python and Java, it's
           | not even close. Memory management in Rust is trivial, it
           | takes up virtually 0% of my time.
        
         | ModernMech wrote:
         | Fear not! Experts will always be inclined to make tools that
         | match their skill level. You can still buy longbows today!
        
         | ttfkam wrote:
         | Every time I hear the term "lowest common denominator" applied
         | to programmers, I reflect on the number of network-accessible
         | remote exploits that provide root access via the Linux kernel
         | over the past three decades.
         | 
         | And yet the folks maintaining the network stack in the Linux
         | kernel are not anywhere near what I or almost anyone else would
         | consider the lowest common denominator programmer.
         | 
         | Sometimes you just have to accept that ALL humans are
         | inherently bad at this, only some are worse than others at
         | various points in their lives. The security and reliability of
         | the product of our output should not be so largely dependent
         | upon our ability to get a full night's sleep, reasonable
         | working hours, and lack of personal conflict. To be sure, we
         | should all strive for those things, but perhaps the choice of
         | tools is correct in prioritizing mitigation of difficulties and
         | vulnerabilities from meatspace.
         | 
         | Sometimes that's a borrow checker. Other times it's a garbage
         | collector. And every once in a while, we need to break out an
         | unsafe block (or the entire C language) to get a job done.
         | 
         | Considering how much more expensive people are than software or
         | hardware, the trade off for easier/simpler access is
         | increasingly straightforward.
        
           | jkilpatr wrote:
           | While I strongly agree this doesn't seem to match the
           | sentiment of the paper.
           | 
           | Which is prioritizing a lower barrier to entry for new
           | programmers at the cost of safety checks that help prevent
           | humans from making mistakes at runtime.
           | 
           | It seems to me if our conclusion is humans, no matter how
           | skilled, are flawed, we should be willing to do absolutely
           | anything to lower the barrier to entry except removing checks
           | on correctness.
        
             | bjourne wrote:
             | What makes you say that? What safety or correctness
             | features do you think a garbage collector in Rust eschews?
             | On the contrary, gc should make the language safer since it
             | obviates the need for the "unsafe" escape hatch.
        
               | jkilpatr wrote:
               | > A key tradeoff is that Bronze does not guarantee thread
               | safety
               | 
               | Data races are currently prevented by the borrow checker.
               | Any GC in order to provide equivalent correctness would
               | need to do so as well.
        
               | dahfizz wrote:
               | If you read the paper, they needed to throw out the
               | thread safety from Rust's borrow checker in order to make
               | the GC work. That is a massive surface area for bugs they
               | are opening back up to make the language easier for
               | beginners.
        
               | mcoblenz wrote:
               | I just added a clarification to the README about this.
               | The main issue is that the current implementation keeps
               | track of roots with a shadow stack technique
               | (https://llvm.org/docs/GarbageCollection.html#using-llvm-
               | gcwr...), which is not thread-safe. It wasn't worth the
               | engineering work for this particular study since the
               | tasks didn't require more than one thread. A practical
               | implementation, of course, would need to be thread-safe.
        
               | dahfizz wrote:
               | I'm sure the GC implementation itself could be made
               | thread safe. But the paper mentions that Bronze lets you
               | have multiple mutable references to an object. Doesn't
               | this open the door to the user's code having data races,
               | whereas it would be safe by default in vanilla Rust?
        
               | bjourne wrote:
               | Because their gc is a proof-of-concept created
               | specifically for this research. It doesn't even
               | deallocate memory. Most likely, they didn't have their
               | students write any threaded code so thread-safety wasn't
               | a concern. For a production ready tracing gc, of course
               | they would add thread safety, it's not a big problem.
        
               | dahfizz wrote:
               | No, this is the fundamental tradeoff they made to make
               | the Bronze'd Rust easy to use:
               | 
               | > Rust permits only one mutable reference to a value at a
               | time... With Bronze, mutation is permitted through all
               | references to each garbage-collected object, with no
               | extra effort. A key tradeoff is that Bronze does not
               | guarantee thread safety; as in other garbage collected
               | languages, it is the programmer's responsibility to
               | ensure safety.
               | 
               | Allowing mutability anywhere is what fundamentally makes
               | Bronze easier to learn, and more error-prone.
        
               | bjourne wrote:
               | The paper's author has already explained to you how
               | thread safety can be achieved in a production-ready gc.
               | This is not something that is particularly difficult to
               | engineer and is quite orthogonal to whether one chooses
               | to use tracing gc, ref counting or Rust-like borrow
               | checking.
        
               | adgjlsfhk1 wrote:
               | See https://users.rust-lang.org/t/bronze-gc-and-aliasing-
               | problem.... The GC allows use after free bugs that are
               | compile time exceptions in Rust.
        
               | Lerc wrote:
               | What does "use after free" mean in a garbage collected
               | environment? Isn't the purpose of GC to automatically
               | free after last use.
        
               | adgjlsfhk1 wrote:
               | It means the GC design is fundamentally broken.
        
               | p0nce wrote:
               | Quoting the article:
               | 
               | > those who [used the GC] required only about a third as
               | much time (4 hours vs. 12 hours).
               | 
               | Surely you can devote a chunk of your newfounded time to
               | find use-after-free bugs.
        
               | adgjlsfhk1 wrote:
               | If that worked, people wouldn't still be finding use
               | after free bugs in commonly used C libraries. The whole
               | reason to use Rust is that it turns most of C's UB into
               | compile time errors so that your code isn't horribly
               | broken in the first place.
        
               | notriddle wrote:
               | I don't know how to find use-after-free bugs in arbitrary
               | code, no matter how much time I devote to the task. I
               | just can't keep enough state in my head at once.
        
               | bjourne wrote:
               | But the gc is there to test the usability cost of Rust's
               | memory management scheme. A properly written gc would of
               | course not allow for use-after-free bugs.
        
               | adgjlsfhk1 wrote:
               | The problem is that this study is relatively worthless,
               | because the API used by this GC inherently introduces UB.
               | If you have a correct API, the usability tradeoff might
               | be very different.
        
               | bjourne wrote:
               | Can you please point to some results in the study that
               | would have been different if the tracing gc hadn't
               | suffered from use-after-free bugs?
        
               | steveklabnik wrote:
               | To phrase what my sibling commentor said but in a
               | different way:
               | 
               | This paper is an experiment to see if a particular API
               | could make using Rust easier. This specific API is not
               | sound. This means that the paper's results are kind of
               | irrelevant in a strict sense; this API cannot work in
               | Rust, so it being easier is kind of a moot point. Maybe
               | someone can take their API, make it sound, and then try
               | again, and that's certainly good. But it is a serious
               | flaw in the methodology.
               | 
               | Specifically, this API call is unsound:
               | GcRefCell<T>::as_mut(&self) -> &mut T
               | 
               | It's not about the _internals_ of the GC. It 's about the
               | API that it exposes to users.
               | 
               | The author has some ideas: https://github.com/mcoblenz/Br
               | onze/issues/2#issuecomment-939... These ones are
               | straightforward, and would probably work, but they would
               | also introduce some friction, and removing friction is
               | the entire point of the exercise. Is it too much? Maybe!
               | It also maybe isn't. You'd need another study to figure
               | that out.
        
               | bjourne wrote:
               | > This paper is an experiment to see if a particular API
               | could make using Rust easier.
               | 
               | According to the author: "The Bronze project is exploring
               | the usability costs of the restrictions that Rust
               | imposes."
               | 
               | That does not require a sound gc to explore. Maybe it
               | would have been different had the goal been to see
               | whether a gc can be bolted onto Rust. Yes, that might be
               | difficult given Rust's semantics and how to deals with
               | pointers. But that doesn't seem to be the goal of the
               | author's research.
        
               | steveklabnik wrote:
               | Again, it's not about the GC being sound, it's about the
               | API that's being used. There's (imho) not a lot of value
               | in figuring out if an API that can't be used is usable.
               | 
               | There are other GC crates that offer sound APIs. Research
               | using those sounds very promising and good!
        
               | bjourne wrote:
               | Then explain to me why it matters. If none of the toy
               | examples in the research actually required multiple
               | mutable references to the same objects, then why would it
               | matter that the compiler allowed it? I think you missed
               | the point of the research: to "explor[e] the usability
               | costs of the restrictions that Rust imposes."
        
               | steveklabnik wrote:
               | If they didn't require it, then that would significantly
               | strengthen the paper! They could have not exposed that
               | API and it would be much more useful. I suspect that they
               | probably _did_ need it though. An immutable GC would only
               | be useful by adding an interior mutability wrapper, which
               | is exactly the kind of friction the paper is trying to
               | avoid.
               | 
               | It matters because the rest of the Rust universe follows
               | this pattern. If they coded their own standard library
               | (and any other allowed libraries) and modified the
               | compiler to not miscompile this usage, then that
               | exploration would be valid. But you're also going to get
               | friction from miscompiles and fighting with other APIs
               | that do have this property. So it would be more useful to
               | either go all-out ok this idea that Rust's uniqueness
               | properties are a bad thing, or fix the soundness issues.
               | The halfway step simply confounds too many issues to be
               | truly useful, in my opinion.
               | 
               | I agree that exploring the space is a good idea and
               | useful. My issue is with the methodology, not the
               | concept.
        
               | adgjlsfhk1 wrote:
               | The problem isn't that the GC suffered from use after
               | free. The problem is that the GC allowed the user to have
               | 2 references to a mutable object which is UB in Rust (and
               | a compile time error without unsafe code). The problem
               | with the API is that without some pretty fundamental
               | changes to the language, the only times a GC doesn't
               | error, and Rust does is when the user tries to do
               | undefined behavior. Removing the UB is also pretty much
               | impossible because if you allow these references, you
               | remove one of the main tools the Rust compiler uses to
               | optimize code.
        
               | bjourne wrote:
               | Having simultaneous mutable references to an object is UB
               | in Rust because the memory manager cannot detect use-
               | after-free errors. What you are talking about is not a
               | feature but a limitation of Rust's borrow checker. But
               | when using a gc multiple multiple references it not a
               | problem at all so there is no reason to prevent it. This
               | has almost nothing to do with performance. Restricting
               | the number of mutable references to one does not mean
               | that the compiler can emit significantly faster code.
        
               | steveklabnik wrote:
               | > Having simultaneous mutable references to an object is
               | UB in Rust
               | 
               | This is correct.
               | 
               | > because the memory manager cannot detect use-after-free
               | errors.
               | 
               | ... this is not. It is UB because the language declares
               | it UB. It is absolutely to the core of the design of the
               | language itself. All Rust code relies on this property to
               | work. Something that breaks it is in fact broken,
               | regardless of any other aspect of the program.
        
           | [deleted]
        
         | t_scytale wrote:
         | There is absolutely no evidence to support this assertion.
         | 
         | Instead there is plenty of evidence that currently there is a
         | lot innovation in all niches of the programming ecosystem -
         | from low level [Rust] to high level, and a lot of coder
         | interest in all the options.
         | 
         | Also talking about "lowest common denominator" comes across as
         | somewhat snobby - many world-class coders use high-level
         | languages when appropriate. It's a matter of choosing the right
         | tool for the job, not dumbing down.
        
           | AnIdiotOnTheNet wrote:
           | > There is absolutely no evidence to support this assertion.
           | 
           | Consider the popularity of Javascript and Electron for
           | _Desktop_ applications.
        
             | Spivak wrote:
             | Because it's a first class development experience, cross-
             | platform by default, V8 is really really fast, and toolkits
             | that support "build your own toolkit" are non-existent
             | outside the web.
             | 
             | I don't want to make a "Windows app", "A Mac app", or a "QT
             | app". I want a rectangle and a high-level enough interface
             | to build my own widgets. People who are single mode users
             | obviously hate that every app looks and behaves different
             | but most people are multi-mode and don't care.
             | 
             | JS is only easy at the most superficial level and gets to
             | be a mess once you go beyond small apps.
        
               | AnIdiotOnTheNet wrote:
               | > Because it's a first class development experience [...]
               | 
               | I'm going to have to disagree with that.
               | 
               | > People who are single mode users obviously hate that
               | every app looks and behaves different but most people are
               | multi-mode and don't care.
               | 
               | I am going to have to strongly disagree with that. If
               | that were true nobody would ever have wanted to do
               | theming, which was a big deal before developers forgot
               | how to make software flexible enough to support it.
               | 
               | > JS is only easy at the most superficial level and gets
               | to be a mess once you go beyond small apps.
               | 
               | Oh, you mean like BASIC? A language designed specifically
               | to be easy to learn? Lots of applications were made in
               | BASIC because it was easy to get into and people just
               | kinda dealt with the mess. Visual Basic especially has a
               | reputation. Sound familiar?
        
             | ssokolow wrote:
             | I think that's more a function of "We want to access all
             | demographics without paying to _properly_ comply with the
             | interface design guidelines of each platform individually.
             | What  'write once, run everywhere including the browser'
             | solution have you got for us?"
        
               | AnIdiotOnTheNet wrote:
               | That wouldn't explain why even companies like Microsoft
               | use webtech in their OS configuration GUI these days.
        
             | bastawhiz wrote:
             | And yet much of Google was built with Python for a very
             | significant chunk of its life. Netflix and Uber were/are
             | heavily leveraging JavaScript for core workloads. The
             | machine learning ecosystem is largely _dominated_ by
             | Python. Stripe, GitHub, and Shopify are still investing
             | heavily in Ruby. Almost none of this is /was for the sake
             | of accessibility to beginners.
             | 
             | Your example cherry picks exactly one instance, ignoring
             | the context of that choice. Such an assertion requires more
             | than just anecdotal musings and ignores the tradeoffs that
             | those teams made when choosing a platform.
        
           | [deleted]
        
         | civilized wrote:
         | But if equipping Rust with a GC makes it as easy as Python,
         | Rust could become the language of choice because you have the
         | low entry barrier _and_ the option of making your code much
         | more robust within the same language. That seems like a big win
         | for everyone.
         | 
         | I think there can be an unproductive temptation to use a
         | language as gatekeeper of a culture. If you want a culture with
         | shared values about how to do things, there are plenty of ways
         | to do that other than keeping the language from accommodating
         | anyone outside of that culture. And your culture will be more
         | accessible to people who genuinely belong in it, if it's
         | visible from the places they already live (e.g. the Rust
         | language).
         | 
         | The languages you dislike are popular because they make it easy
         | for everyone to contribute, and as a result they have a bigger
         | community and, perhaps even more importantly, a greater breadth
         | and depth of libraries and packages than competitors. Rust
         | could be competitive with these languages if it had a low floor
         | and a high ceiling of admissible code quality and
         | sophistication.
        
       | tragomaskhalos wrote:
       | From https://crates.io/crates/bronze_gc : "The Bronze garbage
       | collector for Rust. This version only includes the API for
       | creating and using GC references; _it does not actually collect
       | anything_. For experimental purposes only. " (my emphasis)
       | 
       | This seems to be at odds with the paper, which describes it as
       | mark-sweep?
        
         | MobiusHorizons wrote:
         | I don't think bronze is actually intended to be used outside of
         | the context of the study. My impression is that it exist purely
         | to make it possible to to conduct a study to quantify the
         | overhead of constructing code that can pass the borrow checker.
         | 
         | It's possible the team behind this may have hoped to use the
         | study as part of a grant proposal to get funding to build out a
         | more robust GC for rust.
        
         | Deukhoofd wrote:
         | From Github:
         | 
         | > This implementation is experimental. The 'main' branch has a
         | collector, but it only works in limited cases is not general
         | enough to work with YOUR code. The 'API-only' branch has the
         | collector disabled; be aware that you will eventually run out
         | of memory. However, the present version is suitable for
         | experimentation and prototyping.
        
           | bruce343434 wrote:
           | That's sort of disappointing. Why do people insist on
           | "releasing" and marketing before the product is even finished
           | nowadays?
        
       | staticassertion wrote:
       | Rust is already extremely easy to use.
        
       | ashtonkem wrote:
       | Why would you want to add garbage collection to rust? Doesn't
       | that undermine one of its key value propositions?
        
       | ModernMech wrote:
       | > [the borrow checker] makes Rust relatively hard to learn and
       | use.
       | 
       | I would say the borrow checker makes rust harder to learn, but it
       | does not make it harder to use once you actually grok it. When
       | that time comes, the borrow checker fades into the background.
       | When I got to that point with Rust, it became much easier to use
       | than other languages for me (others I use being C++ and C).
        
       | forgotmypw17 wrote:
       | I was fortunate to see Michael present this recently, and found
       | the presentation convincing.
       | 
       | I may be a bit sheltered, but this was my first exposure to a
       | study with so many volunteers completing involved coding tasks to
       | assess language features.
       | 
       | I find Figure 3 to be particularly convincing:
       | http://shitmyself.com/image/figure3.png
        
         | adwn wrote:
         | > _http://shitmyself.com/image/figure3.png_
         | 
         | Why are you posting a link to a page which requires
         | authentication?
        
           | forgotmypw17 wrote:
           | Sorry about that, I fixed the configuration and it shouldn't
           | require auth anymore.
        
           | hayley-patton wrote:
           | If you refuse to provide authentication, the page will tell
           | you the authentication to provide. Not sure why this
           | mechanism is in place.
        
             | forgotmypw17 wrote:
             | It is basically a captcha to keep out crawler bots.
             | 
             | I added an exception for images and then overwrote the
             | config with a previous version... -_-
             | 
             | Should be fixed now.
        
       ___________________________________________________________________
       (page generated 2021-12-23 23:01 UTC)