Should modifying private members be @system?

Dennis dkorpel at gmail.com
Fri Oct 4 11:55:11 UTC 2019


Imagine I am making my own slice type:

```
struct SmallSlice(T) {
     private T* ptr = null;
     private ushort _length = 0;
     ubyte[6] extraSpace;

     this(T[] slice) @safe {
         ptr = &slice[0];
         assert(slice.length <= ushort.max);
         _length = cast(ushort) slice.length;
     }

     T opIndex(size_t i) @trusted {
         return ptr[0.._length][i];
     }
}
```

The use of @trusted seems appropriate here, right? I'm doing 
pointer slicing, but I know that the _length member is correct 
for ptr since it came from a slice. The struct couldn't have been 
void-initialized or overlapped in a union since that's not 
allowed in @safe code when there are pointer members. Using { 
initializers } is not allowed since I have a constructor, and the 
members are private so they can't be modified outside of my 
(thoroughly audited) module.

Except that last thing isn't true:

```
import std;
void main() @safe {
     int[4] arr = [10, 20, 30, 40];
     auto slice = SmallSlice!int(arr[]);
     __traits(getMember, slice, "_length") = 100; // change 
private member
     writeln(slice[9]); // out of bounds memory access
}
```

__traits(getMember) enables one to bypass private, so the 
@trusted use was incorrect. This bypassing makes it really hard 
to write @trusted code relying on the integrity of the struct. 
How are you going to do @safe reference counting when the 
reference count can be tampered with from @safe code outside the 
control of the library writer?

I'm tossing the idea that __traits(getMembers) should be @system 
when it's bypassing visibility constraints of the member. What do 
you think?


More information about the Digitalmars-d mailing list