Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-10 Thread Daniel N via Digitalmars-d-announce

On Saturday, 9 February 2019 at 01:31:05 UTC, H. S. Teoh wrote:


Using lowering to lambdas as a way of defining semantics is not 
the same thing as actually using lambdas to implement a feature 
in the compiler!


While it can be convenient to do the latter as a first stab, 
I'd expect that the optimizer could make use of special 
knowledge available in the compiler to implement this more 
efficiently. Since the compiler will always use a fixed pattern 
for the lowering, the backend could detect this pattern and 
optimize accordingly.  Or the compiler implementation could 
lower it directly to something more efficient in the first 
place.



T


The lambda even correctly handles "@disable this(this);", I like 
it!


struct One { @disable this(this); }
void fun(ref One one) { }

One gun() { return One.init; }

void main()
{
  One one; one.fun();
  (One __temp0){ return fun( __temp0 ); }(gun()); // OK
}



Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread H. S. Teoh via Digitalmars-d-announce
On Sat, Feb 09, 2019 at 01:08:55AM +, bitwise via Digitalmars-d-announce 
wrote:
> On Saturday, 9 February 2019 at 00:04:20 UTC, Dennis wrote:
> > On Friday, 8 February 2019 at 23:58:49 UTC, H. S. Teoh wrote:
> > > Yep, the moral of the story is, if codegen quality is important to
> > > you, use ldc (and presumably gdc too) rather than dmd.
> > 
> > That's definitely true, but that leaves the question whether
> > lowering rvalue references to lambdas is acceptable. There's the
> > 'dmd for fast builds, gdc/ldc for fast code' motto, but if your
> > debug builds of your game make it run at 15 fps it becomes unusable.
> > I don't want the gap between dmd and compilers with modern back-ends
> > to widen.
> 
> Since the user doesn't explicitly place the lambda in their code,
> wouldn't it be justifiable for the compiler to take it back out again
> at a later step in compilation, even in debug mode?

Using lowering to lambdas as a way of defining semantics is not the same
thing as actually using lambdas to implement a feature in the compiler!

While it can be convenient to do the latter as a first stab, I'd expect
that the optimizer could make use of special knowledge available in the
compiler to implement this more efficiently. Since the compiler will
always use a fixed pattern for the lowering, the backend could detect
this pattern and optimize accordingly.  Or the compiler implementation
could lower it directly to something more efficient in the first place.


T

-- 
If you look at a thing nine hundred and ninety-nine times, you are perfectly 
safe; if you look at it the thousandth time, you are in frightful danger of 
seeing it for the first time. -- G. K. Chesterton


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread bitwise via Digitalmars-d-announce

On Saturday, 9 February 2019 at 00:04:20 UTC, Dennis wrote:

On Friday, 8 February 2019 at 23:58:49 UTC, H. S. Teoh wrote:
Yep, the moral of the story is, if codegen quality is 
important to you, use ldc (and presumably gdc too) rather than 
dmd.


That's definitely true, but that leaves the question whether 
lowering rvalue references to lambdas is acceptable. There's 
the 'dmd for fast builds, gdc/ldc for fast code' motto, but if 
your debug builds of your game make it run at 15 fps it becomes 
unusable. I don't want the gap between dmd and compilers with 
modern back-ends to widen.


Since the user doesn't explicitly place the lambda in their code, 
wouldn't it be justifiable for the compiler to take it back out 
again at a later step in compilation, even in debug mode?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread H. S. Teoh via Digitalmars-d-announce
On Sat, Feb 09, 2019 at 12:04:20AM +, Dennis via Digitalmars-d-announce 
wrote:
> On Friday, 8 February 2019 at 23:58:49 UTC, H. S. Teoh wrote:
> > Yep, the moral of the story is, if codegen quality is important to
> > you, use ldc (and presumably gdc too) rather than dmd.
> 
> That's definitely true, but that leaves the question whether lowering
> rvalue references to lambdas is acceptable. There's the 'dmd for fast
> builds, gdc/ldc for fast code' motto, but if your debug builds of your
> game make it run at 15 fps it becomes unusable. I don't want the gap
> between dmd and compilers with modern back-ends to widen.

TBH, I've been finding that ldc compilation times aren't all that bad
compared to dmd.  It's definitely slightly slower, but it's not anywhere
near the gap between, say, dmd and g++.

Recently I've been quite tempted to replace dmd with ldc as my main D
compiler, esp. now that ldc releases are essentially on par with dmd
releases in terms of release schedule of a particular language version.
The slowdown in compilation times isn't enough to offset the benefits,
as long as you're not compiling with, say, -O3 which *would* make the
ldc optimizer run slower (but with the huge benefit of significantly
better codegen -- I've seen performance improvements of up to ~200% with
ldc -O3 vs. dmd -O -inline).

And template-heavy code is slow across all D compilers anyway, so the
relatively small compilation time difference between dmd and ldc doesn't
really matter that much anymore once you have a sufficiently large
codebase with heavy template use.


T

-- 
What doesn't kill me makes me stranger.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread Dennis via Digitalmars-d-announce

On Friday, 8 February 2019 at 23:58:49 UTC, H. S. Teoh wrote:
Yep, the moral of the story is, if codegen quality is important 
to you, use ldc (and presumably gdc too) rather than dmd.


That's definitely true, but that leaves the question whether 
lowering rvalue references to lambdas is acceptable. There's the 
'dmd for fast builds, gdc/ldc for fast code' motto, but if your 
debug builds of your game make it run at 15 fps it becomes 
unusable. I don't want the gap between dmd and compilers with 
modern back-ends to widen.




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread H. S. Teoh via Digitalmars-d-announce
On Fri, Feb 08, 2019 at 03:42:51PM -0800, H. S. Teoh via Digitalmars-d-announce 
wrote:
> On Fri, Feb 08, 2019 at 11:34:47PM +, Dennis via Digitalmars-d-announce 
> wrote:
> > On Friday, 8 February 2019 at 23:02:34 UTC, Nicholas Wilson wrote:
> > > Immediately called lamdas are always inlined.
> > 
> > ```
> > extern(C) void main() {
> > int a = (() => 1)();
> > }
> > ```
[...]
> Does LDC/GDC inline it?
> 
> I no longer trust dmd for codegen quality. :-/
[...]

Just checked: LDC does inline it.  In fact, LDC compiles the whole thing
out and just has `ret` for main(). :-D  Forcing LDC not to elide the
whole thing by inserting a writeln(a) call reveals that the lambda is
indeed inlined.

Yep, the moral of the story is, if codegen quality is important to you,
use ldc (and presumably gdc too) rather than dmd.


T

-- 
Freedom of speech: the whole world has no right *not* to hear my spouting off!


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread H. S. Teoh via Digitalmars-d-announce
On Fri, Feb 08, 2019 at 11:34:47PM +, Dennis via Digitalmars-d-announce 
wrote:
> On Friday, 8 February 2019 at 23:02:34 UTC, Nicholas Wilson wrote:
> > Immediately called lamdas are always inlined.
> 
> ```
> extern(C) void main() {
> int a = (() => 1)();
> }
> ```
> 
> dmd -inline -O -release -betterC
> 
> asm:
> ```
> main:
>   pushRBP
>   mov RBP,RSP
>   callqword ptr pure nothrow @nogc @safe int
> onlineapp.main().__lambda1()@GOTPCREL[RIP]
>   xor EAX,EAX
>   pop RBP
>   ret
> ```
> 
> https://run.dlang.io/is/lZW9B6
> 
> Still a lambda call :/

Does LDC/GDC inline it?

I no longer trust dmd for codegen quality. :-/


T

-- 
Customer support: the art of getting your clients to pay for your own 
incompetence.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread Dennis via Digitalmars-d-announce

On Friday, 8 February 2019 at 23:02:34 UTC, Nicholas Wilson wrote:

Immediately called lamdas are always inlined.


```
extern(C) void main() {
int a = (() => 1)();
}
```

dmd -inline -O -release -betterC

asm:
```
main:
pushRBP
mov RBP,RSP
		call	qword ptr pure nothrow @nogc @safe int 
onlineapp.main().__lambda1()@GOTPCREL[RIP]

xor EAX,EAX
pop RBP
ret
```

https://run.dlang.io/is/lZW9B6

Still a lambda call :/


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread Nicholas Wilson via Digitalmars-d-announce

On Friday, 8 February 2019 at 16:00:58 UTC, bitwise wrote:

On Monday, 4 February 2019 at 20:08:39 UTC, Paul Backus wrote:

On Monday, 4 February 2019 at 18:35:37 UTC, bitwise wrote:

[...]


It's actually fine to leave the `return` there 
unconditionally--you're allowed to return an expression of 
type `void` from a function.


Example: https://run.dlang.io/is/tnSGN4


Even better ;)

No one else seems particularly excited about the rewrite though 
- what am I missing?


I suppose a lambda cost significantly more, but I don't think 
the lambda should make it through the optimizer for this case 
though.


Immediately called lamdas are always inlined.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-08 Thread bitwise via Digitalmars-d-announce

On Monday, 4 February 2019 at 20:08:39 UTC, Paul Backus wrote:

On Monday, 4 February 2019 at 18:35:37 UTC, bitwise wrote:
On Monday, 4 February 2019 at 18:32:56 UTC, Dominikus Dittes 
Scherkl wrote:

I don't understand this.
What does "(return)?" mean? Is this valid D syntax? What do I 
miss?


I meant for that to be interpreted like a Regular expression, 
denoting conditional presence of the return statement. I'm not 
sure what the proper notation would be to express such a thing.


It's actually fine to leave the `return` there 
unconditionally--you're allowed to return an expression of type 
`void` from a function.


Example: https://run.dlang.io/is/tnSGN4


Even better ;)

No one else seems particularly excited about the rewrite though - 
what am I missing?


I suppose a lambda cost significantly more, but I don't think the 
lambda should make it through the optimizer for this case though.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-04 Thread Paul Backus via Digitalmars-d-announce

On Monday, 4 February 2019 at 18:35:37 UTC, bitwise wrote:
On Monday, 4 February 2019 at 18:32:56 UTC, Dominikus Dittes 
Scherkl wrote:

I don't understand this.
What does "(return)?" mean? Is this valid D syntax? What do I 
miss?


I meant for that to be interpreted like a Regular expression, 
denoting conditional presence of the return statement. I'm not 
sure what the proper notation would be to express such a thing.


It's actually fine to leave the `return` there 
unconditionally--you're allowed to return an expression of type 
`void` from a function.


Example: https://run.dlang.io/is/tnSGN4


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-04 Thread bitwise via Digitalmars-d-announce
On Monday, 4 February 2019 at 18:32:56 UTC, Dominikus Dittes 
Scherkl wrote:

I don't understand this.
What does "(return)?" mean? Is this valid D syntax? What do I 
miss?


I meant for that to be interpreted like a Regular expression, 
denoting conditional presence of the return statement. I'm not 
sure what the proper notation would be to express such a thing.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-04 Thread Dominikus Dittes Scherkl via Digitalmars-d-announce

On Monday, 4 February 2019 at 17:09:25 UTC, bitwise wrote:


I think this solves all of the above:

fun(10);
==>
(int __temp0){ (return)? fun( __temp0 ); }(10);

-The expression/statement issue is solved by the closure
-The initialization issue created by the ":=" approach is not 
present here
-For this rewrite, 'T' is the type of the rvalue argument, not 
the type of the function parameter. This prevents undesired 
implicit conversions.


I don't understand this.
What does "(return)?" mean? Is this valid D syntax? What do I 
miss?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-04 Thread bitwise via Digitalmars-d-announce

On Thursday, 24 January 2019 at 07:18:58 UTC, Mike Parker wrote:

Walter and Andrei have declined to accept DIP 1016, "ref T 
accepts r-values", on the grounds that it has two fundamental 
flaws that would open holes in the language.




fun(10)
==>
{
  T __temp0 = void;
  fun(__temp0 := 10);
}


the rewrite is from an expression to a statement, rendering it 
invalid.


if the first constructor throws an exception, all remaining 
values will be destroyed in the void state as they never have 
the chance to become initialized.


They say that with the current semantics, this function only 
operates on long values as it should. With the proposed 
semantics, the call will accept all shared integral types.


I think this solves all of the above:

fun(10);
==>
(int __temp0){ (return)? fun( __temp0 ); }(10);

-The expression/statement issue is solved by the closure
-The initialization issue created by the ":=" approach is not 
present here
-For this rewrite, 'T' is the type of the rvalue argument, not 
the type of the function parameter. This prevents undesired 
implicit conversions.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread 12345swordy via Digitalmars-d-announce

On Friday, 1 February 2019 at 23:24:44 UTC, Olivier FAURE wrote:

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.


Languages like c# solve this problem by disallowing passing 
property to ref parameter arguments.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Paul Backus via Digitalmars-d-announce

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.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Olivier FAURE via Digitalmars-d-announce

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.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Olivier FAURE via Digitalmars-d-announce
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.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Olivier FAURE via Digitalmars-d-announce
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?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread 12345swordy via Digitalmars-d-announce

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


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Aliak via Digitalmars-d-announce

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?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread 12345swordy via Digitalmars-d-announce

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


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread aliak via Digitalmars-d-announce

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?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread Timon Gehr via Digitalmars-d-announce

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.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-02-01 Thread aliak via Digitalmars-d-announce
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
}





Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread jmh530 via Digitalmars-d-announce

On Thursday, 31 January 2019 at 22:35:26 UTC, H. S. Teoh wrote:
On Thu, Jan 31, 2019 at 10:26:39PM +, jmh530 via 
Digitalmars-d-announce wrote:
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.
> 


The way you put it makes it sound like a bug...

I don't know if it helps, but below compiles without error.

struct Foo
{
   private int _x;
   int* x() { return &_x; }
}

struct Bar
{
   private Foo _y;
   Foo* y() { return &_y; }
   void y(Foo foo) { _y = foo; }
}

void main() {
Foo a = Foo(1);
assert(*a.x == 1);
*a.x *= 2;
assert(*a.x == 2);

Bar b;
b.y = Foo(1);
assert(*b.y.x == 1);
*b.y.x *= 2;
assert(*b.y.x == 2);
}


Why is it a problem that this code compiles without error?


T


Sorry if I didn't really complete my thought.

The code below corresponds to the ref version mentioned above and 
gets the same error originally reported. The only difference is 
that I use Foo instead of Foo* for the getter in Bar. So if you 
instead make that member function a ref function, then it also 
compiles without error (regardless of if you use the 
doubleMyValue function or not).


So they were right that the issue is with the getter. However, 
you're not really protected in any way if you have a ref getter 
at one point in a chain and a non-ref getter somewhere else. 
Making all the getters auto ref also avoids the issue.


struct Foo
{
   private int _x;
   ref int x() { return _x; }
}

