April 04, 2013
2013/4/5 Namespace <rswhite4@googlemail.com>

> Hmm, I don't know if I could write a long and good text for the DIP. My
> english is very limited and not free of failures.
> I still had hoped that Kenji or some other find the time, to see over my
> code and to make a DIP/Pull Request.
>

Timely guess. I roughly implemented it in my experimental branch.

https://github.com/9rnsr/dmd/commits/new_inref

I need more cleanup for it, but it would work as we expected.

Kenji Hara


April 04, 2013
On Thursday, 4 April 2013 at 16:21:50 UTC, Namespace wrote:
>> I don't know. My opinion has no value here.
> I know. But I wanted to hear just your personal opinion about the code and if you have any suggestions or anything.
>
>> I may advice to write a DIP that makes more accent on theoretical side of problem - what "scope" currently is, how it combines with ref now, how it should combine, how Andrei's DIP fits in the picture, how it fits overall type system, what are possible code breakage scenarios, what are typical use cases for this feature etc. If such DIP and matching pull request do exist, it is only matter of agreement (with Andrei/Walter) about points stated in DIP.
>
> Hmm, I don't know if I could write a long and good text for the DIP. My english is very limited and not free of failures.
> I still had hoped that Kenji or some other find the time, to see over my code and to make a DIP/Pull Request.

