Jump to page: 1 212  
Page
Thread overview
DIP 36: Rvalue References
Apr 09, 2013
Namespace
Apr 10, 2013
kenji hara
Apr 10, 2013
Dicebot
Apr 11, 2013
Dicebot
Apr 11, 2013
kenji hara
Apr 11, 2013
Dicebot
Apr 11, 2013
kenji hara
Apr 11, 2013
Dicebot
Apr 12, 2013
Namespace
Apr 17, 2013
Namespace
Apr 17, 2013
Minas Mina
Apr 17, 2013
Namespace
Apr 17, 2013
Minas Mina
Apr 17, 2013
Namespace
Apr 17, 2013
Zach the Mystic
Apr 20, 2013
Namespace
Apr 20, 2013
deadalnix
Apr 20, 2013
Namespace
Apr 20, 2013
deadalnix
Apr 20, 2013
Namespace
Apr 20, 2013
deadalnix
Apr 20, 2013
Dicebot
Apr 20, 2013
Timon Gehr
Apr 21, 2013
Manu
Apr 21, 2013
Zach the Mystic
Apr 21, 2013
Manu
Apr 21, 2013
deadalnix
Apr 21, 2013
Dicebot
Apr 21, 2013
Zach the Mystic
Apr 21, 2013
deadalnix
Apr 21, 2013
Zach the Mystic
Apr 21, 2013
Timon Gehr
Apr 21, 2013
Manu
Apr 21, 2013
Timon Gehr
Apr 21, 2013
Manu
Apr 21, 2013
Timon Gehr
Apr 21, 2013
Zach the Mystic
Apr 22, 2013
Namespace
Apr 22, 2013
Diggory
Apr 22, 2013
Namespace
Apr 22, 2013
Diggory
Apr 22, 2013
Namespace
Apr 22, 2013
Zach the Mystic
Apr 23, 2013
Dicebot
Apr 23, 2013
Timon Gehr
Apr 23, 2013
Dicebot
Apr 20, 2013
John Colvin
Apr 20, 2013
Namespace
Apr 20, 2013
John Colvin
Apr 20, 2013
Namespace
Apr 21, 2013
deadalnix
Apr 21, 2013
Dicebot
Apr 21, 2013
Zach the Mystic
Apr 21, 2013
Zach the Mystic
Apr 23, 2013
Dicebot
Apr 20, 2013
Minas Mina
Apr 20, 2013
Timon Gehr
Apr 22, 2013
Tove
Apr 22, 2013
Namespace
Apr 23, 2013
Dicebot
Apr 23, 2013
Dicebot
Apr 23, 2013
Manu
Apr 23, 2013
Diggory
Apr 23, 2013
Diggory
Apr 23, 2013
Manu
Apr 24, 2013
Mehrdad
Apr 23, 2013
Manu
Apr 23, 2013
Timon Gehr
Apr 23, 2013
Timon Gehr
Apr 24, 2013
kenji hara
Apr 24, 2013
Timon Gehr
Apr 21, 2013
Zach the Mystic
Apr 21, 2013
Namespace
Apr 12, 2013
Zach the Mystic
Apr 10, 2013
Zach the Mystic
Apr 10, 2013
kenji hara
Apr 10, 2013
Zach the Mystic
Apr 10, 2013
Zach the Mystic
Apr 10, 2013
Manu
Apr 10, 2013
Zach the Mystic
Apr 10, 2013
Manu
Apr 23, 2013
Mehrdad
Apr 24, 2013
Zach the Mystic
Apr 10, 2013
Zach the Mystic
Apr 23, 2013
Dicebot
Apr 23, 2013
Timon Gehr
Apr 23, 2013
Dicebot
Apr 10, 2013
kenji hara
Apr 10, 2013
Manu
Apr 10, 2013
Dicebot
Apr 10, 2013
Zach the Mystic
Apr 10, 2013
Dicebot
Apr 11, 2013
Zach the Mystic
Apr 10, 2013
Manu
Apr 10, 2013
Dicebot
Apr 10, 2013
deadalnix
Apr 10, 2013
Dicebot
Apr 10, 2013
Namespace
Apr 10, 2013
Manu
Apr 10, 2013
Minas Mina
Apr 10, 2013
deadalnix
Apr 10, 2013
Dicebot
Apr 10, 2013
Manu
Apr 11, 2013
Jonas Drewsen
April 09, 2013
http://wiki.dlang.org/DIP36
April 10, 2013
2013/4/10 Namespace <rswhite4@googlemail.com>

