August 11, 2016
My comments:

1) `scope` on local variables is unnecessary. Requiring it probably makes the implementation easier, but it doesn't need to be specified explicitly because it can always be inferred. It's a tradeoff: do we want to make it easier for compiler writers to implement, or do we want to ease the burden for the end users of the feature?

2) The lifetime algebra contains lots of rules saying "only applicable to pointer types". That's an indication that some of the definitions weren't well chosen. I believe it is a consequence of all values having a lifetime, even though it is defined to be identical to the visibility for non-reference types. Adjusting the definitions will probably simplify things. E.g. `lifetime(&e) = visibility(e)` instead of `lifetime(&e) = lifetime(e)`

3) LHS and RHS need to be treated differently, at least for the ternary operator (min for RHS, max for LHS); consider

int *a;
int b;
int *c;
int d;
c = cond ? &b : &d;    // ok, rejected because c outlives b
(cond ? a : c) = &b;   // not ok, accepted even though a outlives b

An equivalent situation can be crafted by using a function with return scope and multiple scope parameters. If the return value is used on the LHS, the max of all the involved lifetimes has to be used.

As a consequence, there must be two lifetimes associated with every reference.

4) The DIP doesn't address mutable aliasing at all. As a consequence, the example `RefCountedSlice` is unsafe:

auto arr = RefCountedSlice!int(10);
auto ptr = &arr[5];
arr = RefCountedSlice!int(42);
*ptr = 1;    // use after free
August 11, 2016
On Wednesday, 10 August 2016 at 20:36:38 UTC, Dicebot wrote:
>
> Proposal text: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md

I trust the leadership that this is an important issue (including for perception), but...

Does memory safety deserve such an extensive use of complexity?
From a (very) naive POV, how come ref/scoped/@safe can't be "replaced" wholesale by a type constructor owned!T + lifetimes, that this DIP otherwise introduces.

This DIP ensures unsafe references do not escape, but I can't remember having such a problem even once, sorry.

Does this allow throwing exceptions in @nogc code? That would be great.
August 11, 2016
On Thursday, 11 August 2016 at 13:36:06 UTC, Marc Schütz wrote:
> 2) The lifetime algebra contains lots of rules saying "only applicable to pointer types". That's an indication that some of the definitions weren't well chosen.

Yes, the spec should limit itself to types with and without indirections.

> 3) LHS and RHS need to be treated differently, at least for the ternary operator (min for RHS, max for LHS); consider
>

I proposed computing revalue and lvalue lifetime differently. When reading, you need to make the most concervative lifetime compuation, but when writing, you need to make the least concervative lifetime computation, in both cases to prevent use after free.

The DIP choses instead to limit the number of indirection supported, which I don't think is the right tradeof.


> As a consequence, there must be two lifetimes associated with every reference.
>

Pretty much.

> 4) The DIP doesn't address mutable aliasing at all. As a consequence, the example `RefCountedSlice` is unsafe:
>
> auto arr = RefCountedSlice!int(10);
> auto ptr = &arr[5];
> arr = RefCountedSlice!int(42);
> *ptr = 1;    // use after free

There are essentially 2 aproaches I know of: creating a copy of the owner for the lifetime ptr, or disabing the owner (accessing arr while ptr is alive is an error).

Both require ownership to work.

August 11, 2016
On 08/11/2016 11:07 AM, Jacob Carlborg wrote:
> On 10/08/16 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
> 
> DIP 1_000? Is this the one DIP to rule them all, making all the 900 DIPs or so you skipped over not necessary :)

I have decided to start counting new DIPs from 1000 so that it is immediately clear when someone casually mentions "DIP N" if the person refers to old or new queue.



August 11, 2016
On Wednesday, 10 August 2016 at 20:36:38 UTC, 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
>
> Few notes:
>
> - Please submit pull requests to adjust the markdown document if you want to propose any improvements (mentioning @WalterBright and @andralex for confirmation).
> - The proposal refers to a number of other documents and it is recommended to become familiar at least briefly with all of them.
> - At this point the question I'd personally suggest to be evaluated is "does this proposal enable enough useful designs?". A good check would be to try taking some of your projects and see if having DIP1000 approved and implemented could improve them.


There is confusion between what lifetime and visibility in the DIP.
(Well, I am confused)

1) infinite lifetime null

int * p;

The lifetime(p) is infinite while the visibility(p) starts here.
It seems to be the lifetime of p is determined by the value assigned to it,
which in this case is null and the lifetime of lifetime(null) is infinite.


