DIP69 - Implement scope for escape proof references
Walter Bright via Digitalmars-d
digitalmars-d at puremagic.com
Sat Dec 6 14:56:07 PST 2014
On 12/6/2014 5:30 AM, "Marc Schütz" <schuetzm at gmx.net>" wrote:
> On Friday, 5 December 2014 at 23:58:41 UTC, Walter Bright wrote:
>> As you point out, 'ref' is designed for this.
> I wouldn't call it "designed", but "repurposed"...
Perhaps, but the original reason to even have 'ref' was so it could be a
restricted pointer type that could be passed down a call hierarchy, but not up.
>
>>> 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]);
You are correct, and it remains to be seen if these occur enough to be a problem
or not. The workarounds do exist, though. Another workaround:
scope ref tmp = c[42];
becomes:
auto scope ref tmp() { return c[42]; }
> 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`?
Yes.
More information about the Digitalmars-d
mailing list