January 18, 2016
On Monday, 18 January 2016 at 19:32:19 UTC, bitwise wrote:
> struct S;
>
> void func(ref S s);
> func(S());   // FINE
>
> void func(ref S s) @safe;
> func(S());   // ERROR

Isn't that backwards? I mean, @safe functions can't escape their parameters, so whether or not it is a temporary shouldn't matter to a @safe function. Meanwhile, non-@safe *can* escape parameters, and would fail or at least lead to problems if it tried to escape a ref to a temporary.

On the other hand, banning @safe code from passing a temporary as a ref parameter, while allowing it in non-@safe code makes a bit more sense to me, but seems less desirable.
January 19, 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:
> [...]

https://github.com/D-Programming-Language/phobos/pull/3937
January 19, 2016
On Tuesday, 19 January 2016 at 00:11:45 UTC, tsbockman wrote:
> On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:
>> [...]
>
> https://github.com/D-Programming-Language/phobos/pull/3937

Is this like...a sarcastic pull request?

You can't actually expect people to write code like this just to have their functions take rvalues..

    Bit

January 19, 2016
On Monday, 18 January 2016 at 21:39:09 UTC, Anon wrote:
> On Monday, 18 January 2016 at 19:32:19 UTC, bitwise wrote:
>> struct S;
>>
>> void func(ref S s);
>> func(S());   // FINE
>>
>> void func(ref S s) @safe;
>> func(S());   // ERROR
>
> Isn't that backwards? I mean, @safe functions can't escape their parameters, so whether or not it is a temporary shouldn't matter to a @safe function. Meanwhile, non-@safe *can* escape parameters, and would fail or at least lead to problems if it tried to escape a ref to a temporary.
>
> On the other hand, banning @safe code from passing a temporary as a ref parameter, while allowing it in non-@safe code makes a bit more sense to me, but seems less desirable.

It turns out, you're right, but this only makes arguments against passing rvalues to ref params even _less_ valid.

You could simply allow rvalue->ref implicit instantiation right now, and @safe code would still be @safe, and unsafe code would be more convenient.

@safety seems like a very specific concern. Many people just won't need that kind of guarantee. Some will be perfectly happy ensuring the safety of their own code, while others simply won't care if their code is totally safe because they're writing low risk or very simple software.

    Bit

January 19, 2016
On Tuesday, 19 January 2016 at 03:01:55 UTC, bitwise wrote:
> On Tuesday, 19 January 2016 at 00:11:45 UTC, tsbockman wrote:
>> On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:
>>> [...]
>>
>> https://github.com/D-Programming-Language/phobos/pull/3937
>
> Is this like...a sarcastic pull request?
>
> You can't actually expect people to write code like this just to have their functions take rvalues..
>
>     Bit

It's ten times easier to write code that way, than the way Manu complained about in the OP.

Manu's been trying to convince Walter to allow a compiler fix through for over six years (https://github.com/D-Programming-Language/dmd/pull/4717#issuecomment-116182064); it's not working.

If you want to, you can just sit there making nasty comments because it's not an ideal solution. But, my pull request is something practical that can make things easier for people who just want to write computer programs.

I expect this will be much easier to actually get merged, and I'll be happy to see it deprecated whenever `scope` finally gets implemented.
January 19, 2016
On Tuesday, 19 January 2016 at 03:37:17 UTC, tsbockman wrote:
> It's ten times easier to write code that way, than the way Manu complained about in the OP.

To clarify:

1) If `scope` were implemented, Manu's example would look like this:
    // Declaration
    void func(in CustomString s1, in CustomString s2);

    // Whenever rvalues need to be passed:
    func("hello", "world");

2) With my PR, it looks like this:
    // Declaration
    private void funcImpl(ref const(CustomString) s1, ref const(CustomString) s2);
    mixin acceptRVals!("func", funcImpl);

    // Whenever rvalues need to be passed:
    func("hello", "world");

3) Currently, we have this:
    // Declaration
    void func(ref const(CustomString) s1, ref const(CustomString) s2);

    // Whenever rvalues need to be passed;
    auto temp1 = "hello";
    auto temp2 = "world";
    func(temp1, temp2);

If A is the number of such functions, B is the number of `ref` arguments per function, and C is the number of calls where rvalues should be passed:

(2) Requires A more statements than (1).
(3) Requires B*C more statements than (1).