struct Bar
{
   private Foo _y;
   Foo y() { return _y; }
   void y(Foo foo) { _y = foo; }
}

void main() {
Foo a = Foo(1);
assert(a.x == 1);
a.x *= 2;
assert(a.x == 2);

Bar b;
b.y = Foo(1);
assert(b.y.x == 1);
b.y.x *= 2;
assert(b.y.x == 2);
}


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Rubn via Digitalmars-d-announce

On Thursday, 31 January 2019 at 22:00:10 UTC, Walter Bright wrote:

On 1/31/2019 1:46 PM, Andrei Alexandrescu wrote:
The proposal could actually disallow rvalues that have lvalue 
syntax, such as "symbol", "symbol[expr]", "symbol.symbol", 
"symbol.symbol[expr]", etc. Ugh. Gets hairy quickly.


That's why it's problematic to have a rule that rvalues can be 
implicitly converted, but not lvalues. There's not a hard line 
between lvalues and rvalues. For example,


  foreach(i; 0..2)
  {
int[] a = [1, 2];
assert(a[0] == 1]);
a[0] = 3;  // will this cause the assert to fail?
  }


Why would it cause the assert to fail? A new array is constructed 
each loop.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread H. S. Teoh via Digitalmars-d-announce
On Thu, Jan 31, 2019 at 10:26:39PM +, jmh530 via Digitalmars-d-announce 
wrote:
> 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.
> > 
> 
> The way you put it makes it sound like a bug...
> 
> I don't know if it helps, but below compiles without error.
> 
> struct Foo
> {
>private int _x;
>int* x() { return &_x; }
> }
> 
> struct Bar
> {
>private Foo _y;
>Foo* y() { return &_y; }
>void y(Foo foo) { _y = foo; }
> }
> 
> void main() {
> Foo a = Foo(1);
> assert(*a.x == 1);
> *a.x *= 2;
> assert(*a.x == 2);
> 
> Bar b;
> b.y = Foo(1);
> assert(*b.y.x == 1);
> *b.y.x *= 2;
> assert(*b.y.x == 2);
> }

Why is it a problem that this code compiles without error?


T

-- 
Perhaps the most widespread illusion is that if we were in power we would 
behave very differently from those who now hold it---when, in truth, in order 
to get power we would have to become very much like them. -- Unknown


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread jmh530 via Digitalmars-d-announce
On Thursday, 31 January 2019 at 21:57:21 UTC, Steven 
Schveighoffer wrote:

[snip]

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.




The way you put it makes it sound like a bug...

I don't know if it helps, but below compiles without error.

struct Foo
{
   private int _x;
   int* x() { return &_x; }
}

struct Bar
{
   private Foo _y;
   Foo* y() { return &_y; }
   void y(Foo foo) { _y = foo; }
}

void main() {
Foo a = Foo(1);
assert(*a.x == 1);
*a.x *= 2;
assert(*a.x == 2);

Bar b;
b.y = Foo(1);
assert(*b.y.x == 1);
*b.y.x *= 2;
assert(*b.y.x == 2);
}


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread jmh530 via Digitalmars-d-announce

On Thursday, 31 January 2019 at 21:50:19 UTC, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 21:44:53 UTC, jmh530 wrote:
It doesn't compile with dip1000 without first giving the 
getter functions a return attribute for this.


But it still compiles with -dip1000 once you give x() and y() 
return attributes, even though what's happening is clearly 
different from what the user wants (and the compiler has enough 
info to know that).


Agreed. I had checked that it didn't work and as I figured out 
how to get it work I got distracted reading the documentation and 
return and scope.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 4:46 PM, Andrei Alexandrescu wrote:

On 1/31/19 4:42 PM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 16:38:42 UTC, Steven Schveighoffer wrote:

Yeah, that's already a thing that ref in D doesn't protect against:


It took me a while to understand what the compiler was doing.

This really feels like something that shouldn't compile.


The proposal could actually disallow rvalues that have lvalue syntax, 
such as "symbol", "symbol[expr]", "symbol.symbol", 
"symbol.symbol[expr]", etc. Ugh. Gets hairy quickly.


No, because those calls might actually do something with side effects! 
rvalues can contain other references.


The only way to fix this would be to overload member functions on the 
lvalue-ness of `this`. I don't recommend this at all, as I see this as a 
weird but rare problem that doesn't affect most D code.


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Walter Bright via Digitalmars-d-announce

On 1/31/2019 1:46 PM, Andrei Alexandrescu wrote:
The proposal could actually disallow rvalues that have lvalue syntax, such as 
"symbol", "symbol[expr]", "symbol.symbol", "symbol.symbol[expr]", etc. Ugh. Gets 
hairy quickly.


That's why it's problematic to have a rule that rvalues can be implicitly 
converted, but not lvalues. There's not a hard line between lvalues and rvalues. 
For example,


  foreach(i; 0..2)
  {
int[] a = [1, 2];
assert(a[0] == 1]);
a[0] = 3;  // will this cause the assert to fail?
  }


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 4:42 PM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 16:38:42 UTC, Steven Schveighoffer wrote:

Yeah, that's already a thing that ref in D doesn't protect against:


It took me a while to understand what the compiler was doing.

This really feels like something that shouldn't compile.


The problem is that `this` is passed by reference EVEN for rvalues. 
Knowing this, you can construct difficult situations, but normally these 
don't appear in the wild.


If you've ever tried to make a simple math wrapper type, you would see 
how this is weird. And it has been like this since the beginning of D2.


You get things like:

a + Foo(1); // error
Foo(1) + a; // OK!

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.


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Olivier FAURE via Digitalmars-d-announce

On Thursday, 31 January 2019 at 21:44:53 UTC, jmh530 wrote:
It doesn't compile with dip1000 without first giving the getter 
functions a return attribute for this.


But it still compiles with -dip1000 once you give x() and y() 
return attributes, even though what's happening is clearly 
different from what the user wants (and the compiler has enough 
info to know that).


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

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


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/31/19 4:42 PM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 16:38:42 UTC, Steven Schveighoffer wrote:

Yeah, that's already a thing that ref in D doesn't protect against:


It took me a while to understand what the compiler was doing.

This really feels like something that shouldn't compile.


The proposal could actually disallow rvalues that have lvalue syntax, 
such as "symbol", "symbol[expr]", "symbol.symbol", 
"symbol.symbol[expr]", etc. Ugh. Gets hairy quickly.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Olivier FAURE via Digitalmars-d-announce
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);

-Steve


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.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Olivier FAURE via Digitalmars-d-announce
On Thursday, 31 January 2019 at 16:38:42 UTC, Steven 
Schveighoffer wrote:
Yeah, that's already a thing that ref in D doesn't protect 
against:


It took me a while to understand what the compiler was doing.

This really feels like something that shouldn't compile.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread jmh530 via Digitalmars-d-announce

On Thursday, 31 January 2019 at 21:42:04 UTC, Olivier FAURE wrote:

[snip]

It took me a while to understand what the compiler was doing.

This really feels like something that shouldn't compile.


It doesn't compile with dip1000 without first giving the getter 
functions a return attribute for this.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/31/19 11:38 AM, Steven Schveighoffer wrote:

On 1/31/19 11:04 AM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

I still can't see a truck-sized hole.


I don't know if it's truck-sized, but here's another corner case:

 int doubleMyValue(ref int x) {
 x *= 2;
 return x;
 }

 Point pt;
 pt.x = 5;
 pt.y = foobar();

 doubleMyValue(pt.x);
 assert(pt.x == 10);

Question: in the above code, will the assertion pass?

Answer: it depends on Point's implementation. If x is a member 
variable, then yes. If it's a getter, then doubleMyValue will take a 
rvalue and x won't be mutated and the assertion will fail.


I think this is a non-trivial conceptual problem.


Yeah, that's already a thing that ref in D doesn't protect against:

struct Point
{
    private int _x, _y;
    ref int x() { return _x; }
    ref int y() { return _y; }
}

struct Rect
{
    private Point _origin, _lengths;
    Point origin() { return _origin; }
    Point lengths() { return _lengths; }
    void origin(Point p) { _origin = p; }
    void lengths(Point p) { _lengths = p; }
}

Rect r;
r.origin = Point(1, 2);
r.lengths = Point(5, 5);
doubleMyValue(r.lengths.x);
assert(r.lengths.x == 10); // fail

-Steve


Affirmative. This discussion should be part of the revised DIP along 
with an assessment of its gravity.


Goes the same with scope-level variables replaced with homonym functions 
that return rvalues.



Andrei


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 11:04 AM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

I still can't see a truck-sized hole.


I don't know if it's truck-sized, but here's another corner case:

     int doubleMyValue(ref int x) {
     x *= 2;
     return x;
     }

     Point pt;
     pt.x = 5;
     pt.y = foobar();

     doubleMyValue(pt.x);
     assert(pt.x == 10);

Question: in the above code, will the assertion pass?

Answer: it depends on Point's implementation. If x is a member variable, 
then yes. If it's a getter, then doubleMyValue will take a rvalue and x 
won't be mutated and the assertion will fail.


I think this is a non-trivial conceptual problem.


BTW, the DIP discusses how to annotate these rare situations:

int doubleMyValue(ref int x) { ... }
@disable int doubleMyValue(int x);

-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 11:04 AM, Olivier FAURE wrote:

On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

I still can't see a truck-sized hole.


I don't know if it's truck-sized, but here's another corner case:

     int doubleMyValue(ref int x) {
     x *= 2;
     return x;
     }

     Point pt;
     pt.x = 5;
     pt.y = foobar();

     doubleMyValue(pt.x);
     assert(pt.x == 10);

Question: in the above code, will the assertion pass?

Answer: it depends on Point's implementation. If x is a member variable, 
then yes. If it's a getter, then doubleMyValue will take a rvalue and x 
won't be mutated and the assertion will fail.


I think this is a non-trivial conceptual problem.


Yeah, that's already a thing that ref in D doesn't protect against:

struct Point
{
   private int _x, _y;
   ref int x() { return _x; }
   ref int y() { return _y; }
}

struct Rect
{
   private Point _origin, _lengths;
   Point origin() { return _origin; }
   Point lengths() { return _lengths; }
   void origin(Point p) { _origin = p; }
   void lengths(Point p) { _lengths = p; }
}

Rect r;
r.origin = Point(1, 2);
r.lengths = Point(5, 5);
doubleMyValue(r.lengths.x);
assert(r.lengths.x == 10); // fail

-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Olivier FAURE via Digitalmars-d-announce

On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

I still can't see a truck-sized hole.


I don't know if it's truck-sized, but here's another corner case:

int doubleMyValue(ref int x) {
x *= 2;
return x;
}

Point pt;
pt.x = 5;
pt.y = foobar();

doubleMyValue(pt.x);
assert(pt.x == 10);

Question: in the above code, will the assertion pass?

Answer: it depends on Point's implementation. If x is a member 
variable, then yes. If it's a getter, then doubleMyValue will 
take a rvalue and x won't be mutated and the assertion will fail.


I think this is a non-trivial conceptual problem.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 3:25 AM, Walter Bright wrote:
But the DIP says const ref is not required. Therefore, copying an lvalue 
to a temporary cannot be allowed, therefore implicit conversion of 
lvalues cannot happen.


The biggest reason I see to not worry about const is that we already 
don't for member functions. And the world hasn't ended (yet).




Then we're faced with the question of if implicit conversion of lvalues 
is not allowed, should implicit conversion of rvalues be allowed? I'm 
not so sure it should be. For one thing, a lot of people are confused 
about lvalues vs rvalues, and would find the difference in behavior 
puzzling. For another, it can complicate overloading rules. I'd say 
allowing the conversions needs a strong rationale.


We could certainly start out with no conversions allowed (except you 
MUST allow conversions of compile-time data -- e.g. literals and CTFE 
produced values -- that is very key), and then relax the rules later if 
that's important.


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/31/19 2:26 AM, Andrei Alexandrescu wrote:

The trouble is major.

Replace "if" with "while":

while (ref_fun(10)) { ... }
==>
{
   int __tmp = 10;
   while (ref_fun(__tmp)) { ... }
}

That means ref_fun is called with the same lvalue multiple times. In all 
likelihood this is not what you want!


Yes, the trouble specifically is loops. Because loops execute their 
internal expressions over and over again.


Unfortunately, this means lowering isn't possible. That is, lowering to 
something expressible in the normal language isn't possible.


However, we all know that loops are essentially "lowered" in the AST to 
simple ifs and gotos. We just need to operate at that level.


So for instance the above looks something like this in AST:

loop_continue:
if(ref_fun(10))
{
  ...
}
else
   goto loop_end;
goto loop_continue;
loop_end:

(I know I'm omitting a lot of extra stuff like scope cleanup, that is 
implied here, as I don't know the exact details).


What needs to happen is the temporary (with extra scope)is inserted 
between the loop start and the if statement:


loop_continue:
{
   int __tmp = 10;
   if(ref_fun(__tmp))
   {
  ...
   }
   else
  goto loop_end;
}
goto loop_continue;
loop_end:

A possible retort is: "Of course, while would not be lowered that way, 
but a slightly different way!" etc. The point is, ALL OF THAT must be in 
the DIP, not assumed obvious or clarified in informal discusson outside 
the DIP.


Again: please be thorough, state your assumptions, cover all cases.


Agree, this needs to handle all possible cases. Really I think loops are 
the only problems, foreach, for, and while/do..while


A possible way forward is inventing a new syntax to allow declarations 
in this space, and then lowering can happen. Something similar to 
if(auto x = ...)


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-31 Thread Walter Bright via Digitalmars-d-announce

On 1/30/2019 5:55 PM, Manu wrote:

lets replace 10 with a short variable named: S

"a short variable named: S" is an lvalue, so why would the rewrite be
attempted? S must be an rvalue for any rewrite to occur. We're talking
about rvalues here.


This illustrates why this should be compared with C++. Consider this C++ code:

  const int& foo(const int& x) { return x; }

  const int& test() {
short s;
return foo(s);
  }

It compiles with clang++. The code generated for test() is:

pushRBP
mov RBP,RSP
sub RSP,010h
lea RDI,-8[RBP]
movsx   EAX,word ptr -2[RBP]
mov -8[RBP],EAX
callfoo
add RSP,010h
pop RBP
ret

See what it is doing? It's converting s to an int, putting the int into a 
temporary, then passing a reference to that temporary to foo(). So when you ask 
why would a person think that this would happen with the DIP, if they know C++, 
they would assume similar behavior. This is why the DIP needs to specifically 
say this is not the proposed behavior. It is why a comparison to C++ behavior is 
essential. It is a lot easier to understand the DIP if people can apply their 
existing understanding, with a few modifications, to the D behavior. It's also 
necessary to compare with C++ to see if the DIP missed something important, and 
to justify any other behavioral differences.


The interesting question is, since C++ supports this behavior, what about the 
truck-sized hole? The answer is in the declaration of foo(const int&). The const 
is the reason. The referenced value cannot be modified. The realloc example is 
blocked by the compiler.


But the DIP says const ref is not required. Therefore, copying an lvalue to a 
temporary cannot be allowed, therefore implicit conversion of lvalues cannot happen.


Then we're faced with the question of if implicit conversion of lvalues is not 
allowed, should implicit conversion of rvalues be allowed? I'm not so sure it 
should be. For one thing, a lot of people are confused about lvalues vs rvalues, 
and would find the difference in behavior puzzling. For another, it can 
complicate overloading rules. I'd say allowing the conversions needs a strong 
rationale.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/30/19 10:12 PM, Manu wrote:

On Wed, Jan 30, 2019 at 7:05 PM Nicholas Wilson via
Digitalmars-d-announce  wrote:


On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

On Wed, Jan 30, 2019 at 1:05 PM Andrei Alexandrescu via

fun(my_short); // implicit type conversions (ie, short->int
promotion)