2) Fundamentals of scope.

This declares 4 scope rules as of 11 August of which the first rule is:

"A scope variable can only be initialized and assigned from values that have lifetimes longer than the variable's lifetime"


int global_var;
int* global_ptr;

void bar(scope int* input);

void fun1() {
    scope int* a = &global_var; // OK per rule 1, lifetime(&global_var) > lifetime(a)
    int b;
    a = &b; // Disallowed per rule 1, lifetime(&b) < lifetime(a)

Shouldn't the rule be:

"A scope variable can only be initialized and assigned from values that have lifetimes longer than the variable's VISIBILITY"

As in the case above. What is the lifetime(a) "scope int *a" when the &global_var
has not yet been assigned to it? It doesn't have a lifetime yet,
it gets the lifetime from &global_var.


Peter






August 11, 2016
On 8/11/2016 4:40 AM, Robert burner Schadek wrote:
> Ok, I disagree, but there is no way that I can proof to be right. You can also
> not proof that you're right, so I'll trust your judgement.

Thanks for the vote of confidence! I hope to justify it.

August 11, 2016
On Thursday, 11 August 2016 at 21:28:57 UTC, sclytrack wrote:
> On Wednesday, 10 August 2016 at 20:36:38 UTC, Dicebot wrote:
>> [...]
>
>
> There is confusion between what lifetime and visibility in the DIP.
> (Well, I am confused)
>
> [...]


What are those puppy dogs doing there? I don't have a gravatar account.

August 11, 2016
On 8/11/16 5:42 PM, sclytrack wrote:
> On Thursday, 11 August 2016 at 21:28:57 UTC, sclytrack wrote:
>> On Wednesday, 10 August 2016 at 20:36:38 UTC, Dicebot wrote:
>>> [...]
>>
>>
>> There is confusion between what lifetime and visibility in the DIP.
>> (Well, I am confused)
>>
>> [...]
>
>
> What are those puppy dogs doing there? I don't have a gravatar account.
>

Apparently fake@hotmail.com does. Perhaps that's not your real email?

-Steve
August 11, 2016
On 8/11/2016 6:36 AM, Marc Schütz wrote:
> 1) `scope` on local variables is unnecessary. Requiring it probably makes the
> implementation easier, but it doesn't need to be specified explicitly because it
> can always be inferred.

Yes, it can be easily inferred from the initializer, and I plan to do it that way. The 'return' of 'return scope' can also be frequently inferred like it is for 'return ref'.


> 2) The lifetime algebra contains lots of rules saying "only applicable to
> pointer types". That's an indication that some of the definitions weren't well
> chosen. I believe it is a consequence of all values having a lifetime, even
> though it is defined to be identical to the visibility for non-reference types.
> Adjusting the definitions will probably simplify things. E.g. `lifetime(&e) =
> visibility(e)` instead of `lifetime(&e) = lifetime(e)`
>
> 3) LHS and RHS need to be treated differently, at least for the ternary operator
> (min for RHS, max for LHS); consider
>
> int *a;
> int b;
> int *c;
> int d;
> c = cond ? &b : &d;    // ok, rejected because c outlives b

With conditionals, the scope of it is the narrowest scope of each of its leaves.

> (cond ? a : c) = &b;   // not ok, accepted even though a outlives b

I had overlooked the lvalue case, but you're right. The rules for it are inevitable.


> An equivalent situation can be crafted by using a function with return scope and
> multiple scope parameters. If the return value is used on the LHS, the max of
> all the involved lifetimes has to be used.

That's right.


> As a consequence, there must be two lifetimes associated with every reference.


> 4) The DIP doesn't address mutable aliasing at all. As a consequence, the
> example `RefCountedSlice` is unsafe:
>
> auto arr = RefCountedSlice!int(10);
> auto ptr = &arr[5];
> arr = RefCountedSlice!int(42);
> *ptr = 1;    // use after free

The idea is to have containers return references by 'return ref' or 'return scope' so the internal references can't escape the expression they're used in.
August 11, 2016
On 8/11/2016 4:46 AM, Robert burner Schadek wrote:
> Can I do this:
>
> ```
> struct Foo { int a; }
> auto rcs = RefCountedSlice!Foo(); // assume rcs.length > 0
>
> scope Foo zero = rcs[0];
> zero.a = 1337;
> assert(rcs[0].a == 1337);
> ```

No, because the lifetime of zero exceeds the lifetime of rcs[0].