Obviously there is little reason to complain about any of this unless B >= 1 and C > A, so unless I'm missing something, my PR is a large improvement over the status quo.
January 19, 2016
On Tuesday, 19 January 2016 at 04:27:12 UTC, tsbockman wrote:
> On Tuesday, 19 January 2016 at 03:37:17 UTC, tsbockman wrote:
>> It's ten times easier to write code that way, than the way Manu complained about in the OP.
>
> To clarify:
>
> 1) If `scope` were implemented, Manu's example would look like this:
>     // Declaration
>     void func(in CustomString s1, in CustomString s2);
>
>     // Whenever rvalues need to be passed:
>     func("hello", "world");
>
> 2) With my PR, it looks like this:
>     // Declaration
>     private void funcImpl(ref const(CustomString) s1, ref const(CustomString) s2);
>     mixin acceptRVals!("func", funcImpl);
>
>     // Whenever rvalues need to be passed:
>     func("hello", "world");
>
> 3) Currently, we have this:
>     // Declaration
>     void func(ref const(CustomString) s1, ref const(CustomString) s2);
>
>     // Whenever rvalues need to be passed;
>     auto temp1 = "hello";
>     auto temp2 = "world";
>     func(temp1, temp2);
>
> If A is the number of such functions, B is the number of `ref` arguments per function, and C is the number of calls where rvalues should be passed:
>
> (2) Requires A more statements than (1).
> (3) Requires B*C more statements than (1).
>
> Obviously there is little reason to complain about any of this unless B >= 1 and C > A, so unless I'm missing something, my PR is a large improvement over the status quo.

Sorry if that seemed mean, but it wasn't meant to be insulting. But while your solution is clever, I find it totally unrealistic.

Why would anyone use it when they can just templatize their function and get exactly the same thing?

struct S{}

void foo(ref const(S) s) {}
becomes
void foo()(auto ref const(S) s) {}

Not to mention the fact that people's first reaction to D's ref params not taking rvalues isn't going to be to look in the standard library.

Finally, this situation simply should not be this complicated. A ref param should accept an rvalue. @safety is a specific concern, and unless I'm annotating my code with @safe, I should be able to write it however I want(within reason).

To quote a famous author: "Sometimes, an entire community can miss a point".

This is one of those points.

Most of my reaction is to the fact that this is actually a problem. Sorry I offended you.

    Bit

January 19, 2016
On Tuesday, 19 January 2016 at 05:43:57 UTC, bitwise wrote:
> Sorry if that seemed mean, but it wasn't meant to be insulting. But while your solution is clever, I find it totally unrealistic.
>
> Why would anyone use it when they can just templatize their function and get exactly the same thing?
>
> struct S{}
>
> void foo(ref const(S) s) {}
> becomes
> void foo()(auto ref const(S) s) {}

That has fundamentally different semantics from my PR, and does not solve Manu's problem at all. For example, this:

int foo()(auto ref int x) {
    return x + 1;
}

Is actually a template with two possible instantiations (that's why `auto ref` is disallowed on non-template functions):

// lvalues are passed by reference:
int foo(ref int x) {
   return x + 1;
}

// rvalues are passed by value:
int foo(int x) {
    return x + 1;
}

There are several problems with this:

1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.

2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`.

3) `auto ref` CANNOT be used on an extern(C++) function, because the rvalue calls won't link!

By marking the wrapper `pragma(inline, true)` and forwarding everything to the all `ref` version of the function, my PR mostly solves (1), and entirely solves (2) and (3).

> Not to mention the fact that people's first reaction to D's ref params not taking rvalues isn't going to be to look in the standard library.
>
> Finally, this situation simply should not be this complicated. A ref param should accept an rvalue. @safety is a specific concern, and unless I'm annotating my code with @safe, I should be able to write it however I want(within reason).
>
> To quote a famous author: "Sometimes, an entire community can miss a point".
>
> This is one of those points.
>
> Most of my reaction is to the fact that this is actually a problem. Sorry I offended you.
>
>     Bit

I understand, but please don't take it out on me. I have no more control over what gets into the compiler than you do.
January 19, 2016
On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:
> 1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.

Oops - I was being a little dyslexic here. It's actually much worse than that: not N^2, but 2^N.
January 19, 2016
On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:
> On Tuesday, 19 January 2016 at 05:43:57 UTC, bitwise wrote:
>> [..]
>
> There are several problems with this:
>
> 1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.

Your solution suffers from exactly the same problem. It still uses auto ref.

> 2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`.

No, they won't. Temporaries will be created for rvalues, and lvalues will be passed by ref.

> 3) `auto ref` CANNOT be used on an extern(C++) function, because the rvalue calls won't link!

This is the _one_ advantage that your solution actually has over simply templatizing the function.

You are still missing the point though. This shouldn't even be a problem in the first place. It's faulty language design. This limitation makes no sense, and should be removed. There is no argument anyone can make that isn't totally broken.

Having ref params not take rvalues doesn't make the language any safer or more intuitive at all.

If rvalues were allowed to be passed to ref params, the temporaries would be constructed on the stack right before the function call. It's already possible to have variables on the stack and pass them to ref params. There is no difference.

In terms of conveying intention to the caller, just make the param const and you're done.

Finally, for a language that is nearly 1:1 compatible with C++ in many areas, people will expect familiar semantics. There is no real reason to deviate here. At the very least, extern(C++) functions with ref params could take rvalues.

   Bit