[HN Gopher] Arc and Mutex in Rust
       ___________________________________________________________________
        
       Arc and Mutex in Rust
        
       Author : bshanks
       Score  : 112 points
       Date   : 2022-06-05 04:30 UTC (1 days ago)
        
 (HTM) web link (itsallaboutthebit.com)
 (TXT) w3m dump (itsallaboutthebit.com)
        
       | lenkite wrote:
       | A Rust newbie here. Can someone explain why rustc complains that
       | the clojure may outlive the function ? I mean we are joining on
       | both thread handles so the main function has to block until they
       | finish right ? Shouldn't RAII get rid of the clojure objects ?
        
         | marcosdumay wrote:
         | Because the compiler doesn't know to look for this way to wait
         | for the end of the thread. The language is Turing complete, but
         | the compiler can only look for a finite set of subprograms that
         | wait for the thread, so it can never catch them all.
         | 
         | The compiler could have a special case for looking at joins.
         | But that's extra complexity that gets you almost nothing in
         | return. Instead, Rust developers decided that it's better to do
         | it in a library and created the scoped thread the article talks
         | about.
        
           | lenkite wrote:
           | Thanks for explaining, though since the code _is_ formally
           | correct - taking into account thread joins can 't really be
           | considered a special case. I suspect thread spawning and
           | joining would need be a language feature instead of a library
           | feature to enable this.
        
             | marcosdumay wrote:
             | Yes, the code is correct.
             | 
             | That comes from the undecidability of any interesting
             | property in Turing complete code. It means that if you are
             | doing static analysis on your code, you have to decide if
             | you are going with false errors or mark bad code a correct,
             | because no analysis can always give you the correct result.
             | 
             | On this case, you get a false error.
        
             | steveklabnik wrote:
             | It doesn't need to be a language feature. Scoped threads
             | are a library implementation of the idea of joining right
             | away. The issue is that spawn is specifically the most
             | general API; one where you may never even join the thread
             | at all, hence its type signature requiring a 'static bound.
             | Rust doesn't suddenly go "oh you're not actually using the
             | full power this signature gives you, so I'll allow it,"
             | because that would make the code extremely fragile, be
             | tough to implement, all sorts of things. Really, this is
             | about using the API that communicates the semantic you
             | want, so that the compiler can check it.
        
       | ostenning wrote:
       | Theres a lot of criticism here about "async rust". I find this
       | wording strange, I use rust asynchronously with rtic (realtime
       | interrupt concurrency) for low level work. Its really excellent.
       | Are peoples criticisms specifically about inline async?
        
       | pipeline_peak wrote:
       | Return type definitions are optional as Rust programmer's might
       | get confused by difficult words like "void".
        
         | conradludgate wrote:
         | It's just implicit for `-> ()`. Nothing magical
        
       | Communitivity wrote:
       | Every language is hard when you are working with hard problems
       | (e.g. concurrency).
       | 
       | I've also found Rust to be hard until I got a decent
       | understanding of the borrow checker and how it works.
       | 
       | After that, the only times I found Rust to be hard were when I
       | was trying to make it conform to my way of thinking, rather than
       | changing how I approached the problem to match the way Rust was
       | designed. I've had a similar experience in other complex and
       | well-designed languages such as Clojure, Erlang, and Haskell.
       | 
       | In my experience the benefits of Rust (safety-guarantees, speed,
       | good ease of use vs complexity tradeoffs) much outweigh the
       | quirks and learning curve.
        
       | vgel wrote:
       | One option the author didn't mention is that threads can join
       | with a value, so instead of needing scope it could have looked
       | like (on my phone so syntax is probably not quite right):
       | let user = todo!();         let handle: JoinHandle<User> =
       | spawn(move || {             // do stuff with user             //
       | hand back user             user         });         // wait for
       | thread to stop and retake ownership of user         let user =
       | handle.join();
       | 
       | I used this recently to remove locking in a worker thread and it
       | was a big performance boost, _and_ made the code nicer -- win
       | /win.
        
       | pornel wrote:
       | Very good article, and these types are essential to have in your
       | Rust "vocabulary".
       | 
       | I've seen programmers fight the borrow checker a fight they can't
       | win, because `Arc<Mutex<Object>>` has a non-zero overhead and
       | looks uglier than a plain `Object` or `&Object`. However, if the
       | program has object lifetimes that aren't statically known and/or
       | shared mutable state, these are simply the correct types to use
       | (e.g. event-based systems that can attach listeners have to use
       | these). Rust is just being very explicit about ownership and
       | putting all overheads in your face. In something like Python
       | there's no extra syntax for this, because every object is
       | automatically under a lock and has a refcount.
        
       | gnulinux wrote:
       | I want to note here that throughout the internet and HN there is
       | this ongoing wisdom that although Rust is very useful, valuable
       | etc writing code in it is very hard because it constantly feels
       | like you're wrestling the compiler.
       | 
       | Well, maybe there is some truth to it, but I want to say that
       | having started learning Rust in 2022, I found it's multi-
       | threadedness model very refreshing. I thought it was such a
       | delight to write code in, and personally loved it at least one
       | order of magnitude than Go's goroutines. It's safe, embedded in
       | type system (Send etc), has tons of standard tools (Arc, Mutex,
       | mspci channel etc...) that are hard to shoot your foot with.
       | 
       | When people talk about Rust's complicated nature, I wish more
       | emphasis is made on how it completely eliminates entire
       | categories of bugs _even within a multi-threaded context_. As a
       | corrolary, it really makes some parts of programming hard in
       | other languages, nearly trivial in Rust.
        
         | josephg wrote:
         | I agree. I've been writing a lot of javascript for the past few
         | years. I've come to love async in javascript - async makes my
         | javascript code fast, readable and reliable.
         | 
         | Moving to rust, a lot of the struggle I've experienced has come
         | from trying to write rust the way I would javascript - by using
         | rust's async primitives. Async support in rust is complex,
         | immature and incomplete. And its been this way for years.
         | 
         | For a project a few years ago, I tried making an HTTP server
         | which supported a custom SSE-style endpoint. The resulting code
         | was atrocious - it was long, complicated, and I needed to
         | invoke deep lifetime magic that I still don't fully understand
         | to make it compile. I just want to implement both sides of an
         | async stream - but no; thats apparently too hard. I got
         | hundreds of lines in, and the code still wasn't finished. I
         | rewrote it in about 20 lines of javascript and it works great.
         | 
         | I've decided to stay away from async rust until the language &
         | ecosystem mature. Synchronous rust is a delight. I'm going to
         | need to do more IO soon, and I'm dreading it. I don't really
         | want to use threads, but I think it might be the right choice
         | given the current state of async rust.
        
           | likeabbas wrote:
           | Does anyone know what the final state of Rust's async will
           | look like? It seems like everyone is dreading it now but will
           | it ever get to a point that people like writing it?
        
             | mojzu wrote:
             | In my experience I quite enjoyed async Rust, there was
             | definitely quite a bit of yak shaving required to get tokio
             | and various other async/sync libraries to play nicely
             | together, but once that was done I haven't run into any
             | significant issues with it. Are there problems with it I'm
             | unaware of or is the somewhat fractured async ecosystem
             | still a too high barrier to entry?
        
               | mcronce wrote:
               | I agree. It's not like there aren't plenty of
               | improvements to be made, but I write a lot of async Rust
               | and the limitations (which are well enumerated elsewhere
               | in the comments) just aren't really an issue for what I
               | do.
        
             | lumost wrote:
             | async is final unfortunately. My experience with rust so
             | far is that there is a small set of program structures
             | which Rusts type system works well for, and a large set of
             | programs and structures where it becomes an unholy mess to
             | make work e.g. deep lifetime magic, complex async/traits
             | scope, etc.
             | 
             | If you stick on the golden path then the compiler has your
             | back, deviate, and then you are stuck in a deep hell of
             | compiler suggestions that don't pan out. One observation
             | I've had is that complex lifetime problems are usually
             | solved by copy's or the use of unsafe in most production
             | code. I would love to see a future equivalent of "clean
             | code" for Rust, as the current situation is reminiscent of
             | early java programming.
        
               | josephg wrote:
               | Async is final, and I think the design is fine.
               | 
               | The problem is that async code doesn't interact properly
               | with the rest of the rust language. You can't make async
               | traits, async iterators or streams, or use async
               | closures. The problem isn't async. Its that the rest of
               | the language is apparently (still!) incompatible with
               | async code.
               | 
               | All of this stuff is "coming" - and by that I mean, there
               | have been RFCs kicking around since 2017 aiming to fix
               | these problems. Blergh.
               | 
               | Eg:
               | 
               | GATs: https://github.com/rust-lang/rust/issues/44265
               | (This one might land soon!)
               | 
               | Async closures: https://github.com/rust-
               | lang/rust/issues/62290 (seems to have stalled)
               | 
               | TAIT: https://github.com/rust-lang/rust/issues/63063
               | (seems to have stalled)
               | 
               | And so on.
        
               | maleldil wrote:
               | > async is final unfortunately
               | 
               | This is wrong. Async traits and iterators will be huge
               | improvements to the language, and there is more in
               | progress.
               | 
               | Can you provide examples of copy/unsafe being required
               | for complex problems?
        
             | cjg wrote:
             | https://rust-lang.github.io/wg-async/vision/roadmap.html
        
           | smolder wrote:
           | Maybe I just got lucky, but I just built an http to irc relay
           | using Rocket (tokio based) and the irc client crate (also
           | tokio based) and the implementation came out super clean. I
           | made some small wrong turns along the way like breaking
           | graceful shutdown by putting a non terminating future into a
           | join! with the main Rocket future, but with enough time in
           | the various docs I got it right and it's pretty elegant. The
           | Anyhow crate made error handling easy, and I'm happy to see
           | Rocket building on stable since last time I used it. There
           | wasn't really any borrow checker pain or messing with
           | lifetimes. The compiler was very helpful, as usual.
        
           | hkalbasi wrote:
           | Lunatic (https://docs.rs/lunatic/0.7.0/lunatic/) is an Erlang
           | inspired alternative to async rust and manual threads.
        
         | pkulak wrote:
         | Concurrency is hard. Before I started using Rust I was totally
         | on the immutability train, and I still think it's a great
         | strategy. But immutability everywhere also involves jumping
         | through hoops and fighting with the compiler. Though for some
         | reason no one talks about that strategy the same way they talk
         | about Rust's. I think that, no matter what strategy you settle
         | on, it's a bit more work to guarantee correct concurrency.
        
           | klabb3 wrote:
           | > Concurrency is hard.
           | 
           | Absolutely true. This is the submerged part of the iceberg
           | for any programming language. Whenever I see a new language,
           | I skip the hello worlds and the syntax sugar and go straight
           | to see how they solved concurrency and parallelism. Chances
           | are you're gonna need concurrency. If you do, it'll likely be
           | the largest source of complexity in your program at large.
           | Sound concurrency is paramount, and a huge challenge for PL
           | designers.
           | 
           | Rust has solved some major problems and deserves recognition
           | for that. It is already influencing new languages, and we
           | will be better off in the long term. That said, in order to
           | achieve their extremely ambitious goals, they needed to push
           | the type system to its absolute limits, and in a painfully
           | user-facing way. When you are writing async Rust today,
           | you're spending a large part of your limited
           | attention/complexity budget trying to satisfy the compiler,
           | even when your mental model of the business logic is sound.
           | This is what people mean when they say async Rust is hard.
        
             | igorkraw wrote:
             | On the flip side, having used C++, python+javascript
             | (ahhhh) and Rust concurrency, I found the assurance and
             | debuggabilty the type system gives you very relaxing. I can
             | simply break down the problem into "model business logic"
             | and "make the compiler happy" and if I have solved both
             | problems without escape hatches it's not easy to mess up
             | concurrency in Rust (in my opinion). And the ecosystem
             | might be complex, but it's not _unnecessarily complicated_
             | : basically everything is there for a reason and allow you
             | to hack as much as possible while staying in the promises
             | that rust gives you.
        
               | klabb3 wrote:
               | > having used C++, python+javascript (ahhhh) and Rust
               | concurrency, I found the assurance and debuggabilty the
               | type system gives you very relaxing
               | 
               | Not to say anything about C++, python and pre-async JS,
               | but if you compare with async in modern languages and
               | especially if you compare with Go, async Rust leaves a
               | lot to desire imo, mostly in terms of ergonomics and
               | total system complexity.
               | 
               | > but it's not unnecessarily complicated: basically
               | everything is there for a reason
               | 
               | Yes and no. Let me be careful with my words here.
               | Everything is there for a reason, which is always locally
               | coherent. However, globally speaking, these reasons can
               | get more and more detached from the end goal, including
               | the core principles of Rust such as zero-cost and
               | fearless concurrency. I believe this is exactly what
               | happened to async Rust.
               | 
               | A simple example would be lack of async traits. Traits
               | are one of Rust's best features, and everyone has to work
               | around them, meaning that you have to think differently
               | about the same problem depending on if you're in async vs
               | not.
               | 
               | Another example is implementing the Future trait
               | (implementing a trait is standard practice in Rust). Only
               | this often requires awareness around auto traits like
               | Send, HRTBs and pin projection, (which happens to be one
               | of the most complex things I've done), and all I'm trying
               | to do is wrap some user provided future. These deep
               | topics are more of a convoluted type system puzzle (and
               | if you like those it can be fun). But it has very little
               | to do with concurrency and much less with whatever
               | business logic we're trying to manage.
        
         | brink wrote:
         | > writing code in it is very hard because it constantly feels
         | like you're wrestling the compiler
         | 
         | I've been doing Rust for about two years. This difficulty
         | eventually subsides and writing "safe" code becomes second-
         | nature. I rarely wrestle with the compiler any more.
        
           | rascul wrote:
           | It took me about a month of free time coding to quit fighting
           | the compiler. I'm not sure who won, but we work together now.
           | 
           | It's a real good feeling when you can finally write 100 lines
           | or so that rustc takes on the first try. Even if it was all
           | comments...
        
           | geodel wrote:
           | Agree. For other languages it would be Stockholm syndrome but
           | in Rust's case it is enlightenment.
        
           | stormbrew wrote:
           | For me I'd describe it as having transitioned from "fighting
           | with the compiler" to "having a conversation with the
           | compiler." If I'm doing anything at all non trivial there's a
           | back and forth there still but I appreciate and understand
           | the feedback more now.
        
         | puffoflogic wrote:
         | A likely large contributor to others' experience not matching
         | yours is async: Newcomers often refuse to try rust's excellent
         | native threading support and jump right to the badly tacked-on,
         | lets-write-javascript-in-rust monstrosity called async. Async
         | "won" in the rust ecosystem because of superior branding but it
         | is by far the worst solution to parallelism in rust. It has, by
         | necessity, 100% of the problems and limitations of threading,
         | such as they are, plus many more of its own. It's impossible
         | that async could ever be easier than threading and yet
         | countless newcomers are lured in and convinced they don't
         | understand threads therefore need async. "I don't understand
         | how to fly a Cessna therefore I need to fly an F-15."
        
           | cmrdporcupine wrote:
           | Yep and the worst is that it seems that now 3rd party
           | dependencies basically force it because they've also made
           | that choice.
           | 
           | And one thing in your stack is async, everything else ends up
           | following.
        
           | Zababa wrote:
           | > Newcomers often refuse to try rust's excellent native
           | threading support and jump right to the badly tacked-on,
           | lets-write-javascript-in-rust monstrosity called async.
           | 
           | To be fair, many of those newcomers have heard that threaded
           | code is very hard to get right (which is repeated by so many
           | people these days), and/or come from the JS world where async
           | is pretty much the only choice you have. This is something
           | that may be partially fixed by more communication. For
           | example, the Rust book currently doesn't cover async at all.
           | Adding a chapter on async and when to use it might help.
           | Another issue is that lots of people come to Rust from/for
           | webdev. The most popular web frameworks (actix-web, rocket,
           | ...) are all using async. I don't have any idea on how to fix
           | this.
           | 
           | If what you say is true, that "It's impossible that async
           | could ever be easier than threading", then I think that's
           | something that people should know and tell other people.
        
           | the__alchemist wrote:
           | I'd love an async filter on `crates.io` and `docs.rs`.
        
           | remram wrote:
           | Async has been in development for a few years during which
           | the experience wasn't great. The popularity of Rust made it
           | so many people wanted to try it anyway, with a plethora of
           | frameworks being developed and replaced and not working when
           | the next version of futures/tokio/hyper came out.
           | 
           | The experience now that futures are in the standard library
           | and tokio etc are actually stable is much better. Most async
           | libraries are thread-safe, contrary to the JavaScript or
           | Python asyncio worlds, so you are free to call call
           | block_on(func(...)) in whatever thread if that is your
           | preferred coding style and the library doesn't already expose
           | a blocking interface. The low-level "zero-cost" future
           | composition is available to you if you need to squeeze a lot
           | of performance but you absolutely don't have to wrestle with
           | the "monstrosity" if you don't want to.
        
           | geodel wrote:
           | Well, users are obsessed with Async because Rust authors
           | themselves are obsessed with it. The amount of discussions
           | around design and development of Async feature is endless.
           | The common theme is how a normal crappy Go app will become
           | super app with Rust's zero cost async support.
           | 
           | I can understand they chose this path to gain market share by
           | having tons of web services written in Rust. And async might
           | be great fit for it. But now one can't just go around and say
           | 'Oh, Rust async is not for plebs they can continue with
           | something much simpler to fulfill their needs'.
        
           | josephg wrote:
           | Async works great in other languages. I adore being able to
           | get high performance out of a single thread in javascript
           | thanks to its async IO model.
           | 
           | Rust's problem with async isn't that async itself is a bad
           | idea. The problem is that rust got halfway through adding
           | async support and then didn't finish the job.
           | 
           | If you have half a house, your problem isn't that houses are
           | a bad idea. You just need a builder. (Or, a wrecking ball.
           | Which I'd be more than happy with at this point.)
        
             | mwcampbell wrote:
             | > (Or, a wrecking ball. Which I'd be more than happy with
             | at this point.)
             | 
             | I doubt that would be necessary or appropriate. A lot of
             | thought, discussion, and work has already gone into the
             | design, and I'm inclined to assume that the people involved
             | knew what they were doing. Rust's zero-overhead approach to
             | async is much more ambitious than the async support in
             | other languages. More work on the interactions with other
             | language features would certainly be useful, but I think
             | suggesting that the existing implementation be discarded is
             | more likely to frustrate the people who have been doing all
             | of this hard work than to accomplish anything useful.
        
         | mamcx wrote:
         | Totally!
         | 
         | I return to Swift/Kotlin for new UIs and wrestle with their
         | errors.
         | 
         | Man, "wrestling the compiler" in Rust is SOOOO much better!
         | 
         | ... and this is even considering very simple things (like see
         | how they choke in simple syntax error with so small help
         | provided)
        
         | inamberclad wrote:
         | Generally, I've found that wrestling the compiler involves
         | doing something that should really be done in another way.
        
         | hintymad wrote:
         | How are Rust's concurrency tools compared with those of Java?
         | In Java we rarely need to use mutex at all. Instead,
         | programmers use high-level synchronizers (latches, barriers,
         | phasers, exchanges, and etc) and containers (concurrent
         | collections, executors, various pools and flows, and etc). I
         | don't have extensive experience in Rust, and somehow I saw
         | Mutex everywhere.
        
         | Chio wrote:
         | To add my own few cents to this very common discussion Rust is
         | hard is the same way that most programming languages that rely
         | "non-standard" paradigms are hard because they challenge your
         | current mental model of programming. However "different",
         | instead of "hard", would be a better way to describe these sort
         | of languages like Rust, Prolog, and Haskell (as well as a ton
         | of other languages).
         | 
         | If you look at Rust from this perspective then it becomes much
         | more valuable to consider learning because it teach you a
         | different way to modelling your data, and how to break-up your
         | code; and while a language like Java may not force you to
         | consider the borrow checker you will probably be a better
         | overall Engineer knowing how to make it happy even when working
         | in other languages.
         | 
         | On the topic discussed in the actual article: I can't wait for
         | scoped threads to finally go stable since being forced for
         | throw an Arc around almost everything you want to share between
         | threads does not really suit Rust which really emphasise zero-
         | copy in their standard library.
        
           | josephg wrote:
           | I think a lot of the complaints about rust's difficulty come
           | from people trying to use async in rust. I don't think the
           | problem there is that rust is "different". The problem is
           | that async rust isn't ready yet.
           | 
           | Rust's ecosystem pushes users toward using async for IO, and
           | async support in the language & compiler is wildly
           | incomplete. And it has been for years - the last big async
           | feature (the async keyword) landed 2.5 years ago [1]. But its
           | barely usable as-is. Building software with async today feels
           | like trying to build a house out of daggers. Traits? Nope.
           | Closures? Nope. Regular types? Only if they're Pinned. Your
           | types are pinned, right? Iterators over async objects? Nope
           | that doesn't work. Library support? Without traits, libraries
           | are limited in what they can provide. Async rust? Batteries
           | are not included.
           | 
           | We need TAIT, GAT, async closures, async iterators / streams,
           | and a bunch of other little quality of life improvements
           | before I'd consider it "done". I don't know where async's
           | momentum went, but its a bit disappointing how halfbaked
           | async is given how nice the rest of the language is.
           | 
           | [1] https://areweasyncyet.rs/
        
             | tayo42 wrote:
             | How are people writing high throughput web/network services
             | without async? Is there a async library to use. Like what
             | do you reach for if you wanted to write redis or nginx with
             | rust?
        
               | TFortunato wrote:
               | I'm not a rust expert by any means, but redis and nginx
               | are both written in C, which doesn't have async as a
               | language feature. Is there a reason the techniques used
               | there wouldn't translate to rust, regardless of the state
               | of rusts native async support?
        
               | tayo42 wrote:
               | yeah, rusts async/await is just making it nicer to use
               | the same ideas. like is there a libuv or libevent in the
               | rust world thats being used?
        
               | steveklabnik wrote:
               | https://crates.io/crates/mio is the de-facto standard
               | package that's similar to libuv/libevent. The most
               | popular async executor, Tokio, is built on top of this.
               | They're maintained by the same organization.
        
               | tayo42 wrote:
               | I thought this library had alot less features then the
               | popular c event loop libraries?
        
               | steveklabnik wrote:
               | I haven't written anything against it directly in years
               | at this point, so I can't speak to that, it's just the
               | best example of a library at the same level of
               | abstraction.
        
               | steveklabnik wrote:
               | You can, it's just not as nice. Writing code this way can
               | also require unsafe. Async in Rust is primarily about
               | achieving zero-cost async code in a safe way.
        
             | tomjakubowski wrote:
             | I totally agree. I've been working with Rust since before
             | 1.0, and I love the language, and I never want to work on
             | async code in Rust. The mental model is too hard for the
             | payoff. I've also found debugging async code to be more
             | nightmarish.
             | 
             | Most Rust applications I've worked on which have used some
             | kind of parallelism/concurrency would be fine with a thread
             | pool of workers and good old sync channels.
        
             | Chio wrote:
             | I agree wholeheartedly on your points regarding async,
             | which is a topic I've tried to avoid so far in all of my
             | Rust projects because of all the reasons you've already
             | raised above and you really don't need it for most use-
             | cases.
        
           | mamcx wrote:
           | > Rust is hard is the same way that most programming
           | languages that rely "non-standard" paradigms are hard
           | 
           | Agree.
           | 
           | And the problem is not (mainly) async, the borrow checker,
           | etc.
           | 
           | Rust is truly different to other "imperative looking,
           | functional looking" languages. I suspect the choice of make
           | it look too close to C is part of the issue: You come to it
           | and quickly start producing code as if it were another
           | C/python/C# and that is a major mistake.
           | 
           | In specially, because Rust make SO MUCH SO EASIER... but _not
           | the things that other langs make easier_ (use of `String`
           | anyone?), so is a major shock to see that supposedly
           | "simple" things "not work".
           | 
           | Is only after getting that the core of Rust is `Struct Enum
           | Pattern Matching Moves & Borrows`, _and pls_ , stick all
           | together with this `Traits` & composition, that are part of
           | this important `Paradigms` is when Rust click.
           | 
           | This is the shock: Rust is not about the use of some `types`
           | and then apply algorithms. Is the MODELING of behaviours
           | (traits) and the INTERACTION of the types/traits.
           | 
           | That is the mind-bending. Is like see programming flipped!
        
           | klabb3 wrote:
           | > I can't wait for scoped threads to finally go stable since
           | being forced for throw an Arc around almost everything you
           | want to share between threads does not really suit Rust which
           | really emphasise zero-copy in their standard library.
           | 
           | Note that this is only for lexical scopes so each set of
           | scoped threads you create must be destroyed in the same
           | lexical scope.
           | 
           | In practice, this means that thread pooling (and in
           | particular async runtimes) cannot use them.
           | 
           | In fact, we used to have the closure passed to thread and
           | join handle had a lifetime param 'a (not 'static), but this
           | was unsound in combination with Arc etc that didn't require
           | those. If you're interested, it's related to the drop
           | guarantees and safety of `mem::leak`. There was a big debacle
           | right before 1.0 and, imo, the team rushed this decision and
           | we're paying for it with Arcs - any async code base is
           | riddled with it.
        
         | Thaxll wrote:
         | It's great until you touch async to which Go is way better and
         | easier to use.
        
       | singhrac wrote:
       | I really liked this article, but if I can provide some sort of
       | drive-by advice (also for others looking to write technical
       | content), providing some examples of where to _use_ various
       | traits would really help, e.g. what kind of data structure one
       | would implement !Send on.
        
         | drogus wrote:
         | That's a good point and I think I will add a paragraph or too
         | about that. The simplest answer is: as long as you're not doing
         | any unsafe Rust you should just use whatever is derived from
         | types within a type. If you have a struct where all fields are
         | `Send`, then the struct will be `Send` too. If you add anything
         | that is `!Send` (like `Cell`), it will be `!Send` and you don't
         | have to explicitly mark is as `!Send`.
         | 
         | The most common exception to this is when you implement a type
         | that has a `!Send` attribute, but you still mark it as `Send`,
         | because you implement an API that guards against misusing the
         | type. I honestly can't think of any practical example of the
         | opposite (ie. you have a type with all `Send` attributes), but
         | that would probably be similar: you have a type with all `Send`
         | attributes, but you implement some kind of API that makes it
         | unsafe to sent the type between threads.
        
       | hintymad wrote:
       | I think a programmer can get over the "Rust is hard" part after
       | writing certain amount of code. The type system and the borrow
       | checker will just become intuitive enough for a programmer to
       | grasp. I do have a question about productivity, though: what
       | added productivity does Rust bring over languages like Go or Java
       | for writing RPC/HTTP services, given that Rust requires an
       | engineer to think about memory management all the time, while GC
       | languages don't?
        
       ___________________________________________________________________
       (page generated 2022-06-06 23:02 UTC)