February 01, 2019
On Thursday, 31 January 2019 at 21:50:32 UTC, Steven Schveighoffer wrote:
> On 1/31/19 4:46 PM, Olivier FAURE wrote:
>> On Thursday, 31 January 2019 at 18:31:22 UTC, Steven Schveighoffer wrote:
>>> BTW, the DIP discusses how to annotate these rare situations:
>>>
>>> int doubleMyValue(ref int x) { ... }
>>> @disable int doubleMyValue(int x);
>>>
>> 
>> I don't think that's a solution. The problem is in the getter method, not in doubleMyValue. If nothing else, since the DIP is designed to work on existing functions, it could happen on doubleMyValue functions which would be both designed by and used by people completely unaware of DIP-1016.
>
> How is the problem not in doubleMyValue? It's sole purpose is to update an lvalue. It is the perfect candidate to mark with @disable for rvalues.
>
> -Steve

Shouldn't doubleMyValue(pt.x) be a compiler error if pt.x is a getter? For it not to be a compile error pt.x should also have a setter, in which case the code needs to be lowered to something else:

{
  auto __temp = pt.x;
  doubleMyValue(__temp);
  pt.x = __temp;
}

I believe this is something along the lines of what Swift and C# do as well.

Or something... a DIP to fix properties anyone? :)

Also, this applies to a much wider variety of operations on properties that return rvalues and not just on functions calls no?

struct B {
    int x;
}
struct A {
  B _b;
  @property B b() { return _b; }
}

void main() {
    A a;
    a.b.x += 1;
    writeln(a.b.x); // 0
}



February 01, 2019
On 01.02.19 10:10, aliak wrote:
>>
> 
> Shouldn't doubleMyValue(pt.x) be a compiler error if pt.x is a getter? For it not to be a compile error pt.x should also have a setter, in which case the code needs to be lowered to something else:
> 
> {
>    auto __temp = pt.x;
>    doubleMyValue(__temp);
>    pt.x = __temp;
> }
> 
> I believe this is something along the lines of what Swift and C# do as well.
> 
> Or something... a DIP to fix properties anyone? :)

http://wilzbach.github.io/d-dip/DIP24

I'm not sure your rewrite is good though, because it does not preserve aliasing during the function call.
February 01, 2019
On Friday, 1 February 2019 at 11:48:51 UTC, Timon Gehr wrote:
> On 01.02.19 10:10, aliak wrote:
>>>
>> 
>> Shouldn't doubleMyValue(pt.x) be a compiler error if pt.x is a getter? For it not to be a compile error pt.x should also have a setter, in which case the code needs to be lowered to something else:
>> 
>> {
>>    auto __temp = pt.x;
>>    doubleMyValue(__temp);
>>    pt.x = __temp;
>> }
>> 
>> I believe this is something along the lines of what Swift and C# do as well.
>> 
>> Or something... a DIP to fix properties anyone? :)
>
> http://wilzbach.github.io/d-dip/DIP24
>
> I'm not sure your rewrite is good though, because it does not preserve aliasing during the function call.

You mean if __temp is modified in the doubleMyValue and pt.x aliases something else? Or? Wouldn't the assignment back "just work"?

