DIP69 - Implement scope for escape proof references
via Digitalmars-d
digitalmars-d at puremagic.com
Sat Dec 6 05:30:03 PST 2014
On Friday, 5 December 2014 at 23:58:41 UTC, Walter Bright wrote:
> On 12/5/2014 8:48 AM, "Marc Schütz" <schuetzm at gmx.net>" wrote:
>> 1) Escape detection is limited to `ref`.
>>
>> T* evil;
>> ref T func(scope ref T t, ref T u) @safe {
>> return t; // Error: escaping scope ref t
>> return u; // ok
>> evil = &u; // Error: escaping reference
>> }
>>
>> vs.
>>
>> T[] evil;
>> T[] func(scope T[] t, T[] u) @safe {
>> return t; // Error: cannot return scope
>> return u; // ok
>> evil = u; // !!! not good
>
> right, although:
> evil = t; // Error: not allowed
>
>> }
>>
>> As can be seen, `ref T u` is protected from escaping (apart
>> from returning it),
>> while `T[] u` in the second example is not. There's no general
>> way to express
>> that `u` can only be returned from the function, but will not
>> be retained
>> otherwise by storing it in a global variable. Adding `pure`
>> can express this in
>> many cases, but is, of course, not always possible.
>
> As you point out, 'ref' is designed for this.
I wouldn't call it "designed", but "repurposed"...
>> struct Container(T) {
>> scope ref T opIndex(size_t index);
>> }
>>
>> void bar(scope ref int a);
>>
>> Container c;
>> bar(c[42]); // ok
>> scope ref tmp = c[42]; // nope
>>
>> Both cases should be fine theoretically; the "real" owner
>> lives longer than
>> `tmp`. Unfortunately the compiler doesn't know about this.
>
> Right, though the compiler can optimize to produce the
> equivalent.
??? This is a problem on the semantic level, unrelated to
optimization:
// contrived example to illustrated the point
Container c;
scope ref x = c[42]; // not
scope ref y = c[44]; // ...
scope ref z = c[13]; // allowed
foo(x, y, z, x+y, y+z, z+x, x+y+z);
// workaround, but error-prone and has different semantics
// (opIndex may have side effects, called multiple times)
foo(c[42], c[44], c[13], c[42]+c[44], c[44]+c[13],
c[13]+c[42], c[42]+c[44]+c[13]);
// another workaround, same semantics, but ugly and unreadable
(scope ref int x, scope ref int y, scope ref int z) {
foo(x, y, z, x+y, y+z, z+x, x+y+z);
}(c[42], c[44], c[13]);
>> 3) `scope` cannot be used for value types.
>>
>> I can think of a few use cases for scoped value types (RC and
>> file descriptors),
>> but they might only be marginal.
>
> I suspect that one can encapsulate such values in a struct
> where access to them is strictly controlled.
They can, but again at the cost of an indirection (ref).
>> 4) No overloading on `scope`.
>>
>> This is at least partially a consequence of `scope` inference.
>> I think
>> overloading can be made to work in the presence of inference,
>> but I haven't
>> thought it through.
>
> Right. Different overloads can have different semantic
> implementations, so what should inference do? I also suspect it
> is bad style to overload on 'scope'.
It only makes sense with scope value types (see the RC example).
For references, I don't know any useful applications.
>> 6) There seem to be problems with chaining.
>>
>> scope ref int foo();
>> scope ref int bar1(ref int a) {
>> return a;
>> }
>> scope ref int bar2(scope ref int a) {
>> return a;
>> }
>> ref int bar3(ref int a) {
>> return a;
>> }
>> ref int bar4(scope ref int a) {
>> return a;
>> }
>> void baz(scope ref int a);
>>
>> Which of the following calls would work?
>>
>> foo().bar1().baz();
>
> yes
>
>> foo().bar2().baz();
>
> no - cannot return scope ref parameter
>
>> foo().bar3().baz();
>
> yes
>
>> foo().bar4().baz();
>
> no, cannot return scope ref parameter
>
>
>> I'm not sure I understand this fully yet, but it could be that
>> none of them work...
>
> Well, you're half right :-)
Ok, so let's drop bar2() and bar4().
scope ref int foo();
scope ref int bar1(ref int a) {
return a;
}
ref int bar3(ref int a) {
return a;
}
ref int baz_noscope(/*scope*/ ref int a);
foo().bar1().baz_noscope();
foo().bar3().baz_noscope();
And now? In particular, will the return value of `bar3` be
treated as if it were `scope ref`?
More information about the Digitalmars-d
mailing list