Should modifying private members be @system?

ag0aep6g anonymous at
Fri Oct 4 12:13:29 UTC 2019

On Friday, 4 October 2019 at 11:55:11 UTC, Dennis wrote:
> ```
> 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.

You don't know that in opIndex. In opIndex you just know that 
there's a `T* ptr` and a `size_t _length`. opIndex doesn't know 
where they came from or if they're compatible.

> 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.

You're not marking the module as @trusted. You're marking 
opIndex. When you justify @trusted with something outside the 
marked function, you're misusing it.

Unfortunately, breaking the rules like this is rather common. But 
it's still breaking the rules. It's still undermining @safe.

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

My best idea so far (might not be originally mine) is to let the 
@system attribute apply to variables. You'd mark `_length` as 
@system and the effect would be that @safe functions would not be 
allowed to access it.

More information about the Digitalmars-d mailing list