> http://wiki.dlang.org/DIP36
>

Typo:
> Similar to "auto ref" but no extra template instantations.
  Similar to "auto ref" but no extra template instantiations

One question:
void test1(scope ref A a) {}

    test1(A(42)); // @safe, this temporary value is valid for mutation and
"scope" ensures it does not leak scope
    A a = A(23); // no difference
    test1(a);

void test32(T)(scope ref T id) {}

    test32(1337); // Prohibited, no address for "1337"
    test32(a.id); // fine and @safe

Why test32 does not accept rvalue like test1? I think that "scope ref" should always behave same for rvalue argument - create temporary and take its address to "scope ref" parameter. Consistent behavior with any types is important for the generic programming.

Other than comment, looks good. Good work, Randy and Михаил!

Kenji Hara


April 10, 2013
On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:
> http://wiki.dlang.org/DIP36

// Does not pretend to be @safe any more
void test2(ref A a) {
}

I believe 'ref' still *can* be @safe. The unsafe action is really when you assign it to a global pointer.

void test2(ref A a) {
  static A* p;
  p = &a; // <-- This is really the only unsafe thing
}

I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is @safe so long as the *caller* keeps track of what it passes in, according to DIP25.

"Following limitation apply to scope ref function parameters (including in ref):
...3. Parameter can only be used as an argument for other function if it also accepts scope ref, no implicit casting away."

The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently @safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere.

Also, given that 'scope' implies 'ref', there may be significant advantage in simply allowing *all* scope parameters to accept rvalue temps. It would be helpful to have a use case where 'scope' was clearly desired but rvalue temps clearly *not* desired. In most cases, it seems, anything marked 'scope' could easily accept an rvalue temp no problem.

The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.
April 10, 2013
2013/4/10 Zach the Mystic <reachzach@gggggmail.com>

> On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:
>
>> http://wiki.dlang.org/DIP36
>>
>
> // Does not pretend to be @safe any more
> void test2(ref A a) {
> }
>
> I believe 'ref' still *can* be @safe. The unsafe action is really when you assign it to a global pointer.
>
> void test2(ref A a) {
>   static A* p;
>   p = &a; // <-- This is really the only unsafe thing
> }
>
> I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is @safe so long as the *caller* keeps track of what it passes in, according to DIP25.
>
> "Following limitation apply to scope ref function parameters (including in
> ref):
> ...3. Parameter can only be used as an argument for other function if it
> also accepts scope ref, no implicit casting away."
>
> The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently @safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere.
>
> Also, given that 'scope' implies 'ref', there may be significant advantage in simply allowing *all* scope parameters to accept rvalue temps. It would be helpful to have a use case where 'scope' was clearly desired but rvalue temps clearly *not* desired. In most cases, it seems, anything marked 'scope' could easily accept an rvalue temp no problem.
>
> The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.
>

I think having both 'ref' and 'scope ref' is still reasonable, because:

1. According to DIP25, escaping ref parameter is always safe. But, for rvalue reference, it allows meaningless code.

// Even if this is allowed, it is safe. BUT will introduce bad practice. ref int foo(scope ref int x) { return x; }

// safe
ref int bar(ref int x) { return x; }

void test() {
    int x;
    foo(x) = 10;    // may useful but...
    foo(1) = 10;    // completely useless!

    bar(x) = 10;    // may useful, and
    bar(1) = 10;    // disallowed.
}

2. Certainly 'scope' by itself _can_ imply 'ref'. BUT, currently a function
parameter without 'ref' storage class implies having value semantics (==
copy).
If we change the 'scope' meaning to 'implicit ref', it will break the
consistency.

And, 'scope' is alredy used for delegate parameter.

int opApply(scope int delegate(ref int) dg);

Such a semantic modification will silently change the meaning of existing code. It's not good to me.

Kenji Hara


April 10, 2013
On Wednesday, 10 April 2013 at 02:41:10 UTC, kenji hara wrote:
> I think having both 'ref' and 'scope ref' is still reasonable, because:
>
> 1. According to DIP25, escaping ref parameter is always safe.  But, for
> rvalue reference, it allows meaningless code.
>
> // Even if this is allowed, it is safe. BUT will introduce bad practice.
> ref int foo(scope ref int x) { return x; }
>
> // safe
> ref int bar(ref int x) { return x; }
>
> void test() {
>     int x;
>     foo(x) = 10;    // may useful but...
>     foo(1) = 10;    // completely useless!
>
>     bar(x) = 10;    // may useful, and
>     bar(1) = 10;    // disallowed.
> }