And is there a rewrite that would work then?
February 01, 2019
On Friday, 1 February 2019 at 11:48:51 UTC, Timon Gehr wrote:
> On 01.02.19 10:10, aliak wrote:
>>>
>> 
>> Shouldn't doubleMyValue(pt.x) be a compiler error if pt.x is a getter? For it not to be a compile error pt.x should also have a setter, in which case the code needs to be lowered to something else:
>> 
>> {
>>    auto __temp = pt.x;
>>    doubleMyValue(__temp);
>>    pt.x = __temp;
>> }
>> 
>> I believe this is something along the lines of what Swift and C# do as well.
>> 
>> Or something... a DIP to fix properties anyone? :)
>
> http://wilzbach.github.io/d-dip/DIP24
>
> I'm not sure your rewrite is good though, because it does not preserve aliasing during the function call.
Not only that, but C# forbids you passing properties as an ref/out parameter.
(The properties should be redefined as accessor, such that you can't take the address of it)
-Alex
February 01, 2019
On Friday, 1 February 2019 at 14:41:52 UTC, 12345swordy wrote:
> On Friday, 1 February 2019 at 11:48:51 UTC, Timon Gehr wrote:
>> On 01.02.19 10:10, aliak wrote:
>>> [...]
>>
>> http://wilzbach.github.io/d-dip/DIP24
>>
>> I'm not sure your rewrite is good though, because it does not preserve aliasing during the function call.
> Not only that, but C# forbids you passing properties as an ref/out parameter.
> (The properties should be redefined as accessor, such that you can't take the address of it)
> -Alex

By properties I mean accessors? I don’t mean normal fieldsat least. Or does c# have a distinction between normal member variables, properties, and accessors?
February 01, 2019
On Friday, 1 February 2019 at 15:58:50 UTC, Aliak wrote:
> On Friday, 1 February 2019 at 14:41:52 UTC, 12345swordy wrote:
>> On Friday, 1 February 2019 at 11:48:51 UTC, Timon Gehr wrote:
>>> On 01.02.19 10:10, aliak wrote:
>>>> [...]
>>>
>>> http://wilzbach.github.io/d-dip/DIP24
>>>
>>> I'm not sure your rewrite is good though, because it does not preserve aliasing during the function call.
>> Not only that, but C# forbids you passing properties as an ref/out parameter.
>> (The properties should be redefined as accessor, such that you can't take the address of it)
>> -Alex
>
> By properties I mean accessors? I don’t mean normal fieldsat least. Or does c# have a distinction between normal member variables, properties, and accessors?

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
February 01, 2019
On Thursday, 31 January 2019 at 21:57:21 UTC, Steven Schveighoffer wrote:
> That being said, you can look at the fact that most people don't even know about this problem, even seasoned veterans, as a sign that it's really not a big problem.

Isn't it a recurring theme on this forum that D is really cool but also kind of obnoxious because of weird corner cases that veterans know, but aren't documented anywhere?
February 01, 2019
On Thursday, 31 January 2019 at 21:50:32 UTC, Steven Schveighoffer wrote:
> How is the problem not in doubleMyValue? It's sole purpose is to update an lvalue. It is the perfect candidate to mark with @disable for rvalues.

But right now, updating an rvalue is what ref is supposed to be used for.

Besides, the fact remains that accepting DIP 1016 would add a new corner case with the potential to create hard-to-detect bugs, which feels to me like it should be a dealbreaker. The fact that this corner case can be patched using @disable isn't good enough, because:
- Existing codebases that use ref won't have the @disable patch, which means using them will become (slightly) dangerous because of DIP 1016.
- Making libraries that behave predictably should be the default path (the "pit of success" philosophy), not require an additional construct.

Besides, D's type system should be more than capable of consistently telling the user "Be careful, you're modifying a temporary when it's probably not what you meant".

---

An alternate proposal that just came to mind: allowing the user to pass rvalues to ref arguments with the following syntax:

    y = doubleMyValue(cast(ref)10);

This syntax would avoid creating ambiguous situations where the compiler thinks you're passing it a getter's return as a temporary when you're trying to pass the attribute that the getter maps to. Eg, the following code:

    y = doubleMyValue(pt.x);

would still fail the same way it currently does when Point.x() is a getter.
February 01, 2019
On Friday, 1 February 2019 at 09:10:15 UTC, aliak wrote:
> Shouldn't doubleMyValue(pt.x) be a compiler error if pt.x is a getter? For it not to be a compile error pt.x should also have a setter, in which case the code needs to be lowered to something else:

The thing is, D doesn't really differentiate between a getter and any other method.

So with DIP-1016, when given

    doubleMyValue(pt.x);

The compiler would assume the programmer means
- Call pt.x()
- Store the result in a temporary
- Pass that temporary as a ref parameter to doubleMyValue

At no point is the compiler aware that the user intends for x to be interpreted as a getter.
February 02, 2019
On Friday, 1 February 2019 at 23:24:44 UTC, Olivier FAURE wrote:
> At no point is the compiler aware that the user intends for x to be interpreted as a getter.

In theory, at least, that's what @property is for.