August 12, 2016
On 10.08.2016 22:36, Dicebot wrote:
> http://forum.dlang.org/post/pqsiqmkxenrwxoruzaml@forum.dlang.org
>
> The first DIP has just landed into the new queue. It is a proposal from
> language authors and thus it bypasses usual nitpicking process and
> proceeds straight to requesting community (your!) feedback.
>
> Essentially, it is an attempt to solve reference lifetime problem by
> extending implementation of `scope` keyword.
>
> Proposal text: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md

This proposes to add a kind of information the type system is supposed to track (lifetimes), which cannot be communicated losslessly across function and aggregate boundaries. Hence it won't work well in its current form.
August 12, 2016
On 11.08.2016 12:13, Walter Bright wrote:
> On 8/11/2016 3:00 AM, deadalnix wrote:
>> This DIP is flawed because it only handle on
>> indirection level and break down for anything more than this.
>
> It actually does two levels - the address of the pointer variable
> ('ref') and the contents of the pointer variable ('scope'). But you are
> essentially correct. This is not a general annotation system for any
> pointer in a non-trivial graph of pointers. There is no notion of
> 'borrowing'.
>
> The question, however, is whether such a system is needed. The intent
> with this DIP is for people constructing such graphs to make them safe
> by using reference counted containers for the nodes rather than networks
> of annotated raw pointers.
>
> This scheme is good enough to prevent the escape of addresses on the
> stack, and for containers to prevent the escape of pointers to their
> contents.

Assuming all the soundness issues are fixed, I think the general scheme it is not expressive enough. E.g. it does not allow lazy range algorithms from std.algorithm and std.range to be used on a slice of stack-allocated data. The selling points of a language are not real selling points if they are mutually exclusive.
August 12, 2016
On 8/12/2016 12:45 PM, Timon Gehr wrote:
> Assuming all the soundness issues are fixed, I think the general scheme it is
> not expressive enough.

Possibly true, but general expressivity comes at a large cost in complexity and difficulty for users.


> E.g. it does not allow lazy range algorithms from
> std.algorithm and std.range to be used on a slice of stack-allocated data.