'foo(1) = 10' is indeed completely useless, but I don't think all uses are completely useless. But I will concede that allowing things like 'foo(1)' may be useless *enough* to disallow it without anyone feeling bad. I have made DIP35, http://wiki.dlang.org/DIP35 , which utilizes 'scope' to actually make DIP25 more flexible, which I think is probably good. The example I used was the 'copy' function. 'foo' above, rewritten as the copy function would be:

ref int foo(scope ref int x) {
  int* y = new int;
  *y = x;
  return y;
}

DIP25 may *need* to use 'scope' in this way to know that foo() will always give a fresh value - so it can treat it like a global safely. Thus 'foo(1)' will return a fresh heap allocated copy of "1".

ref int test() {
  return foo(1); // allowed
  return bar(1); // disallowed!
}

Without the 'scope' parameter, there would be no way the compiler could know. Therefore, it is not completely useless.

> 2. Certainly 'scope' by itself _can_ imply 'ref'. BUT,  currently a function
> parameter without 'ref' storage class implies having value semantics (== copy).

This is slightly wrong, I suspect. 'out' parameters are implicitly references.

> If we change the 'scope' meaning to 'implicit ref', it will break the
> consistency.
>
> And, 'scope' is already used for delegate parameter.
>
> int opApply(scope int delegate(ref int) dg);
>
> Such a semantic modification will silently change the meaning of existing code. It's not good to me.

Generally, I agree. My argument is for a small convenience of not having to type 'ref' when not necessary. It would mean that when the type was implicitly a reference, such as a delegate or object, 'ref' was *not* implied, whereas it *was* implied with a value type. This may or may not wreak havoc on the generic type system. I thought there might be an off-chance that it would actually be a *convenience* for the type system, since it would get the right level of referencing for the type involved.

I believe that the 'scope' keyword may be a necessary addition to DIP25 to make 'ref' fully safe and flexible (DIP35). If so, then there may be a conflict with using it only to mean rvalue temporaries. They are two separate features. I believe that if they are to be used together, it will be because it was decided that whenever you want to stop a reference from escaping, you *always* want to allow rvalue temporaries, and whenever you want to allow rvalue temporaries, you *never* want them to be returned. Right now, returning an rvalue temporary might seem dangerous, but sealed references *are* part of the plan for D, and there may be no need to see them as dangerous.
April 10, 2013
On Wednesday, 10 April 2013 at 04:46:43 UTC, Zach the Mystic wrote:
> ref int bar(ref int x) { return x; }
>
> ref int foo(scope ref int x) {
>   int* y = new int;
>   *y = x;
>   return y;
> }
>
> ref int test() {
>   return foo(1); // allowed
>   return bar(1); // disallowed!
> }

When said 'bar(1)' was disallowed, I meant that it was considered local and not disallowed because it doesn't accept rvalue temps. Fix:

ref int test() {
  int y;
  return foo(y); // allowed
  return bar(y); // disallowed!
}
April 10, 2013
YES PLEASE!!
I've been saying precisely this for years, I'm glad someone took the time
to write it down all nice and proposal-like :)


On 10 April 2013 03:06, Namespace <rswhite4@googlemail.com> wrote:

> http://wiki.dlang.org/DIP36
>


April 10, 2013
On 10 April 2013 12:40, kenji hara <k.hara.pg@gmail.com> wrote:

> 2013/4/10 Zach the Mystic <reachzach@gggggmail.com>
>
>> On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:
>>
>>> http://wiki.dlang.org/DIP36
>>>
>>
>> // Does not pretend to be @safe any more
>> void test2(ref A a) {
>> }
>>
>> I believe 'ref' still *can* be @safe. The unsafe action is really when you assign it to a global pointer.
>>
>> void test2(ref A a) {
>>   static A* p;
>>   p = &a; // <-- This is really the only unsafe thing
>> }
>>
>> I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is @safe so long as the *caller* keeps track of what it passes in, according to DIP25.
>>
>> "Following limitation apply to scope ref function parameters (including
>> in ref):
>> ...3. Parameter can only be used as an argument for other function if it
>> also accepts scope ref, no implicit casting away."
>>
>> The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently @safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere.
>>
>> Also, given that 'scope' implies 'ref', there may be significant
>> advantage in simply allowing *all* scope parameters to accept rvalue temps.
>> It would be helpful to have a use case where 'scope' was clearly desired
>> but rvalue temps clearly *not* desired. In most cases, it seems, anything
>> marked 'scope' could easily accept an rvalue temp no problem.
>>
>> The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.
>>
>
> I think having both 'ref' and 'scope ref' is still reasonable, because:
>
> 1. According to DIP25, escaping ref parameter is always safe. But, for rvalue reference, it allows meaningless code.
>
> // Even if this is allowed, it is safe. BUT will introduce bad practice. ref int foo(scope ref int x) { return x; }
>
> // safe
> ref int bar(ref int x) { return x; }
>
> void test() {
>     int x;
>     foo(x) = 10;    // may useful but...
>     foo(1) = 10;    // completely useless!
>
>     bar(x) = 10;    // may useful, and
>     bar(1) = 10;    // disallowed.
> }
>
> 2. Certainly 'scope' by itself _can_ imply 'ref'. BUT, currently a
> function parameter without 'ref' storage class implies having value
> semantics (== copy).
> If we change the 'scope' meaning to 'implicit ref', it will break the
> consistency.
>

