@property fields

Richard Andrew Cattermole (Rikki) richard at cattermole.co.nz
Tue Dec 3 23:50:20 UTC 2024


The ``@property`` attribute has been left in the lurch for quite 
some time, where only one behaviour related to its return value 
being of any value.

There are two parts of this proposal, however I am only confident 
in the first part, fields.
The other is for methods which would give you full control over 
it.

Syntax is quite simple:

``@property int field;``

It is valid in interfaces, structs, and classes.

```d
interface IField {
     @property int field;
}

class Thing : IField {
     @property int field;
}

struct Thing2 {
     @property int field;
}
```

It results in three things.

1. A field that is either ``protected`` (classes) or ``private`` 
(structs).

     ```d
     class Thing : IField {
         protected int field;
     }

     struct Thing2 {
         private int field;
     }
     ```

     If we have struct inheritance, then it would be ``protected`` 
instead.

2. It will generate a method for classes and structs in the form:

     ```d
     class Thing : IField {
         protected int field;

         ref typeof(this.field) __property_field() /* inferred 
attributes */ {
              return this.field;
         }
     }

     struct Thing2 {
         private int field;

         ref typeof(this.field) __property_field() /* inferred 
attributes */ {
              return this.field;
         }
     }
     ```

3. A method stub is generated for the property field in an 
interface:

     ```d
     interface IField {
         ref typeof(this.field) __property_field();
     }
     ```

     You may place attributes around the field to apply to the 
method.

     ```d
     interface IField {
         @safe:
         @property int field;
     }
     ```

    This allows an interface to require that a field exists, 
without defining one. Since it is the stub that gets inherited 
(which can only be implemented using an ``@property`` field.

Semantically:

1. You will not have direct access to the field outside of the 
type. All accesses and mutation will go through the method.
2. It may be passed to a function parameter that is ``ref`` or 
``out``. This is perfectly safe so needs no protection due to it 
implicitly being ``scope``.
3. An invariant will be called following mutation or when it is 
passed to a ``ref`` or ``out`` function
parameter.
     3.1. For interfaces if a ``@property`` field is used, an 
invariant will be required to be in the vtable implicitly.
4. In ``@safe`` code:
     4.1. It may not be stored in a ref variable ``ref var = 
thing.field;``
     4.2. It may not have a pointer taken to it ``&thing.field``

As long as the invariant is called after mutation, this covers 
the use case of setter methods for properties. It cannot be used 
to transform, but will cause errors. If you need transformation 
wrapping the field with a struct could introduce such behaviors 
so need not be provided at this level (although it should be 
supported with ``@property`` methods).




More information about the dip.ideas mailing list