`restricted` member variables

Mike Parker aldacron at gmail.com
Tue Jun 21 00:33:24 UTC 2022


On Monday, 20 June 2022 at 15:49:20 UTC, Paul Backus wrote:

>
> I'm not convinced the extra granularity is worth adding an 
> entire new attribute for.

My main motivation was the case of having a setter with a 
contract that serves as a cheap invariant:

```d
class Foo {
     int _x;
     void x(int newX)
     in (newX < 1000)
     { _x = newX; }
}
```

If we replace that with an invariant, the problem isn't that the 
module has access to the protected variable. The problem is that 
any function in the module that does access the variable is 
effectively part of the public API, thereby violating the 
guarantee that the invariant is checked when accessed through the 
public API. So that is solvable without a new level of protection 
just by making sure that every write to the variable from within 
the module triggers the invariant check.

The purpose of the function contracts is to validate function 
input and output, but for a setter like the above it effectively 
serves as an invariant as long as nothing writes directly to `_x` 
  outside the setter. And from that perspective, it would be nice 
if there were a way to guarantee that happens both within the 
module and within the class.

So I guess what I'm really after isn't `restricted`, but a 
targeted invariant, perhaps of the form`invariant(_x) _x < 1000` 
that only triggers when the protected variable is written to. It 
just seems overkill to me that an invariant for one member 
variable is run on calls to every member function.

But that also isn't wholly necessary. I can always wrap `_x` in a 
struct, give it a setter and an invariant/contract, and put that 
in a separate module.

So yeah, `restricted` is pointless. The targeted invariant would 
be nice, though.


More information about the Digitalmars-d mailing list