Why are you suggesting changing scope to imply ref? This seems wrong. scope
and ref are separate, should remain that way.
Arguments would be scope ref, or in ref, thus allowing rvalues. Without
ref, I would imagine that the meaning is such that, even though the
argument is a copy, it, or members thereof are not allowed to escape.

struct X { int *p; }
int* global;

void func(scope X x) // note: is not ref
{
  global = x.p; // <- error! scope prevents any part of x escaping, even
though it's a copy.
}

This way, scope has meaning with or without ref.


And, 'scope' is alredy used for delegate parameter.
>
> int opApply(scope int delegate(ref int) dg);
>
> Such a semantic modification will silently change the meaning of existing code. It's not good to me.
>

What does scope mean in this case? Is this a conflict in some way?


April 10, 2013
2013/4/10 Manu <turkeyman@gmail.com>
>
> Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.
>

I say that 'scope' itself should not imply 'ref'. It is *possible* but would break existing code meaning, so it should not be applied.


> Arguments would be scope ref, or in ref, thus allowing rvalues. Without ref, I would imagine that the meaning is such that, even though the argument is a copy, it, or members thereof are not allowed to escape.
>
> struct X { int *p; }
> int* global;
>
> void func(scope X x) // note: is not ref
> {
>   global = x.p; // <- error! scope prevents any part of x escaping, even
> though it's a copy.
> }
>
> This way, scope has meaning with or without ref.
>

That is an enhancement. Similar things is now in my mind, but it is not yet output.


> And, 'scope' is alredy used for delegate parameter.
>>
>> int opApply(scope int delegate(ref int) dg);
>>
>> Such a semantic modification will silently change the meaning of existing code. It's not good to me.
>>
>
> What does scope mean in this case? Is this a conflict in some way?
>

Compiler guarantees that given delegate to the scope parameter never make a
closure.
It would avoid heap allocation.

Kenji Hara


April 10, 2013
On 10 April 2013 15:30, kenji hara <k.hara.pg@gmail.com> wrote:

> 2013/4/10 Manu <turkeyman@gmail.com>
>>
>> Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.
>>
>
> I say that 'scope' itself should not imply 'ref'. It is *possible* but would break existing code meaning, so it should not be applied.
>

Right. Absolutely agree then! :)



> Arguments would be scope ref, or in ref, thus allowing rvalues. Without
>> ref, I would imagine that the meaning is such that, even though the argument is a copy, it, or members thereof are not allowed to escape.
>>
>> struct X { int *p; }
>> int* global;
>>
>> void func(scope X x) // note: is not ref
>> {
>>   global = x.p; // <- error! scope prevents any part of x escaping, even
>> though it's a copy.
>> }
>>
>> This way, scope has meaning with or without ref.
>>
>
> That is an enhancement. Similar things is now in my mind, but it is not yet output.
>

I think this is a tool that will greatly enhance working with @safe in the future. I look forward to it.


 And, 'scope' is alredy used for delegate parameter.
>>>
>>> int opApply(scope int delegate(ref int) dg);
>>>
>>> Such a semantic modification will silently change the meaning of existing code. It's not good to me.
>>>
>>
>> What does scope mean in this case? Is this a conflict in some way?
>>
>
> Compiler guarantees that given delegate to the scope parameter never make
> a closure.
> It would avoid heap allocation.
>

Do you have any ideas/solutions that still fit this proposal?
I tend to think the value of this proposal is of extreme significance to D.
It is, without doubt, the single biggest complaint I've heard by virtually
every programmer I've introduced D to, and the future implications for
@safe improvements are valuable too.


« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11