If that does turn out to be a problem, lazy algorithms can detect it (because they won't compile) and use an eager version for such cases.
August 12, 2016
On 8/11/2016 1:53 AM, John Colvin wrote:
> On Thursday, 11 August 2016 at 08:45:38 UTC, Walter Bright wrote:
>> On 8/11/2016 1:29 AM, John Colvin wrote:
>>> Can someone talk me through the lifetime algebra for the following?
>>>
>>> void foo()
>>> {
>>>     int a;
>>>     int** c;
>>>     void bar()
>>>     {
>>>         int* b = &a;  <= ok, b has a smaller lifetime than a
>>>         c = &b;    <= error, c has a larger lifetime than b
>>>     }
>>>     bar();
>>>     *c; //undefined behaviour
>>> }
>
> but according to this rule:
>
> "For an unrestricted pointer, visibility is dictated by the usual lexical scope
> rules. Lifetime, however is dictated by the lifetime of the data to which the
> pointer points to."
>
> b should have the same lifetime as a, no?

When b is assigned the address of a, then the contents of b, as accessible through b, have the lifetime of b.
August 12, 2016
On 8/12/2016 12:34 PM, Timon Gehr wrote:
> This proposes to add a kind of information the type system is supposed to track
> (lifetimes), which cannot be communicated losslessly across function and
> aggregate boundaries. Hence it won't work well in its current form.

I believe it does track across function boundaries, because function parameters can be annotated.

Aggregate boundaries, no, because annotating fields with 'scope' is not allowed, like 'ref' fields are not allowed.
August 12, 2016
On 08/12/2016 03:34 PM, Timon Gehr wrote:
> On 10.08.2016 22:36, Dicebot wrote:
>> http://forum.dlang.org/post/pqsiqmkxenrwxoruzaml@forum.dlang.org
>>
>> The first DIP has just landed into the new queue. It is a proposal from
>> language authors and thus it bypasses usual nitpicking process and
>> proceeds straight to requesting community (your!) feedback.
>>
>> Essentially, it is an attempt to solve reference lifetime problem by
>> extending implementation of `scope` keyword.
>>
>> Proposal text: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md
>
> This proposes to add a kind of information the type system is supposed
> to track (lifetimes), which cannot be communicated losslessly across
> function and aggregate boundaries. Hence it won't work well in its
> current form.

Could it work in a restricted manner, yet permissive enough to be useful? -- Andrei
August 12, 2016
On 12.08.2016 22:22, Andrei Alexandrescu wrote:
> On 08/12/2016 03:34 PM, Timon Gehr wrote:
>> On 10.08.2016 22:36, Dicebot wrote:
>>> http://forum.dlang.org/post/pqsiqmkxenrwxoruzaml@forum.dlang.org
>>>
>>> The first DIP has just landed into the new queue. It is a proposal from
>>> language authors and thus it bypasses usual nitpicking process and
>>> proceeds straight to requesting community (your!) feedback.
>>>
>>> Essentially, it is an attempt to solve reference lifetime problem by
>>> extending implementation of `scope` keyword.
>>>
>>> Proposal text: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md
>>
>> This proposes to add a kind of information the type system is supposed
>> to track (lifetimes), which cannot be communicated losslessly across
>> function and aggregate boundaries. Hence it won't work well in its
>> current form.
>
> Could it work in a restricted manner, yet permissive enough to be
> useful? -- Andrei

The issue is that there is information that the type system tracks that cannot be passed around effectively at the type system level.

This generally leads to a painful "fighting-the-compiler" experience when trying to use the feature in a not-completely-trivial capacity (c.f. inout, it is also a case of this). I think users of the language generally expect features to compose. So even if it is useful for the handful of special cases it was designed for, there will be a lot of complaints.
August 12, 2016
On 12.08.2016 22:22, Walter Bright wrote:
> On 8/12/2016 12:34 PM, Timon Gehr wrote:
>> This proposes to add a kind of information the type system is supposed
>> to track
>> (lifetimes), which cannot be communicated losslessly across function and
>> aggregate boundaries. Hence it won't work well in its current form.
>
> I believe it does track across function boundaries, because function
> parameters can be annotated.
> ...

Yes, to some extent, but what the type system knows and makes use of at the call site is more informative than what can be tracked around function boundaries. The effect is that there are pieces of code that cannot be abstracted into their own functions, which creates friction.

> Aggregate boundaries, no, because annotating fields with 'scope' is not
> allowed, like 'ref' fields are not allowed.

This rules out structs that wrap data and adapt it in some interesting way, a very common idiom in (generic) D code.
August 12, 2016
On 08/12/2016 04:58 PM, Timon Gehr wrote:
> On 12.08.2016 22:22, Andrei Alexandrescu wrote:
>> On 08/12/2016 03:34 PM, Timon Gehr wrote:
>>> On 10.08.2016 22:36, Dicebot wrote:
>>>> http://forum.dlang.org/post/pqsiqmkxenrwxoruzaml@forum.dlang.org
>>>>
>>>> The first DIP has just landed into the new queue. It is a proposal from
>>>> language authors and thus it bypasses usual nitpicking process and
>>>> proceeds straight to requesting community (your!) feedback.
>>>>
>>>> Essentially, it is an attempt to solve reference lifetime problem by
>>>> extending implementation of `scope` keyword.
>>>>
>>>> Proposal text:
>>>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md
>>>
>>> This proposes to add a kind of information the type system is supposed
>>> to track (lifetimes), which cannot be communicated losslessly across
>>> function and aggregate boundaries. Hence it won't work well in its
>>> current form.
>>
>> Could it work in a restricted manner, yet permissive enough to be
>> useful? -- Andrei
>
> The issue is that there is information that the type system tracks that
> cannot be passed around effectively at the type system level.
>
> This generally leads to a painful "fighting-the-compiler" experience
> when trying to use the feature in a not-completely-trivial capacity
> (c.f. inout, it is also a case of this). I think users of the language
> generally expect features to compose. So even if it is useful for the
> handful of special cases it was designed for, there will be a lot of
> complaints.

Can you please give examples of cases that are (a) unlikely to be supported with reasonable effort, and (b) likely to cause problems in usability? Thanks! -- Andrei
August 12, 2016
On 8/12/2016 2:03 PM, Timon Gehr wrote:
> On 12.08.2016 22:22, Walter Bright wrote:
>> I believe it does track across function boundaries, because function
>> parameters can be annotated.
> Yes, to some extent, but what the type system knows and makes use of at the call
> site is more informative than what can be tracked around function boundaries.
> The effect is that there are pieces of code that cannot be abstracted into their
> own functions, which creates friction.

I don't understand your comment.


>> Aggregate boundaries, no, because annotating fields with 'scope' is not
>> allowed, like 'ref' fields are not allowed.
> This rules out structs that wrap data and adapt it in some interesting way, a
> very common idiom in (generic) D code.

Consider:

    struct S { int* a, b; }

    int x;
    S s;
    s.a = &x;

should be semantically equivalent, as far as scope rules go, to:

    int x;
    int* a;
    a = &x;

(Note that 'scope' is inferred here.)

What would not work is:

    int x;
    S* ps = new S;
    ps.a = &x;