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