Oh I see.


fun(short(10)); // implicit type conversions (ie, short->int
promotion)


I did not intend for this DIP to apply to anything other than
rvalues.
I can totally see how that's not clear. `my_short` should be an
rvalue
of some form, like the rest.
Is that the only such line?


I think so.


Presumably my_short is a variable of type short. Is that
correct?


It is not. It should be an rvalue like everything else. Perhaps
it's an enum... but I should write `short(10)`, that would be
clear.


It would.


* DIP 1016 proposes a hole in the language one could drive a
truck through.


I still can't see a truck-sized hole.


* The problem goes undetected in community review.


I don't know how I could have influenced this outcome.


* Its own author seems to not have an understanding of what
the DIP proposes.


More classy comments. I can't get enough of the way you
belittle people.

I made a 1-word error, where I should have written `short(10)`
to be clear.
1-word error feels amendment-worthy, and not a call for "let's
start
over from scratch".


You should just PR it back to review


I can't do that, it's been rejected, with mostly incorrect rejection
text affixed to the bottom.


with that fix and a note
about how it lowers to statements (incl. an example of
lambdification for if/while/for/switch statements (see
https://forum.dlang.org/post/qysmnatmjquuhylaq...@forum.dlang.org
))


I'm pretty sure that's not necessary. I haven't understood why this
noise about expressions. This DIP applies to statements.
I can't see how there's any problem with the lowering if the statement
is a control statement?

if (ref_fun(10)) { ... }
==>
{
   int __tmp = 10;
   if (ref_fun(__tmp)) { ... }
}

What's the trouble?


The trouble is major.

Replace "if" with "while":

while (ref_fun(10)) { ... }
==>
{
  int __tmp = 10;
  while (ref_fun(__tmp)) { ... }
}

That means ref_fun is called with the same lvalue multiple times. In all 
likelihood this is not what you want!


A possible retort is: "Of course, while would not be lowered that way, 
but a slightly different way!" etc. The point is, ALL OF THAT must be in 
the DIP, not assumed obvious or clarified in informal discusson outside 
the DIP.


Again: please be thorough, state your assumptions, cover all cases.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/30/19 10:05 PM, Manu wrote:

On Wed, Jan 30, 2019 at 6:40 PM Nicholas Wilson via
Digitalmars-d-announce  wrote:


On Wednesday, 30 January 2019 at 18:29:37 UTC, Manu wrote:

On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via
Digitalmars-d-announce 
wrote:

The result of a CastExpression is an rvalue. An implicit cast
is a compiler-inserted CastExpression. Therefore all lvalues
with a potential implicit cast are rvalues.


But there's no existing language rule that attempts to perform
an implicit cast where an lvalue is supplied to a ref arg...?
Why is the cast being attempted? 'p' is an lvalue, and whatever
that does should remain exactly as is (ie, emits a compile
error).

We could perhaps allow this for `const` args, but that feels
like separate follow-up work to me, and substantially lesser
value. This DIP doesn't want to change anything about lvalues.


It appears to say it does:

fun(my_short); // implicit type conversions (ie, short->int
promotion)

You should clarify that ;)


Yes, as said above, read `short(10)`. I can understand the confusion
that it may look like a variable when taken out of context; but listed
beneath the heading immediately above which says:
"This inconvenience extends broadly to every manner of **rvalue**
passed to functions"
It didn't occur to me the reader might interpret the clearly stated
list of cases of rvalues passed to functions to include arguments that
are not rvalues.
The name was just chosen to indicate the argument is a short, perhaps
an enum, or any expression that is a short... I could have used
`short(10)`, but apparently I didn't think of it at the time.

Is this the basis for the claims of "a hole you could drive a truck
through"?


Affirmative.

With the restriction that the expression passed into the function must 
be an rvalue to start with, by Walter's and my understanding, the 
proposed semantics would work and be helpful.



Again, a request for clarification, and a
couldn't-possibly-be-more-trivial revision may resolve this.


Negative.

It must be clear that the reason of this misunderstanding is squarely 
due to the DIP itself. It has multiple problems of informality and vague 
language that have worked together to cause said misunderstanding. (It 
is great it's just that, a misunderstanding; I have been worried people 
would believe such an awful semantics was considered just fine. That 
explains but does not justify my use of unkind language.)


The DIP must convince the reader, and in a way the reader does not "owe" 
the DIP. For good reason, they call the research theme chosen by a 
doctoral candidate a "charge"; the root of "dissertation" is Latin for 
"debate"; and the final doctoral examination is plainly called a 
"defense". The whole thing is structured like a criminal investigation 
:o). Of course we don't want to be as harsh as academics could get, but 
we don't want to transform DIP acceptance into a farmers market 
bargaining process.


So the code with my_short was open to interpretation. Cool. In a 
thorough submission, however, there would have been many places that 
clear that up:


* Use of a distinct notation (non-code non-text font for metalanguage, 
i.e. general expressions);


* Description of the typechecking process, with examples of code that 
passes and code that fails;


* A clarification that lowering proceeds not against all expressions, 
but only against rvalues;


* Several places in text in which it is explained that rvalues resulted 
from implicit conversions are not eligible;


* etc. etc. etc.

So if we rejected the DIP, we didn't do so on account of one word that 
can be so easily changed; we did so on account of a DIP that as a whole 
failed to clarify what it purports to do (and equally importantly, to 
not do).


The purpose of us all is to move things forward, and in that spirit 
allow me to put forward a short list of matters that a revised proposal 
should do, at a minimum:


* Walter has posted about a few issues with various parts of the 
proposal. Those should be addressed.


* The "Reference" section does good to mention the issues, but the 
litany of forum discussions has no value besides "there have been 
repeated discussion in community forums of the topic", and refer to a 
list in an bibliography. Placing them in the "Reference" section 
suggests the reader that they need to read the forum debates in order to 
understand the DIP, which isn't and shouldn't be the case.


* An "Existing Work" section discussing C++ (and possibly Rust) is a 
must. Studious neglect of what other languages do and what problems they 
have does not serve us well. I think Walter could help with that.


* The "Rationale" section currently focuses only on issues caused by the 
current rule. It should have three parts:


- Open with a brief description of the current rule and why it is that 
way. Here we have the advantage that confusing conversions are disallowed.
- Then continue with "However, the binding rule also 

Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/30/19 9:10 PM, Manu wrote:

* Its own author seems to not have an understanding of what the DIP
proposes.


More classy comments. I can't get enough of the way you belittle people.


You're right. I have deleted this post a few seconds after having sent 
it on account of that remark, but somehow it got resuscitated. Please 
accept my apologies.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Wed, Jan 30, 2019 at 7:35 PM Steven Schveighoffer via
Digitalmars-d-announce  wrote:
>
> On 1/30/19 10:05 PM, Manu wrote:
> > On Wed, Jan 30, 2019 at 6:40 PM Nicholas Wilson via
> > Digitalmars-d-announce  wrote:
> >> You should clarify that ;)
> >
> > Yes, as said above, read `short(10)`. I can understand the confusion
> > that it may look like a variable when taken out of context; but listed
> > beneath the heading immediately above which says:
> > "This inconvenience extends broadly to every manner of **rvalue**
> > passed to functions"
> > It didn't occur to me the reader might interpret the clearly stated
> > list of cases of rvalues passed to functions to include arguments that
> > are not rvalues.
> > The name was just chosen to indicate the argument is a short, perhaps
> > an enum, or any expression that is a short... I could have used
> > `short(10)`, but apparently I didn't think of it at the time.
> >
> > Is this the basis for the claims of "a hole you could drive a truck
> > through"? Again, a request for clarification, and a
> > couldn't-possibly-be-more-trivial revision may resolve this.
> >
>
> I think changing it to `short(10)` helps the argument that you didn't
> intend it to mean conversions from lvalues, but I'd recommend still
> spelling out that they are forbidden.

I mean, the heading of the DIP is "ref T accepts r-values", the whole
abstract talks about nothing but rvalues, the header of the confusing
block couldn't say 'rvalues' more clearly... I didn't consider that it
was possible to confuse this as anything other than an rvalue DIP...
but yes, I can certainly spell it out.

> Leaving the reader to infer intent is not as good as clarifying intent
> directly. The whole rvalue vs. lvalue thing is confusing to me, because
> I assumed an lvalue converted to a different type changes it to an
> rvalue. I think of it like an implicit function that returns that new value.

Obviously all of this is true, but I didn't think of it that way;
didn't realise there was a point of confusion, and nobody during the
community reviews appeared to raise confusion either.
I'll obviously revise it, except that it's rejected and moved to the
rejected folder.

For reference, the key point that justifies its mention in the first
place is a little further down:
"It is important that T be defined as the parameter type, and not auto
(ie, the argument type), because it will allow implicit conversions to
occur naturally, with identical behavior as when the parameter is not
ref."
It was important to consider mis-matching types (implicit
conversions), because there is detail in the rules that allows them to
work properly and make the call uniform with the same function if it
passed by-val.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/30/19 10:05 PM, Manu wrote:

On Wed, Jan 30, 2019 at 6:40 PM Nicholas Wilson via
Digitalmars-d-announce  wrote:

You should clarify that ;)


Yes, as said above, read `short(10)`. I can understand the confusion
that it may look like a variable when taken out of context; but listed
beneath the heading immediately above which says:
"This inconvenience extends broadly to every manner of **rvalue**
passed to functions"
It didn't occur to me the reader might interpret the clearly stated
list of cases of rvalues passed to functions to include arguments that
are not rvalues.
The name was just chosen to indicate the argument is a short, perhaps
an enum, or any expression that is a short... I could have used
`short(10)`, but apparently I didn't think of it at the time.

Is this the basis for the claims of "a hole you could drive a truck
through"? Again, a request for clarification, and a
couldn't-possibly-be-more-trivial revision may resolve this.



I think changing it to `short(10)` helps the argument that you didn't 
intend it to mean conversions from lvalues, but I'd recommend still 
spelling out that they are forbidden.


Leaving the reader to infer intent is not as good as clarifying intent 
directly. The whole rvalue vs. lvalue thing is confusing to me, because 
I assumed an lvalue converted to a different type changes it to an 
rvalue. I think of it like an implicit function that returns that new value.


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Wed, Jan 30, 2019 at 7:05 PM Nicholas Wilson via
Digitalmars-d-announce  wrote:
>
> On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:
> > On Wed, Jan 30, 2019 at 1:05 PM Andrei Alexandrescu via
> >> fun(my_short); // implicit type conversions (ie, short->int
> >> promotion)
> >> 
> >
> > Oh I see.
> >
> >> fun(short(10)); // implicit type conversions (ie, short->int
> >> promotion)
> >
> > I did not intend for this DIP to apply to anything other than
> > rvalues.
> > I can totally see how that's not clear. `my_short` should be an
> > rvalue
> > of some form, like the rest.
> > Is that the only such line?
>
> I think so.
>
> >> Presumably my_short is a variable of type short. Is that
> >> correct?
> >
> > It is not. It should be an rvalue like everything else. Perhaps
> > it's an enum... but I should write `short(10)`, that would be
> > clear.
>
> It would.
>
> >> * DIP 1016 proposes a hole in the language one could drive a
> >> truck through.
> >
> > I still can't see a truck-sized hole.
> >
> >> * The problem goes undetected in community review.
> >
> > I don't know how I could have influenced this outcome.
> >
> >> * Its own author seems to not have an understanding of what
> >> the DIP proposes.
> >
> > More classy comments. I can't get enough of the way you
> > belittle people.
> >
> > I made a 1-word error, where I should have written `short(10)`
> > to be clear.
> > 1-word error feels amendment-worthy, and not a call for "let's
> > start
> > over from scratch".
>
> You should just PR it back to review

I can't do that, it's been rejected, with mostly incorrect rejection
text affixed to the bottom.

> with that fix and a note
> about how it lowers to statements (incl. an example of
> lambdification for if/while/for/switch statements (see
> https://forum.dlang.org/post/qysmnatmjquuhylaq...@forum.dlang.org
> ))

I'm pretty sure that's not necessary. I haven't understood why this
noise about expressions. This DIP applies to statements.
I can't see how there's any problem with the lowering if the statement
is a control statement?

if (ref_fun(10)) { ... }
==>
{
  int __tmp = 10;
  if (ref_fun(__tmp)) { ... }
}

What's the trouble?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Wed, Jan 30, 2019 at 6:40 PM Nicholas Wilson via
Digitalmars-d-announce  wrote:
>
> On Wednesday, 30 January 2019 at 18:29:37 UTC, Manu wrote:
> > On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via
> > Digitalmars-d-announce 
> > wrote:
> >> The result of a CastExpression is an rvalue. An implicit cast
> >> is a compiler-inserted CastExpression. Therefore all lvalues
> >> with a potential implicit cast are rvalues.
> >
> > But there's no existing language rule that attempts to perform
> > an implicit cast where an lvalue is supplied to a ref arg...?
> > Why is the cast being attempted? 'p' is an lvalue, and whatever
> > that does should remain exactly as is (ie, emits a compile
> > error).
> >
> > We could perhaps allow this for `const` args, but that feels
> > like separate follow-up work to me, and substantially lesser
> > value. This DIP doesn't want to change anything about lvalues.
>
> It appears to say it does:
>
> fun(my_short); // implicit type conversions (ie, short->int
> promotion)
>
> You should clarify that ;)

Yes, as said above, read `short(10)`. I can understand the confusion
that it may look like a variable when taken out of context; but listed
beneath the heading immediately above which says:
"This inconvenience extends broadly to every manner of **rvalue**
passed to functions"
It didn't occur to me the reader might interpret the clearly stated
list of cases of rvalues passed to functions to include arguments that
are not rvalues.
The name was just chosen to indicate the argument is a short, perhaps
an enum, or any expression that is a short... I could have used
`short(10)`, but apparently I didn't think of it at the time.

