Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> To me it seems more like they're just indexing off the Rust philosophy that zero-values are inherently unsafe and must not be allowed at a language level.

I don't think that "zero-values are inherently unsafe" is a Rust philosophy? I think it's more about some sense of control and/or design - Rust shouldn't force types to have a zero value if a zero value doesn't make sense (e.g., references, NonNull<T>), and Rust shouldn't force your type to have zero as its default value if another default would be more appropriate.

> However a programmer can just as easily set an encryption key to `default()` in Rust and end up with the same issue. It may be "explicit" but programmers get in habits of using things like `default()` and so it's still as likely to happen as it would with non-explicit defaults IMHO.

default() would only be usable if the encryption key type implements Default and I think I'd be a bit on the skeptical side with respect to how likely Default would be "accidentally" implemented on it. Putting aside questions about how Default on an encryption key made it into the codebase in the first place, IIRC array types for representing crypto keys are not that uncommon and I don't think Default is implemented for arrays (by default?), so #[derive(Default)] wouldn't even compile and I'm not sure impl Default would be common enough to be something that's done out of habit.

Specific example aside, I'm not Default is one of those traits that are habitually added to structs in the first place?

> Requiring non-zero values isn't worth the mental overhead in the other 99.9% of cases where zero-values can simplify a lot of coding to say declare a stack array of zero-valued structs or unions, etc.

Would it really be that much simpler? For example, in Rust for Copy types:

    [DefaultStruct::default(); SIZE]
vs.

    [NonDefaultStruct { value: defaultValue }; SIZE] // other options available as well
I'm also not sure whether instances where zero values simplify things outweigh the ability to more accurately model your domain in the type system. Sure, declaring a stack array of zero-valued structs/unions might be simpler, but I feel being able to more accurately model your intended domain by making invalid states unrepresentable would be more generally useful.

> In those cases you can make the zero-value of a union type where the zero value is `UnInitializedBadEncryptionKey`.

The disadvantage to that approach is that now everything that deals with that union type needs to know about/deal with uninitialized values even if such values are only ever transient during initial construction and are supposed to be impossible otherwise. It's arguably cleaner to make such a state unrepresentable at all and use a different mechanism to represent being uninitialized. For example, Rust again:

    let uninit = [const { MaybeUninit<NonDefaultStruct>::uninit() }; SIZE];
    // initialize as appropriate
    let init = unsafe { std::mem::transmute<_, [NonDefaultStruct; SIZE]>(uninit); }
And now all code that deals with NonDefaultStruct knows for sure it has been properly initialized.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: