This is an old blog post of mine, but I still really appreciate this subtle feature of Rust: one of the ways it supports robust thread-safe concurrent code is by _not making everything thread-safe._ It's odd that this property is so rare in languages. Just like how clear boundaries are critical in relationships, being able to designate which parts of your program _can't_ be shared across threads is critical for ensuring that the shared parts are correct.

https://cliffle.com/blog/not-thread-safe/

#rustlang

Safely writing code that isn't thread-safe

An under-appreciated Rust feature

I was musing on this because, as a for-fun thing, I'm rewriting some complex Go code in Rust, replacing ornate goroutine concurrency with compiler-managed concurrency with async... with no runtime.

It turns out the Go code is chock full of data races. I'm finding them because they're compile errors in the Rust code. So it's very nice to be able to draw lines around "this bit is async but not threaded" vs "this bit is not even async."

...unrelated to concurrency, I've noticed a class of Go footgun that I hadn't hit before:

// Foo contains a public Var field
type Foo struct { Var int32 }
// Bar contains a private var field and a Foo
type Bar struct { Foo; var int32 }

Bar is "embedding" a Foo, which causes it to do the equivalent of a Rust Deref coercion -- syntactically it now has a field called Var, in addition to one called var. (In the actual code I'm studying, this fact is far less obvious, spread across a couple of files and several dozen fields.)

These fields differ only in capitalization, which is Go's convention for public/private. And they're incredibly easy to confuse -- the code contains at least one bug resulting from this. The linter, which I am now running thanks to the lsp, is silent.

Anyway, check your capitalization!