Is this the basis for the claims of "a hole you could drive a truck
through"? Again, a request for clarification, and a
couldn't-possibly-be-more-trivial revision may resolve this.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Nicholas Wilson via Digitalmars-d-announce

On Thursday, 31 January 2019 at 02:10:05 UTC, Manu wrote:

On Wed, Jan 30, 2019 at 1:05 PM Andrei Alexandrescu via
fun(my_short); // implicit type conversions (ie, short->int 
promotion)




Oh I see.

fun(short(10)); // implicit type conversions (ie, short->int 
promotion)


I did not intend for this DIP to apply to anything other than 
rvalues.
I can totally see how that's not clear. `my_short` should be an 
rvalue

of some form, like the rest.
Is that the only such line?


I think so.

Presumably my_short is a variable of type short. Is that 
correct?


It is not. It should be an rvalue like everything else. Perhaps 
it's an enum... but I should write `short(10)`, that would be 
clear.


It would.

* DIP 1016 proposes a hole in the language one could drive a 
truck through.


I still can't see a truck-sized hole.


* The problem goes undetected in community review.


I don't know how I could have influenced this outcome.

* Its own author seems to not have an understanding of what 
the DIP proposes.


More classy comments. I can't get enough of the way you 
belittle people.


I made a 1-word error, where I should have written `short(10)` 
to be clear.
1-word error feels amendment-worthy, and not a call for "let's 
start

over from scratch".


You should just PR it back to review with that fix and a note 
about how it lowers to statements (incl. an example of 
lambdification for if/while/for/switch statements (see 
https://forum.dlang.org/post/qysmnatmjquuhylaq...@forum.dlang.org 
))


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Wed, Jan 30, 2019 at 12:40 PM 12345swordy via
Digitalmars-d-announce  wrote:
>
> On Wednesday, 30 January 2019 at 18:29:37 UTC, Manu wrote:
> > On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via
> > Digitalmars-d-announce 
> > wrote:
> >>
> >> On Wed, 30 Jan 2019 09:15:36 -0800, Manu wrote:
> >> > Why are you so stuck on this case? The DIP is about
> >> > accepting rvalues,
> >> > not lvalues...
> >> > Calling with 'p', an lvalue, is not subject to this DIP.
> >>
> >> The result of a CastExpression is an rvalue. An implicit cast
> >> is a compiler-inserted CastExpression. Therefore all lvalues
> >> with a potential implicit cast are rvalues.
> >
> > But there's no existing language rule that attempts to perform
> > an
> > implicit cast where an lvalue is supplied to a ref arg...?
> > Why is the cast being attempted?
> Because of the rewrite that your proposed in your dip.
>
> void fun(ref int x);
>
> fun(10);
>
> {
>T __temp0 = void;
>fun(__temp0 := 10);
> }
>
> lets replace 10 with a short variable named: S

"a short variable named: S" is an lvalue, so why would the rewrite be
attempted? S must be an rvalue for any rewrite to occur. We're talking
about rvalues here.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread kinke via Digitalmars-d-announce
On Monday, 28 January 2019 at 19:58:24 UTC, Andrei Alexandrescu 
wrote:

On 1/28/19 1:00 PM, Andrei Alexandrescu wrote:
It seems to me that a proposal adding the "@rvalue" attribute 
in function signatures to each parameter that would accept 
either an rvalue or an lvalue would be easy to argue.


- No exposing existing APIs to wrong uses
- The function's writer makes the decision ("I'm fine with 
this function taking an rvalue")

- Appears in the function's documentation
- Syntax is light and localized where it belongs
- Scales well with number of parameters
- Transparent to callers


The inverse, the @norval attribute, would feature all but the 
first advantages, at least once people get used to normal ref 
allowing (some) rvalues too. I can't think of many good reasons 
for a callee to disallow rvalues (with matching type at least); 
your example wrt. interlockedIncrement() is a good one, as 
synchronization overhead clearly isn't required for an rvalue. 
But my usages of (mutable) ref are >99% of the time something 
like:


Header readHeader(ref Stream stream)
{
// read from & advance stream, return parsed header
}

where I'd like to be able put everything into one line if trivial 
(stream not required later on):


readHeader(Stream("file")).doSomething();

(And const ref is mostly used for performance with bigger 
structs, where rvalues are absolutely fine).


TLDR: I'd guess that I'd need to type `@rvalue` about 1000 times 
as often as `@norval`. I'm not kidding.


TL;DR: it could be argued that the only dangerous conversions 
are lvalue -> temp rvalue -> ref, so only disable those. The 
conversion rvalue -> temp rvalue -> ref is not dangerous 
because the starting value on the caller side could not be 
inspected after the call anyway.


I agree that the DIP needs to be clearer wrt. rvalues resulting 
from implicit conversions. I also agree with the above point. I'm 
just not sure we need to allow implicit conversions from rvalue 
argument expressions at all. To minimize the changes for overload 
resolution, it might be enough to allow rvalue argument 
expressions of matching type only, i.e., the types which are 
allowed for current ref semantics. After all, I don't plan to use 
the proposed ref semantics for primitive types where that might 
come in handy (something silly like `modf(x, 123.456)` if the 
second param is a `ref real`), and explicit casts would IMO be an 
acceptable price to pay for safety and visibility in the 
remaining cases.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/30/19 1:29 PM, Manu wrote:

On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via
Digitalmars-d-announce  wrote:


On Wed, 30 Jan 2019 09:15:36 -0800, Manu wrote:

Why are you so stuck on this case? The DIP is about accepting rvalues,
not lvalues...
Calling with 'p', an lvalue, is not subject to this DIP.


The result of a CastExpression is an rvalue. An implicit cast is a
compiler-inserted CastExpression. Therefore all lvalues with a potential
implicit cast are rvalues.


But there's no existing language rule that attempts to perform an
implicit cast where an lvalue is supplied to a ref arg...?


That's exactly what lowerings are for: to precisely specify what should 
happen when the proposed construct is used. DIP 1016 proposes a lowering 
of the form:


{
  T __temp0 = expr;
  fun(__temp0);
}

In the first step, an implicit conversion of an lvalue may take place.


Why is the cast being attempted? 'p' is an lvalue, and whatever that
does should remain exactly as is (ie, emits a compile error).


Not according to DIP 1016. Here is an example pasted from it:


This inconvenience extends broadly to every manner of rvalue passed to 
functions, including:

...
fun(my_short); // implicit type conversions (ie, short->int promotion)


Presumably my_short is a variable of type short. Is that correct?

Again (this is not a rhetorical or sarcastic question): are you sure DIP 
1016 expresses what you are trying to accomplish?



We could perhaps allow this for `const` args, but that feels like
separate follow-up work to me, and substantially lesser value. This
DIP doesn't want to change anything about lvalues.


What we have here is:

* DIP 1016 proposes a hole in the language one could drive a truck through.

* The problem goes undetected in community review.

* Its own author seems to not have an understanding of what the DIP 
proposes.



Andrei


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread 12345swordy via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 18:29:37 UTC, Manu wrote:
On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via 
Digitalmars-d-announce  
wrote:


On Wed, 30 Jan 2019 09:15:36 -0800, Manu wrote:
> Why are you so stuck on this case? The DIP is about 
> accepting rvalues,

> not lvalues...
> Calling with 'p', an lvalue, is not subject to this DIP.

The result of a CastExpression is an rvalue. An implicit cast 
is a compiler-inserted CastExpression. Therefore all lvalues 
with a potential implicit cast are rvalues.


But there's no existing language rule that attempts to perform 
an

implicit cast where an lvalue is supplied to a ref arg...?
Why is the cast being attempted?

Because of the rewrite that your proposed in your dip.

void fun(ref int x);

fun(10);

{
  T __temp0 = void;
  fun(__temp0 := 10);
}

lets replace 10 with a short variable named: S

void fun(ref int x);

fun(S)
{
  T __temp0 = void;
  fun(__temp0 := S);
}
fun(__temp0 := S) This is where the cast is being attempted. As 
__temp0 is aninteger type and S is a 
short type


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread 12345swordy via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 16:47:48 UTC, Don wrote:
On Wednesday, 30 January 2019 at 13:58:38 UTC, 12345swordy 
wrote:
I do not accept gut feeling as a valid objection here. The 
current workarounds is shown to be painful as shown in the dip 
and in the discussions that it currently link. That *the* 
motivation here.


Like I said previously I am on the reviews side and that's it.


In terms of what exactly?
Walter had stated they do not rejected the dip in principle.
You apparently *do* rejected it in principle, from judging your 
posts here.


By the way I don't like your tone when you say: "I do not 
accept gut feeling as a valid objection here".


If you stated that you think it a bad/good idea without 
explaining why you think it. That is what I call "gut feeling"


Alright we're talking about a change that have been on hold for 
almost 10 years, if it was simple it would already been done.


The current dip system didn't exist 10 years prior. I wouldn't 
say that things are already done due to them being simple, as 
there are quite number of "simple" features that wasn't 
implemented already (Looking at you tuples).


-Alex




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Wed, Jan 30, 2019 at 9:20 AM Neia Neutuladh via
Digitalmars-d-announce  wrote:
>
> On Wed, 30 Jan 2019 09:15:36 -0800, Manu wrote:
> > Why are you so stuck on this case? The DIP is about accepting rvalues,
> > not lvalues...
> > Calling with 'p', an lvalue, is not subject to this DIP.
>
> The result of a CastExpression is an rvalue. An implicit cast is a
> compiler-inserted CastExpression. Therefore all lvalues with a potential
> implicit cast are rvalues.

But there's no existing language rule that attempts to perform an
implicit cast where an lvalue is supplied to a ref arg...?
Why is the cast being attempted? 'p' is an lvalue, and whatever that
does should remain exactly as is (ie, emits a compile error).

We could perhaps allow this for `const` args, but that feels like
separate follow-up work to me, and substantially lesser value. This
DIP doesn't want to change anything about lvalues.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Manu via Digitalmars-d-announce
On Tue., 29 Jan. 2019, 10:25 pm Walter Bright via Digitalmars-d-announce <
digitalmars-d-announce@puremagic.com wrote:

> On 1/29/2019 3:45 AM, Andrei Alexandrescu wrote:
> > I am talking about this:
> >
> > int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
> > if (alloc.reallocate(a, 200 * int.sizeof)
> > {
> >  assert(a.length == 200);
> > }
>
> Even simpler:
>
>void func(ref void* p) {
>  free(p); // frees (1)
>  p = malloc(100);  // (2)
>}
>
>int* p = cast(int*)malloc(16);  // (1)
>func(p);// p copied to temp for conversion to
> void*
>free(p);// frees (1) again
>// (2) is left dangling
>
> It's a memory corruption issue, with no way to detect it.
>

Why are you so stuck on this case? The DIP is about accepting rvalues, not
lvalues...
Calling with 'p', an lvalue, is not subject to this DIP.

>


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Neia Neutuladh via Digitalmars-d-announce
On Wed, 30 Jan 2019 09:15:36 -0800, Manu wrote:
> Why are you so stuck on this case? The DIP is about accepting rvalues,
> not lvalues...
> Calling with 'p', an lvalue, is not subject to this DIP.

The result of a CastExpression is an rvalue. An implicit cast is a 
compiler-inserted CastExpression. Therefore all lvalues with a potential 
implicit cast are rvalues.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread Don via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 13:58:38 UTC, 12345swordy wrote:
I do not accept gut feeling as a valid objection here. The 
current workarounds is shown to be painful as shown in the dip 
and in the discussions that it currently link. That *the* 
motivation here.


Like I said previously I am on the reviews side and that's it.

By the way I don't like your tone when you say: "I do not accept 
gut feeling as a valid objection here".


I don't think you would like if I say that your opinion is biased 
because you know the author either, so don't go that way, because 
it's not only me against this DIP.


I am familiar with the author here, he is very involved with 
the C++<->D compatibility side of things. He knows the pain 
from first hand experience.


Alright we're talking about a change that have been on hold for 
almost 10 years, if it was simple it would already been done.


In this thread we saw some other concerns been emerged.

Finally I only know the author by his postings in this forum, and 
I don't have anything personally against him.


Donald.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-30 Thread 12345swordy via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 04:34:46 UTC, Don wrote:
On Wednesday, 30 January 2019 at 03:01:36 UTC, 12345swordy 
wrote:

On Wednesday, 30 January 2019 at 00:25:17 UTC, Don wrote:
But what I fail to see is why can't the programmer solve this 
themselves instead of relying on a new feature that would 
cause more harm?



Donald.


...Did you even read the arguments in the dip? This has been 
discuss quite a lot in the forums, it even gives you links to 
them.


Well, I read the DIP and the whole forum discussion back in the 
day, and again I think this will create more harm than benefits 
the way it was proposed.

Donald.


I do not accept gut feeling as a valid objection here. The 
current workarounds is shown to be painful as shown in the dip 
and in the discussions that it currently link. That *the* 
motivation here.
I am familiar with the author here, he is very involved with the 
C++<->D compatibility side of things. He knows the pain from 
first hand experience.


-Alex


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Walter Bright via Digitalmars-d-announce

On 1/29/2019 3:45 AM, Andrei Alexandrescu wrote:

I am talking about this:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof)
{
     assert(a.length == 200);
}


Even simpler:

  void func(ref void* p) {
free(p);  // frees (1)
p = malloc(100);  // (2)
  }

  int* p = cast(int*)malloc(16);  // (1)
  func(p);// p copied to temp for conversion to void*
  free(p);// frees (1) again
  // (2) is left dangling

It's a memory corruption issue, with no way to detect it.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Don via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 03:01:36 UTC, 12345swordy wrote:

On Wednesday, 30 January 2019 at 00:25:17 UTC, Don wrote:
But what I fail to see is why can't the programmer solve this 
themselves instead of relying on a new feature that would 
cause more harm?



Donald.


...Did you even read the arguments in the dip? This has been 
discuss quite a lot in the forums, it even gives you links to 
them.


Well, I read the DIP and the whole forum discussion back in the 
day, and again I think this will create more harm than benefits 
the way it was proposed.


And starting from the beginning of this DIP - Rationale example:

   "void fun(int x);

fun(10); // <-- this is how users expect to call a typical 
function

But when ref is present:

void fun(ref int x);

fun(10); // <-- compile error; not an lvalue!!
Necessitating the workaround:

int temp = 10;
fun(temp);

This inconvenience extends broadly to every manner of rvalue 
passed to

functions, including:"

So the solution in the way I understood is pretty much a syntax 
sugar, creating temporary variable with destruction.


