April 24, 2013
On 24 April 2013 11:22, kenji hara <k.hara.pg@gmail.com> wrote:

> Temporaries which created on stack to pass an address to `scope ref` parameter would be destroyed after the "current statement/expression".
>
> T rvalue();
>
> void foo(scope ref T) { ... }
> foo(rvalue());   // here is "current statement/expression"
> // lowered to: { auto __tmp = rvalue(); foo(__tmp);  __tmp.~this(); };
>
> Note that the lifetime of taken rvalue is mostly same as non-ref parameter
> case.
> void bar(T arg) { ... arg.~this(); }
> bar(rvalue());
> // the rvalue argument is moved into the function 'bar', and destroyed
> inside function.
>

The important distinction is that with scope ref, a temps life can be
prolonged and cascaded via return values.
This is very important behaviour, I couldn't write an efficient&convenient
matrix library for instance without this, i would have to choose one or the
other.


> Kenji Hara
>
>
> 2013/4/24 Diggory <diggsey@googlemail.com>
>
>> On Wednesday, 24 April 2013 at 00:54:12 UTC, kenji hara wrote:
>>
>>> 2013/4/24 Manu <turkeyman@gmail.com>
>>>
>>>  "The r-value being passed is assigned to a stack allocated temporary,
>>>> which has a lifetime that is identical to any other local variable, ie,
>>>> the
>>>> lifetime of the function in which it appears."
>>>> There, I defined it.
>>>>
>>>>
>>> Good definition. If add more,
>>> "getting address of "scope" parameter would be disallowed, at least in
>>> @safe code, because it would be regarded as the escape of stack allocated
>>> temporary."
>>>
>>> Kenji Hara
>>>
>>
>> Why does the temporary need to exist any longer than the current statement? (the current lifetime of temporaries are the statement or expression). Surely any longer is just wasting stack space.
>>
>
>


April 24, 2013
On Wednesday, 24 April 2013 at 03:33:07 UTC, Manu wrote:
> On 24 April 2013 04:44, Walter Bright <newshound2@digitalmars.com> wrote:
>
>> On 4/23/2013 8:33 AM, Manu wrote:
>>
>>> "The r-value being passed is assigned to a stack allocated temporary,
>>> which has
>>> a lifetime that is identical to any other local variable, ie, the
>>> lifetime of
>>> the function in which it appears."
>>> There, I defined it.
>>>
>>
>> Locals have a lifetime that is terminated by the closing } of the scope
>> they appear in. There can be many such scopes in a function.
>>
>> There's also the issue of:
>>
>>   a || b || c
>>
>> If b creates a temporary, it's life ends at the end of the expression or
>> statement - it's complicated.
>>
>
> Is it actually complicated?
> Enclosing scope seems fine too. Can you suggest a case where it could
> escalate to an outer scope via a scope-ref argument?
> So let's say then, that lifetime should be identical to a local declared in
> the same location. No change of any rules is required, it will work as
> expected.

The issue is that in this case for instance, the temporary is conditionally created. Then cannot bind to the enclosing scope.

As temporaries can now be created all over the place, it is mandatory to define them in a much more specific way than it is done right now.
April 24, 2013
On 24 April 2013 14:07, deadalnix <deadalnix@gmail.com> wrote:

> On Wednesday, 24 April 2013 at 03:33:07 UTC, Manu wrote:
>
>> On 24 April 2013 04:44, Walter Bright <newshound2@digitalmars.com> wrote:
>>
>>  On 4/23/2013 8:33 AM, Manu wrote:
>>>
>>>  "The r-value being passed is assigned to a stack allocated temporary,
>>>> which has
>>>> a lifetime that is identical to any other local variable, ie, the
>>>> lifetime of
>>>> the function in which it appears."
>>>> There, I defined it.
>>>>
>>>>
>>> Locals have a lifetime that is terminated by the closing } of the scope they appear in. There can be many such scopes in a function.
>>>
>>> There's also the issue of:
>>>
>>>   a || b || c
>>>
>>> If b creates a temporary, it's life ends at the end of the expression or statement - it's complicated.
>>>
>>>
>> Is it actually complicated?
>> Enclosing scope seems fine too. Can you suggest a case where it could
>> escalate to an outer scope via a scope-ref argument?
>> So let's say then, that lifetime should be identical to a local declared
>> in
>> the same location. No change of any rules is required, it will work as
>> expected.
>>
>
> The issue is that in this case for instance, the temporary is conditionally created. Then cannot bind to the enclosing scope.
>

