Hacker News new | ask | show | jobs
by sharikous 1597 days ago
What is the reason for the rule objects have to be always in a good state even inside unsafe?
2 comments

One of the core ideas behind unsafe blocks is that they don’t actually change any semantics. All they do is allow more operations. This makes it a lot easier to reason about (for both the programmer and the compiler) since there’s not two different set of rules to remember.

It does however makes things a bit clunky since the unsafe bits need to ensure a “safe” state throughout the whole block and not only by the end of it.

I’ve never understood why they don’t just support partially initialized structs. They’re already doing control flow analysis for initializing variables. It seems like a natural extension to do this for aggregate types (product and sum). From a type theory perspective, a struct T is not a T in unitialized state, it’s. “partial T” that at some point gets transformed into a T. So, you’d not be able to use the T in the normal sense until the compiler can prove that all fields have been init on all possible control flow paths.

Why is this problematic? (I presume there is a fatal flaw as it seems too obvious of a solution..)

Rust already supports partially deinitialized structs - that is, moving out of a struct field by field - and there’s no fundamental reason it can’t support partial initialization too.

Indeed, there’s an open issue for it:

https://github.com/rust-lang/rust/issues/54987

But there are a lot of desired features with open issues, so don’t expect this to be implemented anytime soon unless someone takes an interest in it.

Ah okay this makes sense. I wish I personally had the spare time to contribute this.
It's not problematic, it's just not work that's been done yet. Rust isn't finished. I bet you could get an RFC pushed through and implement it if you wanted to, it certainly is a promising idea.
As an example, in C the following is quite common:

Data dat;

dat.a = 1;

dat.b = “foobar”;

do_thing(&dat);

I seems like the compiler should be able to treat “dat” as an “maybe uninit” type until after “dat.b” gets assigned.

Because the compiler makes assumptions on the valid layouts of a type, e.g. packing Option<bool> in a single byte. Prior to 2018 it was assumed the UB was only on read like C but that turned out not to be the case. To avoid this the type has to reflect that it might be uninitialized - hence the transparent MaybeUnit wrapper.