But the concept is weird, because originally your function 
signature has a "ref parameter" and we're just creating a 
workaround expanding it to handle rvalues.


I would prefer to handle it myself with overloading instead of 
being presented with new language feature creating different 
scenarios for something that's not the case right now.


Otherwise D will be pretty much like C++ and in this case why 
bother with it?


Donald.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread 12345swordy via Digitalmars-d-announce

On Wednesday, 30 January 2019 at 00:25:17 UTC, Don wrote:
But what I fail to see is why can't the programmer solve this 
themselves instead of relying on a new feature that would cause 
more harm?



Donald.


...Did you even read the arguments in the dip? This has been 
discuss quite a lot in the forums, it even gives you links to 
them.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Don via Digitalmars-d-announce

I'm on the reviewers side here.

To be honest I never liked this DIP and maybe I'll sound dumb but 
I think this is a case where this could bring more problem than 
anything.


The way I see this would be more like a syntax sugar to create 
temporary variable for ref parameters and that's it.


But what I fail to see is why can't the programmer solve this 
themselves instead of relying on a new feature that would cause 
more harm?


With overload some could do:

void f(int i){
f(i);
}

void f(ref int i){
++i;
writeln(i);
}

void main(){
int i = 0;
f(10);
f(i);
}

prints:
11
1

The "f" function will work with ref or literal (rvalues).

But this will be controlled by the programmer the way they want 
it.


Donald.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Olivier FAURE via Digitalmars-d-announce
On Monday, 28 January 2019 at 17:23:51 UTC, Andrei Alexandrescu 
wrote:
* Regarding the argument "why not make this an iterative 
process where concerns are raised and incrementally addressed?" 
We modeled the DIP process after similar processes - conference 
papers, journal papers, proposals in other languages. There is 
a proposal by one or more responsibles, perfected by a 
community review, and submitted for review. This encourages 
building a strong proposal - as strong as can be - prior to 
submission. Washing that down to a negotiation between the 
proposers and the reviewers leads to a "worst acceptable 
proposal" state of affairs in which proposers are incentivized 
to submit the least-effort proposal, reactively change it as 
issues are raised by reviewers.


Fair enough.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 6:45 AM, Andrei Alexandrescu wrote:
It is truly remarkable that DIP 1016 provides not only a solution to the 
problem, but almost neglects to mention it.


Meant "...not only no solution..."


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 3:35 AM, Manu wrote:

1. All of this is more useful criticism than the official and final
criticism affixed to the rejection, which when revised to remove the
incorrect criticisms, is basically left with the text "The Language
Maintainers found other issues with the proposal, most of which may
have been remedied through simple revision"


No. This is a nonnegotiable matter:

void bump(ref int x) { ++x; }
short y = 42;
bump(y);
assert(y == 43); // fails

The code above should not compile. The DIP allows it to compile. We 
didn't see how the DIP can be lightly edited to fix this problem, so we 
recommended a complete rethinking and rewrite.



2. All of this criticism could have been given at any point in the
past half a year or so prior to submission, and that would have been
appreciated, rather than wasting our time.


We have given this criticism ever since ten years ago when you brought 
the matter up. Literally every time, including in person. Whenever you 
said "why not bind rvalues to ref?" we religiously replied with 
(paraphrased of course) "We are worried about rvalues resulting from 
implicit conversion of lvalues. You'd need to find a solution to that."


It is truly remarkable that DIP 1016 provides not only a solution to the 
problem, but almost neglects to mention it.



3. "It does not influence our decision and should not be construed as
an essential aspect of the review"  <--  Then why did it feature as
one of just 3 core criticism in the rejection text? And supplied as
one of the 2 reasons that could not "have been remedied through simple
revision".


If the matter above can be resolve through simple revision that would be 
great. I don't think it can, but would love to be proven wrong!



4. "Under DIP 1016, a call with any T[] will silently "succeed" by
converting the slice to void[]"  <--  Do you mean "... with any T[]
rvalue ..."? What would be the aim of that call? Can you suggest a
particularly sinister construction?


I am talking about this:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof)
{
assert(a.length == 200);
}

By applying the lowering rules in the DIP (including your pending 
revision), the code is lowered to:


