Not quite, because depending on the compiler implementation / memory model, other things can also lead to UB, and thus be unsafe, e.g.:
* data races in a multi-threaded program
* type-casting to the wrong type (e.g. via unions) with compiler optimizations that rely on proper types
* assuming values are absolutely never aliased (shared xor mutable) when there's actually a way to create aliased values (e.g. unsafe {} and raw pointers)
* creating objects out of a sequence of bytes that is not valid for their type
I think K8s couples two concepts: the declarative-style cluster management, and infrastructure + container orchestration. Keep CRDs, remove everything else, and implement the business-specific stuff on top of the CRD-only layer.
This would give something like DBus, except cluster-wide, with declarative features. Then, container orchestration would be an application you install on top of that.
Edit: I see a sibling mentioned KCP. I’ve never heard of it before, but I think that’s probably exactly what I’d like.
Own and uninit have been in discussions wrt in place construction. The Rust in the Linux kernel project seems to be the motivating use case for this that really got the effort going recently.
Are you sure you mean concurrency safety, and not thread safety?
I think Rust's concurrency safety (e.g. async on a single thread) is mostly granted by the Pin trait [1], and the async code-gen making sure lifetimes make sense over .await points (which requires things to be either pinned across those points, or to not care about their location in memory potentially moving).
Thread safety is instead given by a couple of auto-derived marker traits, called Send and Sync [2], that denote which kinds of data can be sent or shared between threads safely.
This is coupled with types like Arc, Mutex, etc that can wrap data that isn't safe to share, so that the wrapped data as a whole is safe to share. It is also coupled with functions (like std::thread::spawn [3] and MPSC's send()) that have a requirement for the data to either be Sync/Send, or to take full ownership of it (which ensures there are no other active references to it).
Thanks. I actually don't know much about concurrency/lock so I just took whatever the post said. I shall quote:
Galen Hunt Author
Distinguished Engineer at Microsoft
3d
@Sukesh Ashok Kumar No memory safety. No concurrency safety. Of course, for a single C or C++ code base, these qualities can be achieved with extraordinary discipline and effort--and lost with just a single mistake. With Rust, can be proven by the compiler.
I see, most likely thread-safety then. Rust will prevent accessing data shared between threads unless you first lock a mutex, use an atomic, etc.
Or rather, it gives abstractions so that higher-level types in stdlib and other libraries can prevent such access. The low-level implementation of the Mutex/etc types themselves do the same thing C and C++ do, via unsafe blocks, atomic primitives, fences, etc.
In Rust you typically use the "log" crate, which also has a global logger instance [0]. There is also "tracing" which uses thread local storage.
As another comment said, global state is allowed. It just has to be proven thread-safe via Rust's Send and Sync traits, and 'static lifetime. I've used things like LazyLock and ArcSwap to achieve this in the past.
I've been having an absolutely great time with Rust's bumpalo crate, which works very similarly. The lifetime protection still works great, and it's actually a lot more permissive than normal Rust, since it's the same lifetime everywhere.
The sad exception is obviously that Rust's std collections are not built on top of it, and neither is almost anything else.
But nevertheless, I think this means it's not a Zig vs Rust thing, it's a Zig stdlib vs Rust stdlib thing, and Rust's stdlib can be replaced via #[no_std]. In the far future, it's likely someone will make a Zig-like stdlib for Rust too, with a &dyn Allocator inside collections.
> In the far future, it's likely someone will make a Zig-like stdlib for Rust too, with a &dyn Allocator inside collections.
This exists in the nightly edition of Rust, but is unlikely to become a feature in its current form because the alternative of "Storages" seems to be a lot more flexible and to have broader applicability.
* data races in a multi-threaded program
* type-casting to the wrong type (e.g. via unions) with compiler optimizations that rely on proper types
* assuming values are absolutely never aliased (shared xor mutable) when there's actually a way to create aliased values (e.g. unsafe {} and raw pointers)
* creating objects out of a sequence of bytes that is not valid for their type
...and likely many others I can't remember.
reply