October 21, 2016
On Friday, 21 October 2016 at 15:38:39 UTC, Dicebot wrote:
>
> 2) The whole thing is very disappointing ...
> ... won't allow easy skipping of reference count inc/dec - ...

Isn't that - in the short term - impossible anyway? If a struct leaves the scope the reference counter has to be increased. But how does compiled code of a library know, if the foreign struct is an RC-object - without doing any runtime checks? So, any function has to exist twice, one time for RC and one time for no-RC?
I mean, it's probably a big topic that doesn't have to be solved in that DIP, too.
October 22, 2016
On 10/21/2016 1:30 AM, pineapple wrote:
> There's this big language enhancement in the pipeline

But it's not big.

It's the same as 'return ref', which is already there, except it's 'return scope'. The examples on how it works all boil down to a couple lines of code.
October 22, 2016
On 10/21/2016 10:38 AM, Martin Nowak wrote:
> Scope was supposed to apply to the return value, comare
> https://github.com/dlang/DIPs/blob/731255ed7dc37d596fec0552013f0e12c68f7bea/DIPs/DIP1000.md#scope-function-returns.
>
>
> Let's maybe work with a better equivalent example.
>
> @safe scope Klass get(return scope ref Unique!Klass);

Please use simple examples. 'scope' has nothing to do with templates, and adding in templates just distracts and confuses.
October 22, 2016
On 10/20/2016 10:46 PM, Dicebot wrote:
> Wait what?

I've said it multiple times. 'ref' cannot be converted to '*' and be safe. Hence the compiler disallows it.

This is exactly why we need to start with trivial examples.


> This is in direct contradiction with what DIP1000 states and
> what I have been trying to write example of all this time.

I know what you've been trying to write, and each time I point out the same thing.


> By existing
> specification annotating method with `return scope` means that lifetime
> of return value is same as that method `this`.

If this is a class this then return scope is appropriate, because this is a pointer. But when this is a ref, scope then applies to the struct's fields.


> Are you saying that existing system forgets that `instance` is `this`
> the very moment `borrow` methods finishes? If yes, I am afraid it is a
> rather useless feature, much worse than one may think reading DIP1000.

By making borrow @trusted in order to defeat the checking, you defeated the connection between 'instance' the argument and the return value from the function.

Do not convert 'ref' to '*'. It won't work.


>> The practical result is that a container that is passed by ref can only
>> control its uses by returning by ref, not by *.
>
> 1) Why? You still haven't answered how scope pointer is different from
> ref in @safe code.

I've been trying to answer. There are two things at work for variable 'v':

1. v's address
2. v's value

'ref' deals with the first, 'scope' with the second. It is very, very, very important to think about whether you are dealing with v's address or v's value, otherwise you will get hopelessly lost.

Next, recall that 'this' for a struct is an address. 'this' for a class is a value.

> 2) Does that imply that lifetime algebra as described in DIP1000 only
> applies to function internal arguments and variables? As it is not
> possible to neither have `ref` variables, nor take address of `ref`
> return value, lifetime of return value will always be limited to single
> expression.

That's what scope variables are for - storing addresses in.

I implore you to look at the test cases with the PR. They are all trivial and easy to follow.

October 22, 2016
On 10/21/2016 3:11 AM, Martin Nowak wrote:
> What would be the plan for RC.opAssign?

The plan is rather blunt. Andrei is going to design an RC object, and then I am going to figure out how to make it work (because it will need a bit of compiler help, specifically, dealing with the pre-increment case).

You are correct in that RC is only tangentially related to scope.

October 22, 2016
On 10/21/2016 8:38 AM, Dicebot wrote:
> 1) DIP1000 has to be changes a lot because it doesn't list most of those
> limitation, leading to natural conclusion that borrowing can be emulated
> as a user code concept. Most importantly, the statement "The design
> utterly relies on a 'ref' value not being returned as a '*'. Any
> attempts to circumvent this will lose the checking" is not mentioned at all.

I believe they are implicit (taking the & of a 'ref' variable has never been allowed in @safe code), but they are worth reiterating. It also is apparent now that it should explicitly say it has nothing in common with Rust's scheme.


> 2) The whole thing is very disappointing and won't revive dead body of
> @safe as I hoped it will.

What it will do is close the numerous @safe holes that have been identified.


> It won't allow to fix `Unique`, won't enable
> new RNG design Joe has been going, won't allow easy skipping of
> reference count inc/dec - the list goes on.

You're right, scope won't help at all in inc/dec skipping. But all is not lost. I have written up a short article on how the compiler can do inc/dec skipping, but it'll have to wait until we have an actual RC design.

The idea is to have a memory model that always inserts inc/dec, then allow the compiler to remove them as long as it can prove it behaves "as if" the inc/dec happened.


> Leaving aside issue 2, I'd like to give a try at updating DIP1000 this
> weekend to be more in match with what you have just explained.

Thank you! Your help is invaluable.

October 22, 2016
On 10/21/2016 4:54 AM, Martin Nowak wrote:
> On Friday, 21 October 2016 at 11:39:27 UTC, Martin Nowak wrote:
>> The problem that remains could be stated as lifetime tunneling.
>>
>> Given `v2 = func(v1)` lifetime(v2) = lifetime(v1) according to 5.
>> Changing lifetime(v1) by `v1 = e` can change lifetime(v2) to < reachability(v2).
>
> This doesn't manifest easily because there are no named reference variables and
> converting references to pointers isn't allowed in @safe code.
> But the void dangling(ref A a, scope ref B b) is one way to run into this.
> Can we at least enforce that any value/reference returned by `func(v1)` cannot
> be bound to a v2 in the calling scope while still referencing v1?

I don't really understand the question. Can you recast it in terms of a short example?
October 22, 2016
On 10/21/2016 3:21 AM, Martin Nowak wrote:
> On Friday, 21 October 2016 at 06:04:41 UTC, Walter Bright wrote:
>> 3. The design utterly relies on a 'ref' value not being returned as a '*'. Any
>> attempts to circumvent this will lose the checking. The rationale for this is
>> a dramatic simplification of the design.
>
> DIP1000 mentions that disallowing &var in @safe code is overly restrictive. This
> got me fairly confused, please help to clarify
> https://github.com/dlang/DIPs/blob/731255ed7dc37d596fec0552013f0e12c68f7bea/DIPs/DIP1000.md#escaping-via-return
> or my understanding of it.
>

In order to simplify the text, I used &t as an example, even though @safe code doesn't allow taking the address of a local. But, this is allowed:

    int[10] sa;
    int[] da = sa[];

and is the semantic equivalent of taking the address of a local. But I didn't want to confuse things by introducing arrays, I wanted to be reductionist as much as possible.

But the examples in the PR tests use the arrays.
October 22, 2016
On 10/21/2016 5:04 AM, Martin Nowak wrote:
> For sure we want to extend any attribute inferrence to functions, but how to
> make that work with separate compilation is still undecided. Talking more about
> inferrence would be an OT discussion though.

I know how to make it (inference on regular functions) work, but it is a separate topic, and would only further confuse things here.
October 22, 2016
On 10/21/2016 8:38 AM, Dicebot wrote:
> It won't allow to fix `Unique`

What it does mean is given a unique pointer u,

   int foo(scope Unique u);

it is guaranteed that u's value does not escape from foo(). So,

   Unique u = malloc();
   foo(u);
   free(u); // guaranteed to not leave a dangling pointer