May 04, 2013
On 5/4/2013 2:22 PM, deadalnix wrote:
> I still think this is inferior to Rust's solution and like to see ref as a
> equivalent of the Rust burrowed pointer. It achieve the same safety at compile
> time instead at runtime, and incurs no extra complexity except in some very rare
> cases (when you have a function taking several arguments by ref and returning
> also by ref and the lifetime of the returned ref isn't the union of the lifetime
> of the ref parameters - a very specific case).

As you say, D ref's are analogous to Rust's borrowed pointers, and for the escaping ref problem, Rust requires additional annotations (much like the 'scope ref' proposal).

http://static.rust-lang.org/doc/tutorial-borrowed-ptr.html#returning-borrowed-pointers

The runtime check is because Andrei & I really didn't like requiring additional annotations.

May 04, 2013
On Saturday, 4 May 2013 at 21:48:25 UTC, Walter Bright wrote:
> On 5/4/2013 2:22 PM, deadalnix wrote:
>> I still think this is inferior to Rust's solution and like to see ref as a
>> equivalent of the Rust burrowed pointer. It achieve the same safety at compile
>> time instead at runtime, and incurs no extra complexity except in some very rare
>> cases (when you have a function taking several arguments by ref and returning
>> also by ref and the lifetime of the returned ref isn't the union of the lifetime
>> of the ref parameters - a very specific case).
>
> As you say, D ref's are analogous to Rust's borrowed pointers, and for the escaping ref problem, Rust requires additional annotations (much like the 'scope ref' proposal).
>
> http://static.rust-lang.org/doc/tutorial-borrowed-ptr.html#returning-borrowed-pointers
>
> The runtime check is because Andrei & I really didn't like requiring additional annotations.

Where you miss the point, is that these annotations may be omitted (and they are most of the time). When nothing is specified, the lifetime of the returned reference is considered to be the union of the lifetime of parameters lifetime, which is what you want in 99% of cases.
May 04, 2013
On Saturday, 4 May 2013 at 21:57:14 UTC, deadalnix wrote:
> On Saturday, 4 May 2013 at 21:48:25 UTC, Walter Bright wrote:
>> On 5/4/2013 2:22 PM, deadalnix wrote:
>>> I still think this is inferior to Rust's solution and like to see ref as a
>>> equivalent of the Rust burrowed pointer. It achieve the same safety at compile
>>> time instead at runtime, and incurs no extra complexity except in some very rare
>>> cases (when you have a function taking several arguments by ref and returning
>>> also by ref and the lifetime of the returned ref isn't the union of the lifetime
>>> of the ref parameters - a very specific case).
>>
>> As you say, D ref's are analogous to Rust's borrowed pointers, and for the escaping ref problem, Rust requires additional annotations (much like the 'scope ref' proposal).
>>
>> http://static.rust-lang.org/doc/tutorial-borrowed-ptr.html#returning-borrowed-pointers
>>
>> The runtime check is because Andrei & I really didn't like requiring additional annotations.
>
> Where you miss the point, is that these annotations may be omitted (and they are most of the time). When nothing is specified, the lifetime of the returned reference is considered to be the union of the lifetime of parameters lifetime, which is what you want in 99% of cases.

Note : We may also choose the lack of explicit lifetime means runtime check as proposed, instead of being an error.
May 04, 2013
On 5/4/2013 3:03 PM, deadalnix wrote:
>> Where you miss the point, is that these annotations may be omitted (and they
>> are most of the time). When nothing is specified, the lifetime of the returned
>> reference is considered to be the union of the lifetime of parameters
>> lifetime, which is what you want in 99% of cases.
>
> Note : We may also choose the lack of explicit lifetime means runtime check as
> proposed, instead of being an error.

D omits the check when it can prove that the returned ref is not a ref to one of the parameters that is local.

My other comments about 'scope ref' in the first posting in this thread apply as well to the Rust annotation scheme.
May 04, 2013
To put it another way, we wish to solve the problem without introducing more annotations. Rust's solution requires additional annotations, and so is not what we're looking for.
May 04, 2013
On Saturday, 4 May 2013 at 22:33:58 UTC, Walter Bright wrote:
> To put it another way, we wish to solve the problem without introducing more annotations. Rust's solution requires additional annotations, and so is not what we're looking for.

Require isn't the right word, or you hav to explain yourself much more.

For instance, see : http://smallcultfollowing.com/babysteps/blog/2012/07/19/yet-another-tutorial-on-borrowed-pointers/

"So far we have always used the notation &T for a borrowed pointer. However, sometimes if a function takes many parameters, it is useful to be able to group those parameters by lifetime."

In other terms, you need to have several parameters that passes by ref + return by ref + you want a different lifetime for your returned value than union of parameters's lifetime.

Which is a very specific case. That is far away from require. That is most case don't require anything, while 1% require an explicit lifetime. Unless you do some goofy stuff, you don't even need to know about it. And if we decide that no explicit lifetime == runtime check, it is never ever required. Just provided for the dev that want to have the runtime check removed.

If we get more actual, return by ref in D are mostly usefull for collections and ranges. None of theses would require explicit lifetime ever.
May 04, 2013
> These checks would be omitted if the -noboundscheck compiler switch was provided.

This reminds me of Tony Hoare's lecture on null references being a "billion dollar mistake." He mentioned that he asked his Algol customers if they wanted the option to disable array bounds checking, and they all said no. I like this solution, and I will personally never ever turn that safety off.

Diggory asked this same question already. Does all of this also mean that a function with a ref parameter will automagically work with r-values? My one and only attempt at a Phobos pull request thus far will be mostly obsolete if this is the case. (Which is a good thing.)
May 04, 2013
On 5/4/13, Walter Bright <newshound2@digitalmars.com> wrote:
> Andrei & I argued that we needed to make it work with just ref annotations.

So to recap, 2.063 turns slices into r-values which will break code that used ref, e.g.:

-----
void parse(ref int[] arr) { }

void main()
{
    int[] arr = [1, 2];
    parse(arr[]);  // ok in 2.062, error in 2.063
}
-----

Then the user might introduce a non-ref overload:

-----
void parse(ref int[] arr) { }
void parse(int[] arr) { }  // picks this one
-----

And later down the road, maybe even in 2.064, ref will take r-values making the new code error because of ambiguity between the two functions.

Has code breakage ever been taken into account during this dconf conversation?

I doubt a short verbal conversation can solve design problems or take into account all edge-cases, this is why we have the web where we can document all code samples and the flaws of some design spec.

This "resolution" should be a DIP that goes through a review just like all the other DIPs, otherwise DIPs are pointless if they get overruled by some behind-the-scenes conversation.
May 04, 2013
On 5/4/2013 3:50 PM, deadalnix wrote:
> Require isn't the right word, or you hav to explain yourself much more.

You need an explicit annotation if a ref parameter is returned by ref by that function. This is what Rust's annotations do.

Consider:

    ref T foob(ref U u) { return u.t; }

    ref U bar() { U u; return foob(u); }

The compiler cannot know that the ref return of foob is referring to local u (as opposed to, say, a ref to a global) unless it is annotated to say so. Rust is no different.
May 04, 2013
On 5/4/2013 3:51 PM, w0rp wrote:
> Does all of this also mean that a
> function with a ref parameter will automagically work with r-values?

Yes.