Well, I doubt there are that many native speakers here which will be shocked by bad English :) But if you gather all data mentioned (see also Kenji's comment), I can write DIP itself for you. Type system changes should be studied in smallest details as those have have very long term consequences and incredibly hard to replace with better solutions later.
April 04, 2013
> Well, I doubt there are that many native speakers here which will be shocked by bad English :) But if you gather all data mentioned (see also Kenji's comment), I can write DIP itself for you. Type system changes should be studied in smallest details as those have have very long term consequences and incredibly hard to replace with better solutions later.

That sounds good. Then I will try over the weekend to collect all the necessary data and post them here. Then you can take a quick look, whether you have enough information or if I need a little late filing.
April 04, 2013
On Thursday, 4 April 2013 at 16:31:06 UTC, kenji hara wrote:
> 2013/4/5 Namespace <rswhite4@googlemail.com>
>
>> Hmm, I don't know if I could write a long and good text for the DIP. My
>> english is very limited and not free of failures.
>> I still had hoped that Kenji or some other find the time, to see over my
>> code and to make a DIP/Pull Request.
>>
>
> Timely guess. I roughly implemented it in my experimental branch.
>
> https://github.com/9rnsr/dmd/commits/new_inref
>
> I need more cleanup for it, but it would work as we expected.
>
> Kenji Hara

That works well. Thanks for your efforts.
April 05, 2013
On Thursday, 4 April 2013 at 07:52:51 UTC, Dicebot wrote:
> After some thinking on topic I come to conclusion that rvalue refs _should_ be "scope ref" and stuff like "ref int f(@temp ref int x) { return x; }" is invalid. I can see no valid use case for such an error-prone case.

Perhaps they should, but at least I will give the use case I was thinking of.

If you've got a large struct, you don't want to pass it by value. Say you've got two functions which process and return a Large, and they accept rvalue refs. It might not be too much to ask that a Large always be an lvalue, but let's say you want to pass it directly by value for some reason.

struct Large { ... }
ref Large process1(@temp ref Large a) { return a; }
ref Large process2(@temp ref Large a) { return a; }

Large* lar = &process2(process1(Large("Pass"," a ", "Large", "here")));

The use case would allow this to work. And with the kind of error checking suggested in DIP25, this kind of construction would not actually be error prone. 'lar' would be understood as locally derived and could not escape the function it was defined in.

But to speak to your point, this kind of single expression chaining of ref functions might be so rare that there's no great reason to allow it in tandem with rvalues.
April 05, 2013
On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
> I can tell some reasonable points about 'scope ref'.
> - 'in ref' has been allowed from 2.060 (
> http://d.puremagic.com/issues/show_bug.cgi?id=8105)
> - 'scope ref' is still disallowed. ("Error: scope cannot be ref or out")
> - 'scope' means "the reference cannot escape from local scope".
>   And an rvalue reference cannot escape from passed function. There is
> consistent semantics.
> - 'in' is equivalent to 'const scope' ( http://dlang.org/function.html
> )<http://dlang.org/function.html>
>   So, 'in ref' is equivalent to 'const scope ref'.
> - Currently 'scope' affects to delegate parameter. In other cases, 'scope'
> has no meaning.
>
> I recognize that Jonathan had opposed to 'in ref' because it had supported
> just only "const rvalue reference" (like 'cosnt T&' in C++). In D, 'const'
> means physical const, so he has thought that mutable rvalue reference
> should be supported in D.
>
> So, I think 'scope ref' is good proposal against the Jonathan's objection.
>
> Kenji Hara

My argument would be that 'scope ref' and '@temp ref' are two different horns of the same devil, really. The problem with '@temp ref' is that it's "syntax creep", adding a new storage class for limited reward. But 'scope ref' is equally problematic, because if it *does* allow returning the parameter by reference it will be deceptively different from simply what 'scope' would do. So the syntax creep would be replaced by the confusing nature of 'ref', 'scope', and 'scope ref':

ref int func(ref int a) { return a; } // Okay

ref int func2(scope int a) {
  return *new int;
  //return a; // No good, error: a is 'scope'
}

// Okay: 'scope ref' means something different from 'scope'
ref int func3(scope ref int a) { return a; }

ref int testFuncs(ref int y) {
  int x;
  return func(x); // Error: ref return assumed local as x
  return func(y); // Okay: y is from outside and returnable
  return func2(x); // Okay: 'scope' ensures x not returned
  return func2(y); // Okay
  return func3(x); // Error: ref return assumed local as x
  return func3(y); // Okay: y outside
  return func3(53); // Error: temp 53 is local
}

If 'scope' were defined as above, 'scope ref' could not be used to say that you *also* want the parameter to be 'scope' in addition to 'scope ref'. This leads into the remaining issue with DIP25, which is that 'scope' would be useful to tell the calling function that the passed-in variable will not be 'ref' returned, as in func2() above. DIP25 may want 'scope' to help add flexibility to what may or may not be returned.

Dicebot's suggestion, that ref int func3(scope ref int a) {} above be banned from returning 'a', would solve this problem. In this case 'scope ref' would mean both 'scope' *and* '@temp ref'. It does however conflate the two features, making it impossible to return an rvalue ref parameter by ref.

It may be that the cases where you actually *want* to return an rvalue ref parameter by reference are so rare that no one will miss that you can't do it. Or, conversely, it may be so rare that you want to specify 'scope' on your parameter in addition to 'scope ref' that no one will miss not being able to do that either. But one of these solutions must be accepted is 'scope ref' is to mean what is suggested.

The other horn of the devil is to swallow the distasteful pill and allow '@temp ref', 'ref&', or some other "syntax creep".
April 05, 2013
On Friday, 5 April 2013 at 00:12:33 UTC, Zach the Mystic wrote:
> struct Large { ... }
> ref Large process1(@temp ref Large a) { return a; }
> ref Large process2(@temp ref Large a) { return a; }
>
> Large* lar = &process2(process1(Large("Pass"," a ", "Large", "here")));

This is exactly type of code I consider to be bad style and want to see banned. Function that gets rvalue ref should never return it as it knows nothing about its lifetime. Actually, I can't even find scope definition for temporaries in dlang.org, but it is hardly a good thing to rely on anyway. Best is to assume that when function is gone, so is rvalue temporary.

Your code begs for using plain refs and storing Large in a stack variable before calling function chain. May look a bit less convenient but much more reliable and understandable.
April 05, 2013
On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
> I also think writing DIP would be better.
> ...

Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs.

Will make "in" also much more meaningful as a separate entity.
April 05, 2013
On Friday, 5 April 2013 at 07:48:38 UTC, Dicebot wrote:
> On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
>> I also think writing DIP would be better.
>> ...
>
> Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs.
>
> Will make "in" also much more meaningful as a separate entity.

To change "in" from "const scope" to "const scope ref" is IMO a bad idea. It will break code and it's not intuitive.
In my opinion we should use "ref" in combination with something else (in this case "scope").
But that is my personal opinion.
April 05, 2013
On Friday, 5 April 2013 at 08:35:03 UTC, Namespace wrote:
> On Friday, 5 April 2013 at 07:48:38 UTC, Dicebot wrote:
>> On Thursday, 4 April 2013 at 16:25:52 UTC, kenji hara wrote:
>>> I also think writing DIP would be better.
>>> ...
>>
>> Btw, Kenji, what do you think about redefining "in" to "const scope ref" and allowing compiler to chose how variable exactly is passed ("auto ref" with no template bloat)? Within those restrictions plain values should be indistinguishable from const rvalue refs.
>>
>> Will make "in" also much more meaningful as a separate entity.
>
> To change "in" from "const scope" to "const scope ref" is IMO a bad idea. It will break code and it's not intuitive.
> In my opinion we should use "ref" in combination with something else (in this case "scope").
> But that is my personal opinion.

How so? It does not break anything, as all "const scope" cases can be processed with "const scope ref", in fact, compiler should be allowed to degrade first to latter. Regarding meaning - if "scope ref" means permissive rvalues (mutable ones), then "const scope ref" means closer match for C++ "const &" - constant references that can't escape scope. I actually have an impression you do really want exactly "const scope ref" considering frequent references to C++.

Tricky part as far as I can see is ABI - one needs to be able to accept both value and ref parameters within same function signature. Possible but may be too hacky to implement.