Semi-RFC: Unsafe fields


#1

After reading how unsafe rust is relient on the state entablished by the safe rust, I started to think about ways to represent this reliency.
With traits one can mark them unsafe, which means that to be able to implement them you need to use unsafe again.
So why don’t we allow usage unsafe keyword before structs fields?

struct A {
    unsafe size: usize,
}

This would make it to require that all access to the field needs to be within unsafe block.
With this you could clearly mark what parts of a struct are relied upon inside unsafe blocks.

Open questions

First I thought it would be enough to limit write access of unsafe variables to unsafe blocks, because modification is only way to break invariants, but then I thought about interior mutability. Is interior mutability really a problem?
Unsafe code can still rely non-unsafe variables, because its optin nature. It also requires programmer to add quite noisy incantation to the variable. So would people actually use this and would it actually be useful at all?


#2

I don’t think it is practical to unsafe-taint all code that can contribute to unsafe code being wrong. Local variables, “safe” calculations in the same function, data stored in data structures calculated by safe code, safe helper functions, can all feed into the calculations of values that are eventually used in unsafe code such that a bug in any of this safe code can make the unsafe code fatally wrong. The approach in the Rustonomicon, putting the entire module under the same scrutiny, is saner than requiring arcane invocations on all of these components.


#3

Well this addition wouldn’t actually taint any code.
It would be basically a tool that programmer can use to taint their code.

Still you bring a valid point. I only considered the abitilty to taint fields, because they are seperate from code. I did’t think of need to to be able to taint local variables and stuff like that. Maybe there are cases where you’d want to annotate those unsafe as well?

Hmm…So basically I am thinking ways to expand what you can declare unsafe to allow greater control on what is considered unsafe.


#4

I guess I did not make this very clear, but my position applies equally to opt-in “lints”. I can see how for fields specifically this might be useful, since fields can be modified by unrelated safe code very far removed from the unsafe blocks, with no calls linking it to the unsafe code, making it less obvious that the change is potentially dangerous. At the same time, extending such features to cover more and more things has diminishing returns. It’s a question of where in the blurry spectrum we should put a hard line. Unsafe fields might fall on the right side of the line (but I’ll defer judgement to people who write large modules with unsafe and non-trivial invariants on fields). Other things might not.


#5

Heh, this is now the fourth time this feature has been proposed independently: see RFCs 80, 358, and 588. Perhaps the fact that this has been proposed so many times indicates how desirable a feature it is.


#6

Many things have been frequently proposed that will never happen (significant whitespace?) :wink:

As the author of the nomicon, I agree with @rkruppe’s assessment that trying to track the whole unsafety thing is really just a big ol’ mess. Embrace that you’re doing some unsafe stuff, and that means you need to understand the code.

Another tricky case: when unsafe code decides to rely on properties of safe code it calls (Box can’t panic, Vec::iter_mut doesn’t read the memory so it’s fine to iterate uninit memory with, etc).