From D Wiki
Jump to: navigation, search

DIP21: Fixing @property

Title: DIP Template
DIP: 21
Version: 1
Status: Draft
Created: 2012-11-19
Last Modified: 2012-11-19
Author: Adam D. Ruppe


If we make @property rewrite to a call, while leaving the rest the same, we fix problems without creating new ones.


We want to keep existing code working as much as possible. Some code uses the same function with and without parenthesis, especially with UFCS. This is currently allowed, but can cause ambiguity with functions returning a callable or a reference. Additionally, UFCS blur the difference between setter and getter that implicit when using @property as show below :

See some example below that are confusing ATM :

  1. [1, 2].front is now equivalent to front = [1, 2]
  2. void function() foo() { ... } it is now unclear what foo() does.
  3. @property void function() foo() { ... } it is now unclear what foo() does.
  4. ref int foo() it is now unclear what &foo does.
  5. @property ref int foo() it is now unclear what &foo does.


There's a fairly easy way to do this, thanks to the @property word:

  1. Any function without @property remains exactly the same as it is now. Parens are *not* required on them.
  2. Any function with @property is rewritten into a call immediately. Therefore, putting () is naturally an error or delegate call because of the return value.
  • @property int foo() {}
    • foo; rewritten into foo() transparently
    • foo(); since foo is already foo(), this becomes foo()() - an error because you cannot call an int like a function

The only potential for code breakage here is on stuff marked @property, which if you have been marking it on semantic properties already (NOT on places where you just wanted appease the -property switch's idiotic rules), should be fine.

If in doubt, leave @property off. That leaves things exactly as they are.


On Tuesday, 20 November 2012 at 12:44:44 UTC, Jacob Carlborg wrote:

Should this be allowed for functions that isn't marked with @property: foo = 3;

Yes. We should *only* be changing the way @property is implemented. (Namely, actually implementing it!)

Don't want to break existing code. The new changes must be opt in.

If there's both an @property setter and a regular function, the property should be used here.

Generally, overloading on @property could be allowed.

If there isn't a setter, you don't change things.

If setter is present: foo = foo + 1; // becomes: foo(foo() + 1);

If setter is not present: foo = foo + 1; // becomes: foo() = foo() + 1;

If foo returns an rvalue, this is a natural error. If it returnsref, it works fine.

I'm not sure how it fit in the DIP but &funName is ambiguous when funName return a reference.

We can just define this away: &funName if it isn't a @property is the address of the function.

If it is a @property, ALL operations work on the return value, so it is rewritten as &(funName()).


This document has been placed in the Public Domain.