Conditionally created, in the event you pass an rvalue or not? What about
binding?
I don't know what you're saying.

As temporaries can now be created all over the place, it is mandatory to
> define them in a much more specific way than it is done right now.


...I don't follow. There's absolutely nothing special about an implicitly created temp vs an explicit one.


April 24, 2013
On Wednesday, 24 April 2013 at 04:41:47 UTC, Manu wrote:
>>
>> The issue is that in this case for instance, the temporary is
>> conditionally created. Then cannot bind to the enclosing scope.
>>
>
> Conditionally created, in the event you pass an rvalue or not? What about
> binding?
> I don't know what you're saying.
>
> As temporaries can now be created all over the place, it is mandatory to
>> define them in a much more specific way than it is done right now.
>
>
> ...I don't follow. There's absolutely nothing special about an implicitly
> created temp vs an explicit one.

I think you misunderstand the problem. It is usually a bad idea to claim no problem exists when you don't get objections formulated.

Walter gave a very simple example that defeat you proposal (which say that temporary live until end of enclosing scope).

In a || b || c, b is conditionally executed. If it require a temporary, then the temporary can't have a lifetime as you described as it is conditionally declared (which is impossible with explicit declarations).

Problems along the same lines occurs when multiple temporaries are necessary. For instance, in what order they are created, what happen if the creation of one does throw ?
April 24, 2013
On Tuesday, 23 April 2013 at 19:45:39 UTC, Zach the Mystic wrote:
> ref T func(ref T x, @noreturn ref T y) {
>   return x; // pass
>   return y; // error
>   static T* t = &y; // pass!?
> }

Sorry about the static definition. It should be: 'static T* t; t = &y;' instead, and for all subsequent definitions.
April 24, 2013
On Wednesday, 24 April 2013 at 03:41:17 UTC, Manu wrote:
> scope ref a(scope ref int x) { return x; }

One thing to bear in mind about this usage is that 'scope' could apply to the implicit 'this' reference, in addition to describing the return type, which might make it unfeasible. I don't know how often you'd want to tag the 'this' with 'scope' but not the return, and the other way around.

struct S {
  scope ref a(scope ref int x) { return x; }
}
April 24, 2013
On 4/23/2013 8:32 PM, Manu wrote:
> Is it actually complicated?

It's a lot more complicated than simply destructing them at the end of a function. You have to define what happens for conditionally executed expressions || && ?:, what happens at the end of a statement, what happens at a }, what happens to for statement initializers, etc., for each statement type.


> Enclosing scope seems fine too. Can you suggest a case where it could escalate
> to an outer scope via a scope-ref argument?
> So let's say then, that lifetime should be identical to a local declared in the
> same location. No change of any rules is required, it will work as expected.

You cannot declare locals in conditionally compiled expressions. So it isn't as simple as that.

April 24, 2013
On 4/23/2013 6:02 PM, Diggory wrote:
> Why does the temporary need to exist any longer than the current statement?

And it doesn't in C++.
April 24, 2013
On Wednesday, 24 April 2013 at 02:56:42 UTC, Jonathan M Davis wrote:
> So, probably the best route at this point is to come up with a new attribute
> which is replace with ref in the function definition and

When you say "replace with ref", does that mean 'ref' won't appear in the common case?

ref T fc(scope int a) {}

The problem would be that 'scope' would behave differently, implying 'ref' with a value type, from with a reference type, in which it shouldn't imply 'ref'. I don't know if it makes sense to automatically promote the meaning of 'scope' to include 'ref' for value types while leaving it alone for reference types. This was objected to by others, but if it were provably harmless to allow, it would be an appearance improvement.
April 24, 2013
On 4/23/2013 8:44 PM, Manu wrote:
> The important distinction is that with scope ref, a temps life can be prolonged
> and cascaded via return values.
> This is very important behaviour, I couldn't write an efficient&convenient
> matrix library for instance without this, i would have to choose one or the other.

Dealing with this issue, one way or another, is critical for any rvalue ref design.