int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
void[] __temp0 = a;
if (alloc.reallocate(__temp0, 200 * int.sizeof)
{
assert(a.length == 200);
}

The code is far from sinister. But the assertion will fail.

I want to make sure there is mutual understanding that:

1. DIP 1016 proposes this semantics
2. We do not accept this semantics

Even if there is no agreement with (2), these are facts that I want to 
make sure are understood by everyone involved - you, us, the rest of the 
community.



5. "and recommended that it be rewritten simply because it would be
easier and would engender a stronger DIP."  <--  I wrote the DIP I
wrote... your official feedback affixed to the bottom of the DIP was
pretty much entirely unhelpful, almost offensively so. I would just
write the same DIP if I started again. I genuinely hope someone can be
bothered to do this. After 10 years on this, I think I'm over it.


I am sorry you found the review unfit for your needs. I thought it puts 
the main matter plain and simple: we do not accept code like this:


void bump(ref int x) { ++x; }
short y = 42;
bump(y);
assert(y == 43); // fails

Honest, I don't think you have spent 10 years on this DIP. It is not 
thorough work and fails to address the main problem it was supposed to 
address: The one above.



6. "This result was frustrating and disheartening on our side, too: a
stronger DIP ..."  <--  I'm sorry you hated it. You could have
reviewed it at any point, made suggestions at any point, written it
yourself, or encouraged someone competent to do it.


We didn't hate it. We made suggestions literally every time you brought 
up the issue over the past decade. For my part, I have no idea what more 
input I could have provided. "Solve the rvalues coming from implicit 
conversions" is all feedback the DIP needs.



7. Your general tone is superior, as usual.


No need to attempt to make this personal, and claim the moral ground in 
the process. Nobody is after you. We all want the D language to become 
better. The DIP is not good. This is what it is.


All is not lost - the DIP is a good inspiration for a couple of ideas 
that deserve investigation. It seems that allowing _only_ rvalues to be 
bound to ref may work. I'm cautious because there may be cases we didn't 
think of.



Andrei


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 6:38 AM, Nicholas Wilson wrote:

On Tuesday, 29 January 2019 at 08:35:11 UTC, Manu wrote:

4. "Under DIP 1016, a call with any T[] will silently "succeed"  by
converting the slice to void[]"  <--  Do you mean "... with any T[]  
rvalue ..."? What would be the aim of that call? Can you suggest a 
particularly sinister construction?


I _think_ what is meant is:

void[] allocate(size_t size);
bool reallocate(ref void[] b, size_t s);
void deallocate(ref void[]);

T[] arr = allocate(42);
arr.reallocate(8192); // reallocates a temporary as T[] is cast to void
arr.deallocate(); // double free


Affirmative. (Just wrote about the same in another post). Thanks very much.

Andrei



Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Nicholas Wilson via Digitalmars-d-announce

On Tuesday, 29 January 2019 at 08:35:11 UTC, Manu wrote:
4. "Under DIP 1016, a call with any T[] will silently "succeed" 
 by
converting the slice to void[]"  <--  Do you mean "... with any 
T[]  rvalue ..."? What would be the aim of that call? Can you 
suggest a particularly sinister construction?


I _think_ what is meant is:

void[] allocate(size_t size);
bool reallocate(ref void[] b, size_t s);
void deallocate(ref void[]);

T[] arr = allocate(42);
arr.reallocate(8192); // reallocates a temporary as T[] is cast 
to void

arr.deallocate(); // double free




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 1:01 AM, Manu wrote:

This DIP is about passing rvalues to ref... so the issue you describe
passing lvalues to ref does not apply here.
There is no suggestion to change lvalue rules anywhere in this DIP.


The problem is with rvalues resulting as temporaries from lvalues. As in:

void bump(ref int x) { ++x; }
short y = 42;
bump(y);
assert(y == 43); // oops

This is a smoking gun. If DIP 1016 does not propose allowing the code 
above, it has caused a gross misunderstanding. Similarly, you mention in 
a different response:



4. "Under DIP 1016, a call with any T[] will silently "succeed" by
converting the slice to void[]"  <--  Do you mean "... with any T[]
rvalue ..."? What would be the aim of that call? Can you suggest a
particularly sinister construction?


If your intent was to NOT allow rvalues resulting from conversions, it 
didn't come through at all. On the contrary, some examples suggest DIP 
1016 _does_ allow it, as in this example:



This inconvenience extends broadly to every manner of rvalue passed to 
functions, including:


...
fun(my_short); // implicit type conversions (ie, short->int promotion)


The reader assumes since the DIP characterizes passing a short lvalue to 
a ref int is an inconvenience, the DIP has set out to resolve it.


The lowering rules proposed by DIP 1006 prescribe the following:

void bump(ref int x) { ++x; }
short y = 42;
bump(y);
===>
void bump(ref int x) { ++x; }
short y = 42;
{
int __temp0 = y;
bump(__temp0);
}

So... yes, lvalues do (undesirably) get converted to rvalues of a 
different type according to the DIP.


Are you sure the DIP expresses what you are trying to accomplish?


Andrei




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Walter Bright via Digitalmars-d-announce

On 1/28/2019 10:10 PM, Manu wrote:

Furthermore, D has these match levels:

  1. exact
  2. const
  3. conversion
  4. no match

If there are two or more matches at the same level, the decision is made based
on partial ordering. How does adding the new ref/value overloading fit into 
that?


I haven't described this well. I can try and improve this.
Where can I find these existing rules detailed comprehensively? I have
never seen them mentioned in the dlang language reference.


It's where it should be, under "Function Overloading":

https://dlang.org/spec/function.html#function-overloading



If you had have spotted it 4-5 months ago, I would have wasted a LOT
less time... and now you're asking me to sign up for another few
hundred days of do-over from square-1.


It's pretty clear that just writing the DIP myself will take me less time than 
point-by-point endlessly arguing about it. But it will take more calendar time, 
because all this stuff falls to me. It's why I get paid the big bucks.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-29 Thread Manu via Digitalmars-d-announce
On Mon, Jan 28, 2019 at 9:25 AM Andrei Alexandrescu via
Digitalmars-d-announce  wrote:
>
> On 1/24/19 2:18 AM, Mike Parker wrote:
> > Walter and Andrei have declined to accept DIP 1016, "ref T accepts
> > r-values", on the grounds that it has two fundamental flaws that would
> > open holes in the language. They are not opposed to the feature in
> > principle and suggested that a proposal that closes those holes and
> > covers all the bases will have a higher chance of getting accepted.
> >
> > You can read a summary of the Formal Assessment at the bottom of the
> > document:
> >
> > https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1016.md
>
> Hi everyone, I've followed the responses to this, some conveying
> frustration about the decision and some about the review process itself.
> As the person who carried a significant part of the review, allow me to
> share a few thoughts of possible interest.
>
> * Fundamentally: a DIP should stand on its own and be judged on its own
> merit, regardless of rhetoric surrounding it, unstated assumptions, or
> trends of opinion in the forums. There has been a bit of material in
> this forum discussion that should have been argued properly as a part of
> the DIP itself.
>
> * The misinterpretation of the rewrite (expression -> statement vs.
> statement -> statement) is mine, apologies. (It does not influence our
> decision and should not be construed as an essential aspect of the
> review.) The mistake was caused by the informality of the DIP, which
> shows rewrites as a few simplistic examples instead of a general rewrite
> rule. Function calls are expressions, so I naturally assumed the path
> would be to start with the function call expression. Formulating a
> general rule as a statement rewrite is possible but not easy and fraught
> with peril, as discussion in this thread has shown. I very much
> recommend going the expression route (e.g. with the help of lambdas)
> because that makes it very easy to expand to arbitrarily complex
> expressions involving function calls. Clarifying what temporaries get
> names and when in a complex expression is considerably more difficult
> (probably not impossible but why suffer).
>
> * Arguments of the form: "You say DIP 1016 is bad, but look at how bad
> DIP XYZ is!" are great when directed at the poor quality of DIP XYZ.
> They are NOT good arguments in favor of DIP 1016.
>
> * Arguments of the form "Functions that take ref parameters just for
> changing them are really niche anyway" should be properly made in the
> DIP, not in the forums and assumed without stating in the DIP. Again,
> what's being evaluated is "DIP" not "DIP + surrounding rhetoric". A good
> argument would be e.g. analyzing a number of libraries and assess that
> e.g. 91% uses of ref is for efficiency purposes, 3% is unclear, and only
> 6% is for side-effect purpose. All preexisting code using ref parameters
> written under the current rule assumes that only lvalues will be bound
> to them. A subset of these functions take by ref for changing them only.
> The DIP should explain why that's not a problem, or if it is one it is a
> small problem, etc. My point is - the DIP should _approach_ the matter
> and build an argument about it. One more example from preexisting code
> for illustration, from the standard library:
>
> // in the allocators API
> bool expand(ref void[] b, size_t delta);
> bool reallocate(ref void[] b, size_t s);
>
> These primitives modify their first argument in essential ways. The
> intent is to fill b with the new slice resulted after
> expansion/reallocation. Under the current rules, calling these
> primitives is cumbersome, but usefully so because the processing done
> requires extra care if typed data is being reallocated. Under DIP 1016,
> a call with any T[] will silently "succeed" by converting the slice to
> void[], passing the temporary to expand/reallocate, then return as if
> all is well - yet the original slice has not been changed. The DIP
> should create a salient argument regarding these situations (and not
> only this example, but the entire class). It could perhaps argue that:
>
> - Such code is bad to start with, and should not have been written.
> - Such code is so rare, we can take the hit. We then have a
> recommendation for library writers on how to amend their codebase (use
> @disable or some other mechanisms).
> - The advantages greatly outweigh this problem.
> - The bugs caused are minor easy to find.
> - ...
>
> Point being: the matter, again should be _addressed_ by the DIP.
>
> * Regarding our recommendation that the proposal is resubmited as a
> distinct DIP as opposed to a patch on the existing DIP: this was not
> embracing bureaucracy. Instead, we considered that the DIP was too poor
> to be easily modified into a strong proposal, and recommended that it be
> rewritten simply because it would be easier and would engender a
> stronger DIP.
>
> * Regarding the argument "why not make this an iterative 

Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Manu via Digitalmars-d-announce
On Fri, Jan 25, 2019 at 10:20 PM Walter Bright via
Digitalmars-d-announce  wrote:
>
> On 1/25/2019 7:44 PM, Manu wrote:
> > I never said anything about 'rvalue references',
>
> The DIP mentions them several times in the "forum threads" section. I see you
> want to distinguish the DIP from that; I recommend a section clearing that up.
>
> However, my points about the serious problems with @disable syntax remain.

I think the `@disable` semantic is correct; I understand your
criticism that you have to search for the negative to understand the
restruction, but that perspective arises presumably from a presumption
that you want to explicity state inclusion, which is the opposite of
the intent.
The goal is to state exclusion, we are *adding* restrictions (ie,
removing potential calls) from the default more-inclusive behaviour,
and from that perspective, `@disable` is in the proper place.

> A section comparing with the C++ solution is necessary as well, more than the
> one sentence dismissal. For example, how C++ deals with the:
>
>  void foo(const int x);
>  void foo(const int& x);
>
> situation needs to be understood and compared. Failing to understand it can 
> lead
> to serious oversights. For example, C++ doesn't require an @disable syntax to
> make it work.

C++ doesn't desire a @disable semantic, it just works as described in this DIP.

Eg:

```c++
void fun(const int& x) {}
void test()
{
fun(10);
fun(short(10)); // <- no problem!
}
```

It's the dlang critics of this functionality that demand explicit
controls on functions accepting one kind or the other.
I personally see no value in all that noise, but I added it in due to
popular demand.

> >> [...]
> >> Should `s` be promoted to an int temporary, then pass the temporary by
> >> reference? I can find no guidance in the DIP. What if `s` is a uint (i.e. 
> >> the
> >> implicit conversion is a type paint and involves no temporary)?
> > As per the DIP; yes, that is the point.
> > The text you seek is written: "[...]. The user should not experience
> > edge cases, or differences in functionality when calling fun(int x) vs
> > fun(ref int x)."
>
> I don't see how that addresses implicit type conversion at all.

It explicitly permits it as one of the goals of the DIP. Uniformity in
function calling is one of the main goals here.

> > Don't accept naked ref unless you want these semantics. There is a
> > suite of tools offered to use where this behaviour is undesirable.
> > Naked `ref` doesn't do anything particularly interesting in the
> > language today that's not *identical* semantically to using a pointer
> > and adding a single '&' character at the callsite.
>
> It's not good enough. The DIP needs to specifically address what happens with
> implicit conversions. The reader should not be left wondering about what is
> implied.

As I said above, it couldn't be stated more clearly in the DIP; it is
very explicitly permitted, and stated that "the user should not
experience any difference in calling semantics when using ref".

> I often read a spec and think yeah, yeah, of course it must be that
> way. But it is spelled out in the spec, and reading it gives me confidence 
> that
> I'm understanding the semantics, and it gives me confidence that whoever wrote
> the spec understood it.

Okay, but it is spelled out. How could I make it clearer?

> (Of course, writing out the implications sometimes causes the writer to 
> realize
> he didn't actually understand it at all.)
>
> Furthermore, D has these match levels:
>
>  1. exact
>  2. const
>  3. conversion
>  4. no match
>
> If there are two or more matches at the same level, the decision is made based
> on partial ordering. How does adding the new ref/value overloading fit into 
> that?

I haven't described this well. I can try and improve this.
Where can I find these existing rules detailed comprehensively? I have
never seen them mentioned in the dlang language reference.
It's hard for me to speak in these terms, when I've never seen any
text in the language spec that does so.

Note; this criticism was nowhere to be found in your rejection text,
and it would have been trivial during community reviews to make this
note.
I feel like this is a mostly simple revision to make.

> >> It should never have gotten this far without giving a precise explanation 
> >> of how
> > exception safety is achieved when faced with multiple parameters.
> >
> > I apologise. I've never used exceptions in any code I've ever written,
> > so it's pretty easy for me to overlook that detail.
>
> It's so, so easy to get that wrong. C++ benefits from decades of compiler bug
> fixes with that.

I think my revision is water-tight (up a few posts). If the new
rewrite were written by hand and had some problem there, then there's
a serious problem with core language.

> > Nobody else that did the community reviews flagged it,
>
> That's unfortunately right. Note that 'alias this' was approved and 
> implemented,

Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Manu via Digitalmars-d-announce
On Mon, Jan 28, 2019 at 12:00 PM Andrei Alexandrescu via
Digitalmars-d-announce  wrote:
>
> On 1/28/19 1:00 PM, Andrei Alexandrescu wrote:
> > On 1/24/19 3:01 PM, kinke wrote:
> >> On Thursday, 24 January 2019 at 09:49:14 UTC, Manu wrote:
> >>> We discussed and concluded that one mechanism to mitigate this issue
> >>> was already readily available, and it's just that 'out' gains a much
> >>> greater sense of identity (which is actually a positive side-effect if
> >>> you ask me!).
> >>> You have a stronger motivation to use 'out' appropriately, because it
> >>> can issue compile errors if you accidentally supply an rvalue.
> >>
> >> `out` with current semantics cannot be used as drop-in replacement for
> >> shared in-/output ref params, as `out` params are default-initialized
> >> on entry. Ignoring backwards compatibility for a second, I think
> >> getting rid of that would actually be beneficial (most args are
> >> probably already default-initialized by the callee in the line above
> >> the call...) - and I'd prefer an explicitly required `out` at the call
> >> site (C# style), to make the side effect clearly visible.
> >>
> >> I'd have otherwise proposed a `@noRVal` param UDA, but redefining
> >> `out` is too tempting indeed. ;)
> >
> > It seems to me that a proposal adding the "@rvalue" attribute in
> > function signatures to each parameter that would accept either an rvalue
> > or an lvalue would be easy to argue.
> >
> > - No exposing existing APIs to wrong uses
> > - The function's writer makes the decision ("I'm fine with this function
> > taking an rvalue")
> > - Appears in the function's documentation
> > - Syntax is light and localized where it belongs
> > - Scales well with number of parameters
> > - Transparent to callers
> >
> > Whether existing keyword combinations ("in", "out", "ref" etc) could be
> > used is a secondary point.
> >
> > The advantage is there's a simple and clear path forward for API
> > definition and use.
> >
> >
> > Andrei
>
> One more thought.
>
> The main danger is restricted to a specific conversion: lvalue of type T
> is converted to ref of type U. That way both the caller and the function
> writer believe the value gets updated, when in fact it doesn't. Consider:
>
> real modf(real x, ref real i);
>
> Stores integral part in i, returns the fractional part. At this point
> there are two liabilities:
>
> 1. User passes the wrong parameter type:
>
> double integral;
> double frac = modf(x, integral);
> // oops, integral is always NaN
>
> The function silently converts integral from double to real and passes
> the resulting temporary into the function. The temporary is filled and
> lost, leaving user's value unchanged.
>
> 2. The API gets changed:
>
> // Fine, let's use double
> real modf(real x, ref double i);
>
> At this point all correct callers are silently broken - everybody who
> correctly used a real for the integral part now has their call broken
> (real implicitly converts to a double temporary, and the change does not
> propagate to the user's value).
>
> (If the example looks familiar it may be because of
> https://dlang.org/library/std/math/modf.html.)
>
> So it seems that the real problem is that the participants wrongly
> believe an lvalue is updated.
>
> But let's say the caller genuinely doesn't care about the integral part.
> To do so is awkward:
>
> real unused;
> double frac = modf(x, unused);
>
> That code isn't any better or less dangerous than:
>
> double frac = modf(x, double());
>
> Here the user created willingly created an unnamed temporary of type
> double. Given that there's no doubt the user is not interested in that
> value after the call, the compiler could (in a proposed semantics) allow
> the conversion of the unnamed temporary to ref.
>
> TL;DR: it could be argued that the only dangerous conversions are lvalue
> -> temp rvalue -> ref, so only disable those. The conversion rvalue ->
> temp rvalue -> ref is not dangerous because the starting value on the
> caller side could not be inspected after the call anyway.

I started reading this post, and I was compelled to reply with this
same response, and then I realised you got there yourself.
I understand your concern, and it has actually been discussed lightly,
but regardless, you'll find that the issue you describe is not
suggested anywhere in this DIP.
This DIP is about passing rvalues to ref... so the issue you describe
passing lvalues to ref does not apply here.
There is no suggestion to change lvalue rules anywhere in this DIP.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/28/19 9:15 PM, Andrei Alexandrescu wrote:

On 1/28/19 5:23 PM, Steven Schveighoffer wrote:

I already see this kind of bug all the time with alias this.


Can you please post more detail? It may be of relevance to future work.


Any time you have the alias this, then you can get confused when calling 
a function expecting it to be sent as the original type, but the alias 
this is used instead. In cases where both are seemingly accepted by 
overloads, then it can be confusing which overload is used. Sometimes 
it's as simple as the overload that you were expecting to be called 
won't compile or is deselected by constraints. But the code still 
compiles and runs, just does something different from what you expected.


I meant that the effect is similar to what you were noting.

-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/28/19 5:23 PM, Steven Schveighoffer wrote:

I already see this kind of bug all the time with alias this.


Can you please post more detail? It may be of relevance to future work.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/28/19 2:58 PM, Andrei Alexandrescu wrote:
TL;DR: it could be argued that the only dangerous conversions are lvalue 
-> temp rvalue -> ref, so only disable those. The conversion rvalue -> 
temp rvalue -> ref is not dangerous because the starting value on the 
caller side could not be inspected after the call anyway.


I agree with you. It's one thing for the caller to pass in an rvalue 
that can clearly no longer be accessed. It's another thing to pass in an 
lvalue and have it "update" a temporary instead.


I already see this kind of bug all the time with alias this.

-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/28/19 1:00 PM, Andrei Alexandrescu wrote:

On 1/24/19 3:01 PM, kinke wrote:

On Thursday, 24 January 2019 at 09:49:14 UTC, Manu wrote:

We discussed and concluded that one mechanism to mitigate this issue
was already readily available, and it's just that 'out' gains a much
greater sense of identity (which is actually a positive side-effect if
you ask me!).
You have a stronger motivation to use 'out' appropriately, because it
can issue compile errors if you accidentally supply an rvalue.


`out` with current semantics cannot be used as drop-in replacement for 
shared in-/output ref params, as `out` params are default-initialized 
on entry. Ignoring backwards compatibility for a second, I think 
getting rid of that would actually be beneficial (most args are 
probably already default-initialized by the callee in the line above 
the call...) - and I'd prefer an explicitly required `out` at the call 
site (C# style), to make the side effect clearly visible.


I'd have otherwise proposed a `@noRVal` param UDA, but redefining 
`out` is too tempting indeed. ;)


It seems to me that a proposal adding the "@rvalue" attribute in 
function signatures to each parameter that would accept either an rvalue 
or an lvalue would be easy to argue.


- No exposing existing APIs to wrong uses
- The function's writer makes the decision ("I'm fine with this function 
taking an rvalue")

- Appears in the function's documentation
- Syntax is light and localized where it belongs
- Scales well with number of parameters
- Transparent to callers

Whether existing keyword combinations ("in", "out", "ref" etc) could be 
used is a secondary point.


The advantage is there's a simple and clear path forward for API 
definition and use.



Andrei


One more thought.

The main danger is restricted to a specific conversion: lvalue of type T 
is converted to ref of type U. That way both the caller and the function 
writer believe the value gets updated, when in fact it doesn't. Consider:


real modf(real x, ref real i);

Stores integral part in i, returns the fractional part. At this point 
there are two liabilities:


1. User passes the wrong parameter type:

double integral;
double frac = modf(x, integral);
// oops, integral is always NaN

The function silently converts integral from double to real and passes 
the resulting temporary into the function. The temporary is filled and 
lost, leaving user's value unchanged.


2. The API gets changed:

// Fine, let's use double
real modf(real x, ref double i);

At this point all correct callers are silently broken - everybody who 
correctly used a real for the integral part now has their call broken 
(real implicitly converts to a double temporary, and the change does not 
propagate to the user's value).


(If the example looks familiar it may be because of 
https://dlang.org/library/std/math/modf.html.)


So it seems that the real problem is that the participants wrongly 
believe an lvalue is updated.


But let's say the caller genuinely doesn't care about the integral part. 
To do so is awkward:


real unused;
double frac = modf(x, unused);

That code isn't any better or less dangerous than:

double frac = modf(x, double());

Here the user created willingly created an unnamed temporary of type 
double. Given that there's no doubt the user is not interested in that 
value after the call, the compiler could (in a proposed semantics) allow 
the conversion of the unnamed temporary to ref.


TL;DR: it could be argued that the only dangerous conversions are lvalue 
-> temp rvalue -> ref, so only disable those. The conversion rvalue -> 
temp rvalue -> ref is not dangerous because the starting value on the 
caller side could not be inspected after the call anyway.



Andrei


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/24/19 3:01 PM, kinke wrote:

On Thursday, 24 January 2019 at 09:49:14 UTC, Manu wrote:

We discussed and concluded that one mechanism to mitigate this issue
was already readily available, and it's just that 'out' gains a much
greater sense of identity (which is actually a positive side-effect if
you ask me!).
You have a stronger motivation to use 'out' appropriately, because it
can issue compile errors if you accidentally supply an rvalue.


`out` with current semantics cannot be used as drop-in replacement for 
shared in-/output ref params, as `out` params are default-initialized on 
entry. Ignoring backwards compatibility for a second, I think getting 
rid of that would actually be beneficial (most args are probably already 
default-initialized by the callee in the line above the call...) - and 
I'd prefer an explicitly required `out` at the call site (C# style), to 
make the side effect clearly visible.


I'd have otherwise proposed a `@noRVal` param UDA, but redefining `out` 
is too tempting indeed. ;)


It seems to me that a proposal adding the "@rvalue" attribute in 
function signatures to each parameter that would accept either an rvalue 
or an lvalue would be easy to argue.


- No exposing existing APIs to wrong uses
- The function's writer makes the decision ("I'm fine with this function 
taking an rvalue")

- Appears in the function's documentation
- Syntax is light and localized where it belongs
- Scales well with number of parameters
- Transparent to callers

Whether existing keyword combinations ("in", "out", "ref" etc) could be 
used is a secondary point.


The advantage is there's a simple and clear path forward for API 
definition and use.



Andrei


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-28 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/24/19 2:18 AM, Mike Parker wrote:
Walter and Andrei have declined to accept DIP 1016, "ref T accepts 
r-values", on the grounds that it has two fundamental flaws that would 
open holes in the language. They are not opposed to the feature in 
principle and suggested that a proposal that closes those holes and 
covers all the bases will have a higher chance of getting accepted.


You can read a summary of the Formal Assessment at the bottom of the 
document:


https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1016.md


Hi everyone, I've followed the responses to this, some conveying 
frustration about the decision and some about the review process itself. 
As the person who carried a significant part of the review, allow me to 
share a few thoughts of possible interest.


* Fundamentally: a DIP should stand on its own and be judged on its own 
merit, regardless of rhetoric surrounding it, unstated assumptions, or 
trends of opinion in the forums. There has been a bit of material in 
this forum discussion that should have been argued properly as a part of 
the DIP itself.


* The misinterpretation of the rewrite (expression -> statement vs. 
statement -> statement) is mine, apologies. (It does not influence our 
decision and should not be construed as an essential aspect of the 
review.) The mistake was caused by the informality of the DIP, which 
shows rewrites as a few simplistic examples instead of a general rewrite 
rule. Function calls are expressions, so I naturally assumed the path 
would be to start with the function call expression. Formulating a 
general rule as a statement rewrite is possible but not easy and fraught 
with peril, as discussion in this thread has shown. I very much 
recommend going the expression route (e.g. with the help of lambdas) 
because that makes it very easy to expand to arbitrarily complex 
expressions involving function calls. Clarifying what temporaries get 
names and when in a complex expression is considerably more difficult 
(probably not impossible but why suffer).


* Arguments of the form: "You say DIP 1016 is bad, but look at how bad 
DIP XYZ is!" are great when directed at the poor quality of DIP XYZ. 
They are NOT good arguments in favor of DIP 1016.


* Arguments of the form "Functions that take ref parameters just for 
changing them are really niche anyway" should be properly made in the 
DIP, not in the forums and assumed without stating in the DIP. Again, 
what's being evaluated is "DIP" not "DIP + surrounding rhetoric". A good 
argument would be e.g. analyzing a number of libraries and assess that 
e.g. 91% uses of ref is for efficiency purposes, 3% is unclear, and only 
6% is for side-effect purpose. All preexisting code using ref parameters 
written under the current rule assumes that only lvalues will be bound 
to them. A subset of these functions take by ref for changing them only. 
The DIP should explain why that's not a problem, or if it is one it is a 
small problem, etc. My point is - the DIP should _approach_ the matter 
and build an argument about it. One more example from preexisting code 
for illustration, from the standard library:


// in the allocators API
bool expand(ref void[] b, size_t delta);
bool reallocate(ref void[] b, size_t s);

These primitives modify their first argument in essential ways. The 
intent is to fill b with the new slice resulted after 
expansion/reallocation. Under the current rules, calling these 
primitives is cumbersome, but usefully so because the processing done 
requires extra care if typed data is being reallocated. Under DIP 1016, 
a call with any T[] will silently "succeed" by converting the slice to 
void[], passing the temporary to expand/reallocate, then return as if 
all is well - yet the original slice has not been changed. The DIP 
should create a salient argument regarding these situations (and not 
only this example, but the entire class). It could perhaps argue that:


- Such code is bad to start with, and should not have been written.
- Such code is so rare, we can take the hit. We then have a 
recommendation for library writers on how to amend their codebase (use 
@disable or some other mechanisms).

- The advantages greatly outweigh this problem.
- The bugs caused are minor easy to find.
- ...

Point being: the matter, again should be _addressed_ by the DIP.

* Regarding our recommendation that the proposal is resubmited as a 
distinct DIP as opposed to a patch on the existing DIP: this was not 
embracing bureaucracy. Instead, we considered that the DIP was too poor 
to be easily modified into a strong proposal, and recommended that it be 
rewritten simply because it would be easier and would engender a 
stronger DIP.


* Regarding the argument "why not make this an iterative process where 
concerns are raised and incrementally addressed?" We modeled the DIP 
process after similar processes - conference papers, journal papers, 
proposals in other languages. There is a proposal by one 

Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-26 Thread Walter Bright via Digitalmars-d-announce

On 1/26/2019 8:28 AM, Rubn wrote:

[...]


The point is, the DIP needs to spell this out in an organized and complete 
fashion, like any proper spec does.


We all want a better specified language, let's make it happen.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-26 Thread Rubn via Digitalmars-d-announce

On Saturday, 26 January 2019 at 06:15:22 UTC, Walter Bright wrote:

On 1/25/2019 7:44 PM, Manu wrote:

I never said anything about 'rvalue references',


The DIP mentions them several times in the "forum threads" 
section. I see you want to distinguish the DIP from that; I 
recommend a section clearing that up.


However, my points about the serious problems with @disable 
syntax remain.


A section comparing with the C++ solution is necessary as well, 
more than the one sentence dismissal. For example, how C++ 
deals with the:


void foo(const int x);
void foo(const int& x);

situation needs to be understood and compared. Failing to 
understand it can lead to serious oversights. For example, C++ 
doesn't require an @disable syntax to make it work.




[...]
Should `s` be promoted to an int temporary, then pass the 
temporary by
reference? I can find no guidance in the DIP. What if `s` is 
a uint (i.e. the
implicit conversion is a type paint and involves no 
temporary)?

As per the DIP; yes, that is the point.
The text you seek is written: "[...]. The user should not 
experience
edge cases, or differences in functionality when calling 
fun(int x) vs

fun(ref int x)."


I don't see how that addresses implicit type conversion at all.


Anything that could be implicitly converted to use foo(int) can 
be implicitly converted to pass a ref to the temporary that was 
implicitly converted to int into foo(ref int). No rules change in 
this regard. If you don't see how this address type conversion 
perhaps a code sample might help? The one that was given with 
short:


void foo(ref int);
void bar(int);

bar( short(10) ); // is ok
foo( short(10) ); // expected to be ok short->int ; ref to temp 
passed to foo


Just as bar(int) can be passed a short(10), foo(ref int) can be 
passed a reference to the temporary that was created as well.



Don't accept naked ref unless you want these semantics. There 
is a
suite of tools offered to use where this behaviour is 
undesirable.

Naked `ref` doesn't do anything particularly interesting in the
language today that's not *identical* semantically to using a 
pointer

and adding a single '&' character at the callsite.


It's not good enough. The DIP needs to specifically address 
what happens with implicit conversions. The reader should not 
be left wondering about what is implied. I often read a spec 
and think yeah, yeah, of course it must be that way. But it is 
spelled out in the spec, and reading it gives me confidence 
that I'm understanding the semantics, and it gives me 
confidence that whoever wrote the spec understood it.


(Of course, writing out the implications sometimes causes the 
writer to realize he didn't actually understand it at all.)


Furthermore, D has these match levels:

1. exact
2. const
3. conversion
4. no match

If there are two or more matches at the same level, the 
decision is made based on partial ordering. How does adding the 
new ref/value overloading fit into that?


The DIP goes over this, though not in a lot of detail. All the 
same rules apply as with the current implementation. Where there 
would be a compiler error trying to pass an rvalue would instead 
forward the value.


Effectively what is being implemented is the following (for type 
matching only):


   void foo( ref int );
   void foo( int value ) { foo( value ); }

Anything that would have been passed to foo(int) is passed to 
foo(ref int) as a reference to a temporary instead. No rules are 
changed in this regard for matching, all the same rules apply (as 
stated in the DIP). It's pretty clear, unless you can give a 
specific problem faced where this doesn't hold? D is pretty 
strict to ensure rvalues aren't passed to ref's and that's what 
makes this relatively simple to implement without changing 
matching rules.




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Walter Bright via Digitalmars-d-announce

On 1/25/2019 7:44 PM, Manu wrote:

I never said anything about 'rvalue references',


The DIP mentions them several times in the "forum threads" section. I see you 
want to distinguish the DIP from that; I recommend a section clearing that up.


However, my points about the serious problems with @disable syntax remain.

A section comparing with the C++ solution is necessary as well, more than the 
one sentence dismissal. For example, how C++ deals with the:


void foo(const int x);
void foo(const int& x);

situation needs to be understood and compared. Failing to understand it can lead 
to serious oversights. For example, C++ doesn't require an @disable syntax to 
make it work.




[...]
Should `s` be promoted to an int temporary, then pass the temporary by
reference? I can find no guidance in the DIP. What if `s` is a uint (i.e. the
implicit conversion is a type paint and involves no temporary)?

As per the DIP; yes, that is the point.
The text you seek is written: "[...]. The user should not experience
edge cases, or differences in functionality when calling fun(int x) vs
fun(ref int x)."


I don't see how that addresses implicit type conversion at all.



Don't accept naked ref unless you want these semantics. There is a
suite of tools offered to use where this behaviour is undesirable.
Naked `ref` doesn't do anything particularly interesting in the
language today that's not *identical* semantically to using a pointer
and adding a single '&' character at the callsite.


It's not good enough. The DIP needs to specifically address what happens with 
implicit conversions. The reader should not be left wondering about what is 
implied. I often read a spec and think yeah, yeah, of course it must be that 
way. But it is spelled out in the spec, and reading it gives me confidence that 
I'm understanding the semantics, and it gives me confidence that whoever wrote 
the spec understood it.


(Of course, writing out the implications sometimes causes the writer to realize 
he didn't actually understand it at all.)


Furthermore, D has these match levels:

1. exact
2. const
3. conversion
4. no match

If there are two or more matches at the same level, the decision is made based 
on partial ordering. How does adding the new ref/value overloading fit into that?




It should never have gotten this far without giving a precise explanation of how

exception safety is achieved when faced with multiple parameters.

I apologise. I've never used exceptions in any code I've ever written,
so it's pretty easy for me to overlook that detail.


It's so, so easy to get that wrong. C++ benefits from decades of compiler bug 
fixes with that.




Nobody else that did the community reviews flagged it,


That's unfortunately right. Note that 'alias this' was approved and implemented, 
and then multiple serious conceptual problems have appeared with it. I don't 
want a repeat of that.




and that includes you and Andrei, as members of the community.


The idea was that Andrei & I wouldn't get too involved in the DIPs until they 
are vetted by the community. I.e. delegation.




That said, this remains infinitely more important to me than an
rvalue-references DIP. It's been killing me for 10 years, and I'm
personally yet to feel hindered by our lack of rvalue-reference
support.


I look forward to a much improved DIP from you (and anyone else who wishes to 
help you out with the work!).




Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Manu via Digitalmars-d-announce
On Fri, Jan 25, 2019 at 7:44 PM Manu  wrote:
>
> On Fri, Jan 25, 2019 at 4:00 AM Walter Bright via
> Digitalmars-d-announce  wrote:
> >
> > The DIP should not invent its own syntax
>
> I removed it, and replaced it with simpler code (that I think is
> exception-correct) in my prior post here. It's also a super-trivial
> amendment.

Incidentally, the reason I invented a syntax in this DIP, was because
we have no initialisation syntax in D, despite the language clearly
having the ability to initialise values (when they're declared); we
have an amazingly complex and awkward library implementation of
`emplace`, which is pretty embarrassing really.
The fact that I needed to invent a syntax to perform an initialisation
is a very serious problem in its own right.

But forget about that; I removed the need to express initialisation
from the rewrite.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Manu via Digitalmars-d-announce
On Fri, Jan 25, 2019 at 4:00 AM Walter Bright via
Digitalmars-d-announce  wrote:
>
> On 1/24/2019 11:53 PM, Nicholas Wilson wrote:
> > That the conflation of pass by reference to avoid copying and mutation is 
> > not
> > only deliberate but also mitigated by @disable.
>
> The first oddity about @disable is it is attached to the foo(int), not the
> foo(ref int). If I wanted to know if foo(ref int) takes rvalue references,

And right here, I can see our fundamental difference of perspective...

I never said anything about 'rvalue references', and I never meant
anything like that; at least, not in the C++ sense, which you seem to
be alluding to.
In C++, rval references are syntactically distinct and identifiable as
such, for the purposes of implementing move semantics.

If we want to talk about "rvalue references", then we need to be
having a *completely* different conversation.
That said, I'm not sure why you've raised this matter, since it's not
written anywhere in the DIP.

What I'm talking about is "not-rvalue-references accepting rvalues",
which if you want to transpose into C++ terms, is like `const T&`.

> There are indeed
> unlikable things about the C++ rules, but the DIP needs to pay more attention 
> to
> how C++ does this, and justify why D differs. Particularly because D will 
> likely
> have to have some mechanism of ABI compatibility with C++ functions that take
> rvalue references.

I'm not paying attention to C++ T&& rules, because this DIP has
nothing to do with T&&, and there would be no allusion to connecting
this to a T&& method. Again, I find that to be a very interesting
topic of conversation, but it has nothing to do with this DIP.

> [...]
> Should `s` be promoted to an int temporary, then pass the temporary by
> reference? I can find no guidance in the DIP. What if `s` is a uint (i.e. the
> implicit conversion is a type paint and involves no temporary)?

As per the DIP; yes, that is the point.
The text you seek is written: "[...]. The user should not experience
edge cases, or differences in functionality when calling fun(int x) vs
fun(ref int x)."
That text appears at least 2 times through the document as the stated goal.

Don't accept naked ref unless you want these semantics. There is a
suite of tools offered to use where this behaviour is undesirable.
Naked `ref` doesn't do anything particularly interesting in the
language today that's not *identical* semantically to using a pointer
and adding a single '&' character at the callsite. This DIP attempts
to make `ref` interesting and useful as a feature in its own right.
In discussions designing this thing, I've come to appreciate the UFCS
advantages as the most compelling opportunity, among all the other
things that burn me almost practically every time I write D code.

> The DIP should not invent its own syntax

I removed it, and replaced it with simpler code (that I think is
exception-correct) in my prior post here. It's also a super-trivial
amendment.

> It should never have gotten this far without giving a precise explanation of 
> how
exception safety is achieved when faced with multiple parameters.

I apologise. I've never used exceptions in any code I've ever written,
so it's pretty easy for me to overlook that detail.
Nobody else that did the community reviews flagged it, and that
includes you and Andrei, as members of the community.

> All that criticism aside, I'd like to see rvalue references in D. But the DIP
> needs significant work.

This is *NOT* an "rvalue-references" DIP; this is a "references" DIP.
If you want to see an rvalue references DIP, I agree that's a
completely different development, and it's also interesting to me... I
had *absolutely no idea* that an rvalue-references DIP was welcome. I
thought D was somewhat aggressively proud of the fact that we don't
have rvalue-references... apparently I took the wrong impression.

That said, this remains infinitely more important to me than an
rvalue-references DIP. It's been killing me for 10 years, and I'm
personally yet to feel hindered by our lack of rvalue-reference
support.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Manu via Digitalmars-d-announce
On Fri, Jan 25, 2019 at 6:50 PM Neia Neutuladh via
Digitalmars-d-announce  wrote:
>
> On Fri, 25 Jan 2019 18:14:56 -0800, Manu wrote:
> > Removing the `void` stuff end expanding such that the declaration +
> > initialisation is at the appropriate moments; any function can throw
> > normally, and the unwind works naturally?
>
> The contention was that, if the arguments are constructed properly,
> ownership is given to the called function, which is responsible for
> calling destructors.

No, that was never the intent, and certainly not written anywhere.
Ownership is assigned the the calling scope that we introduce
surrounding the statement. That's where the temporaries declared; I
didn't consider that ownership unclear.

> I'm not sure what the point of that was. The called function doesn't own
> its parameters and shouldn't ever call destructors. So now I'm confused.

Correct. You're not confused. The callee does NOT own ref parameters.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Neia Neutuladh via Digitalmars-d-announce
On Fri, 25 Jan 2019 18:14:56 -0800, Manu wrote:
> Removing the `void` stuff end expanding such that the declaration +
> initialisation is at the appropriate moments; any function can throw
> normally, and the unwind works naturally?

The contention was that, if the arguments are constructed properly, 
ownership is given to the called function, which is responsible for 
calling destructors. But if the argument construction fails, the caller is 
responsible for calling destructors.

I'm not sure what the point of that was. The called function doesn't own 
its parameters and shouldn't ever call destructors. So now I'm confused.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Manu via Digitalmars-d-announce
On Fri, Jan 25, 2019 at 4:20 PM Neia Neutuladh via
Digitalmars-d-announce  wrote:
>
> On Fri, 25 Jan 2019 23:08:52 +, kinke wrote:
>
> > On Friday, 25 January 2019 at 19:08:55 UTC, Walter Bright wrote:
> >> On 1/25/2019 2:57 AM, kinke wrote:
> >>> On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote:
>  On 1/24/2019 1:03 PM, kinke wrote:
> > (bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy =
> > b();)) , __gate = true , f(__pfx, __pfy);
> 
>  There must be an individual gate for each of __pfx and pfy.
>  With the rewrite above, if b() throws then _pfx won't be destructed.
> >>>
> >>> There is no individual gate, there's just one to rule the
> >>> caller-destruction of all temporaries.
> >>
> >> What happens, then, when b() throws?
> >
> > `__pfx` goes out of scope, and is dtor expression (cleanup/finally) is
> > run as part of stack unwinding. Rewritten as block statement:
>
> And nested calls are serialized as you'd expect:
>
> int foo(ref S i, ref S j);
> S bar(ref S i, ref S j);
> S someRvalue(int i);
>
> foo(
> bar(someRvalue(1), someRvalue(2)),
> someRvalue(4));
>
> // translates to something like:
> {
> bool __gate1 = false;
> S __tmp1 = void;
> S __tmp2 = void;
> S __tmp3 = void;
> __tmp1 = someRvalue(1);
> try
> {
> __tmp2 = someRvalue(2);
> __gate1 = true;
> __tmp3 = bar(__tmp1, __tmp2);
> }
> finally
> {
> if (!__gate1) __tmp1.__xdtor();
> }
> S __tmp4 = void;
> bool __gate2 = false;
> try
> {
> __tmp4 = someRvalue(4);
> __gate2 = true;
> return foo(__tmp3, __tmp4);
> }
> finally
> {
> if (!__gate2)
> {
> __tmp3.__xdtor();
> }
> }
> }

Is this fine?

Given above example:

int foo(ref S i, ref S j);
S bar(ref S i, ref S j);
S someRvalue(int i);

foo(
bar(someRvalue(1), someRvalue(2)),
someRvalue(4));

===>

{
  S __tmp0 = someRvalue(1);
  S __tmp1 = someRvalue(2);
  S __tmp2 = bar(__tmp0, __tmp1);
  S __tmp3 = someRvalue(4);
  foo(__tmp2, __tmp3);
}

Removing the `void` stuff end expanding such that the declaration +
initialisation is at the appropriate moments; any function can throw
normally, and the unwind works naturally?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Neia Neutuladh via Digitalmars-d-announce
On Fri, 25 Jan 2019 23:08:52 +, kinke wrote:

> On Friday, 25 January 2019 at 19:08:55 UTC, Walter Bright wrote:
>> On 1/25/2019 2:57 AM, kinke wrote:
>>> On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote:
 On 1/24/2019 1:03 PM, kinke wrote:
> (bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy =
> b();)) , __gate = true , f(__pfx, __pfy);

 There must be an individual gate for each of __pfx and pfy.
 With the rewrite above, if b() throws then _pfx won't be destructed.
>>> 
>>> There is no individual gate, there's just one to rule the
>>> caller-destruction of all temporaries.
>>
>> What happens, then, when b() throws?
> 
> `__pfx` goes out of scope, and is dtor expression (cleanup/finally) is
> run as part of stack unwinding. Rewritten as block statement:

And nested calls are serialized as you'd expect:

int foo(ref S i, ref S j);
S bar(ref S i, ref S j);
S someRvalue(int i);

foo(
bar(someRvalue(1), someRvalue(2)),
someRvalue(4));

// translates to something like:
{
bool __gate1 = false;
S __tmp1 = void;
S __tmp2 = void;
S __tmp3 = void;
__tmp1 = someRvalue(1);
try
{
__tmp2 = someRvalue(2);
__gate1 = true;
__tmp3 = bar(__tmp1, __tmp2);
}
finally
{
if (!__gate1) __tmp1.__xdtor();
}
S __tmp4 = void;
bool __gate2 = false;
try
{
__tmp4 = someRvalue(4);
__gate2 = true;
return foo(__tmp3, __tmp4);
}
finally
{
if (!__gate2)
{
__tmp3.__xdtor();
}
}
}


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread kinke via Digitalmars-d-announce

On Friday, 25 January 2019 at 19:08:55 UTC, Walter Bright wrote:

On 1/25/2019 2:57 AM, kinke wrote:
On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright 
wrote:

On 1/24/2019 1:03 PM, kinke wrote:
(bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy = 
b();)) , __gate = true , f(__pfx, __pfy);


There must be an individual gate for each of __pfx and pfy. 
With the rewrite above, if b() throws then _pfx won't be 
destructed.


There is no individual gate, there's just one to rule the 
caller-destruction of all temporaries.


What happens, then, when b() throws?


`__pfx` goes out of scope, and is dtor expression 
(cleanup/finally) is run as part of stack unwinding. Rewritten as 
block statement:


{
  bool __gate = false;
  A __pfx = a();
  try {
B __pfy = b(); // may throw
__gate = true;
return f(__pfx, __pfy); // move args to callee
  } finally {
__gate || __pfx.__xdtor(); // only destruct if not moved to 
callee

  }
}

With this DIP, the g() call (both rvalue args passed by ref) 
would now become:


{
  A __pfx = a();
  try {
B __pfy = b(); // may throw
try {
  return g(__pfx, __pfy); // pass by ref
} finally {
  __pfy.__xdtor(); // always destructed by caller
}
  } finally {
__pfx.__xdtor();
  }
}


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread rikki cattermole via Digitalmars-d-announce

On 26/01/2019 10:00 AM, Rubn wrote:

On Friday, 25 January 2019 at 11:56:58 UTC, Walter Bright wrote:

On 1/24/2019 11:53 PM, Nicholas Wilson wrote:
That the conflation of pass by reference to avoid copying and 
mutation is not only deliberate but also mitigated by @disable.


The first oddity about @disable is it is attached to the foo(int), not 
the foo(ref int). If I wanted to know if foo(ref int) takes rvalue 
references, I'd have to go looking for the existence of another 
function. This is one of those cases where it's hard to prove a 
negative, as other functions can be introduced by mixins. This is a 
strong usability negative.


Next, the @disable applies to the entire parameter list. However, 
overload selection is done by looking at each parameter. The DIP says:


"The DIP author responded that ideas to improve this are welcome, but 
that he cannot imagine a use case."


I can guarantee that the use case of more than one reference parameter 
will come up. The workarounds the DIP suggests are simply awful.


Let's look at what C++ does for rvalue references:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html

The syntax is attached to the parameter declaration of the function it 
applies to, not some other function, and not every parameter:


    int foo(T&& t);  // C++ rvalue ref

There are no weird workarounds, at least for that aspect. There are 
indeed unlikable things about the C++ rules, but the DIP needs to pay 
more attention to how C++ does this, and justify why D differs. 
Particularly because D will likely have to have some mechanism of ABI 
compatibility with C++ functions that take rvalue references.


This is not a small problem.

A further problem is implicit conversions, which the DIP ignores by 
only talking about ints.


    void bar(int);
    void foo(ref int);
    enum short s = 10;
    bar(s); // compiles
    foo(s); // currently fails to compile

Should `s` be promoted to an int temporary, then pass the temporary by 
reference? I can find no guidance in the DIP. What if `s` is a uint 
(i.e. the implicit conversion is a type paint and involves no temporary)?


Here's a discussion of Rust and rvalue references which may offer 
insight:


https://www.reddit.com/r/rust/comments/3ko5pm/explaining_cs_rvalue_references_from_a_rust/ 





That the DIP applies to statements, not expressions.


The DIP should not invent its own syntax, give no explanation of it, 
and have the reader guess. (It did explain the :=, but not the use of 
{ } and statements.) And, even if one did a mental rewrite, the 
semantics of the statement version are simply wrong. (For example, if 
'fun' was actually a function pointer returned by another function, 
and that other function threw an exception - then the destructor would 
be run on an uninitialized variable.)



That the construction order issue is trivially fixable, by specifying 
the same behaviour as the non ref case modulo ref.


It should never have gotten this far without giving a precise 
explanation of how exception safety is achieved when faced with 
multiple parameters. In the past I've done a lot of work on exception 
safety, and it isn't trivial once one goes beyond trivial cases.


All that criticism aside, I'd like to see rvalue references in D. But 
the DIP needs significant work.


For future reference, this is what a formal review should be. I'd also 
rather your exact words than some summarization of them.


So in other words, a formal review should include somebody acting as an 
'interviewer' prompting questions. If that is the case, I do think it 
would be a good idea.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Rubn via Digitalmars-d-announce

On Friday, 25 January 2019 at 11:56:58 UTC, Walter Bright wrote:

On 1/24/2019 11:53 PM, Nicholas Wilson wrote:
That the conflation of pass by reference to avoid copying and 
mutation is not only deliberate but also mitigated by @disable.


The first oddity about @disable is it is attached to the 
foo(int), not the foo(ref int). If I wanted to know if foo(ref 
int) takes rvalue references, I'd have to go looking for the 
existence of another function. This is one of those cases where 
it's hard to prove a negative, as other functions can be 
introduced by mixins. This is a strong usability negative.


Next, the @disable applies to the entire parameter list. 
However, overload selection is done by looking at each 
parameter. The DIP says:


"The DIP author responded that ideas to improve this are 
welcome, but that he cannot imagine a use case."


I can guarantee that the use case of more than one reference 
parameter will come up. The workarounds the DIP suggests are 
simply awful.


Let's look at what C++ does for rvalue references:


http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html


The syntax is attached to the parameter declaration of the 
function it applies to, not some other function, and not every 
parameter:


int foo(T&& t);  // C++ rvalue ref

There are no weird workarounds, at least for that aspect. There 
are indeed unlikable things about the C++ rules, but the DIP 
needs to pay more attention to how C++ does this, and justify 
why D differs. Particularly because D will likely have to have 
some mechanism of ABI compatibility with C++ functions that 
take rvalue references.


This is not a small problem.

A further problem is implicit conversions, which the DIP 
ignores by only talking about ints.


void bar(int);
void foo(ref int);
enum short s = 10;
bar(s); // compiles
foo(s); // currently fails to compile

Should `s` be promoted to an int temporary, then pass the 
temporary by reference? I can find no guidance in the DIP. What 
if `s` is a uint (i.e. the implicit conversion is a type paint 
and involves no temporary)?


Here's a discussion of Rust and rvalue references which may 
offer insight:


https://www.reddit.com/r/rust/comments/3ko5pm/explaining_cs_rvalue_references_from_a_rust/



That the DIP applies to statements, not expressions.


The DIP should not invent its own syntax, give no explanation 
of it, and have the reader guess. (It did explain the :=, but 
not the use of { } and statements.) And, even if one did a 
mental rewrite, the semantics of the statement version are 
simply wrong. (For example, if 'fun' was actually a function 
pointer returned by another function, and that other function 
threw an exception - then the destructor would be run on an 
uninitialized variable.)



That the construction order issue is trivially fixable, by 
specifying the same behaviour as the non ref case modulo ref.


It should never have gotten this far without giving a precise 
explanation of how exception safety is achieved when faced with 
multiple parameters. In the past I've done a lot of work on 
exception safety, and it isn't trivial once one goes beyond 
trivial cases.


All that criticism aside, I'd like to see rvalue references in 
D. But the DIP needs significant work.


For future reference, this is what a formal review should be. I'd 
also rather your exact words than some summarization of them.


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Walter Bright via Digitalmars-d-announce

On 1/25/2019 2:57 AM, kinke wrote:

On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote:

On 1/24/2019 1:03 PM, kinke wrote:
(bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy = b();)) , __gate = 
true , f(__pfx, __pfy);


There must be an individual gate for each of __pfx and pfy. With the rewrite 
above, if b() throws then _pfx won't be destructed.


There is no individual gate, there's just one to rule the caller-destruction of 
all temporaries.


What happens, then, when b() throws?


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/25/19 5:57 AM, kinke wrote:

On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote:

On 1/24/2019 1:03 PM, kinke wrote:
(bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy = b();)) , 
__gate = true , f(__pfx, __pfy);


There must be an individual gate for each of __pfx and pfy. With the 
rewrite above, if b() throws then _pfx won't be destructed.


There is no individual gate, there's just one to rule the 
caller-destruction of all temporaries. That's the current state, and 
there's no need for that to change. I was trying to say that a rewrite 
as expression, as requested as part of the assessment, clearly isn't 
enough, as the dtor expressions aren't visible this way, and neither is 
the scoping (when the dtor expression of `__pfx` comes into play etc.).


I think the point of the DIP is not to lower expressions. It makes no 
sense to, they have to be statements (just like all temporaries live 
until the end of a statement).


-Steve


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Olivier FAURE via Digitalmars-d-announce

On Friday, 25 January 2019 at 11:56:58 UTC, Walter Bright wrote:
All that criticism aside, I'd like to see rvalue references in 
D. But the DIP needs significant work.


I haven't participated to writing this DIP, but I personally 
appreciate this level of feedback.


I think it would have been more appreciated if the original 
answer had that level of detail.


Otherwise, I don't think this should be an all-or-nothing 
situation. It would make sense to bump the DIP back one stage or 
two for minor adjustments, and if the author decide that they 
need to make major changes to get past the problems you mention, 
require these changes to go through the entire process again 
(through another DIP).


Re: DIP 1016--ref T accepts r-values--Formal Assessment

2019-01-25 Thread Nicholas Wilson via Digitalmars-d-announce

On Friday, 25 January 2019 at 12:03:36 UTC, Nicholas Wilson wrote:

On Friday, 25 January 2019 at 11:56:58 UTC, Walter Bright wrote:
It should never have gotten this far without giving a precise 
explanation of how exception safety is achieved when faced 
with multiple parameters.


The pot calling the kettle black. DIP1000? DIP1017?


Or DIP1008: https://issues.dlang.org/show_bug.cgi?id=19463



  1   2   >