On Thursday, 3 January 2013 at 21:56:22 UTC, David Nadlinger
wrote:
I must admit that I haven't read the rest of the thread yet,
but I think the obvious and correct solution is to disallow
passing locals (including non-ref parameters, which are
effectively locals in D) as non-scope ref arguments.
The scope attribute, once properly implemented, would make sure
that the reference is not escaped. For now, we could just make
it behave overly conservative in @safe code.
David
If you disallow passing local variables as non-scope ref
arguments, then you effectively disallow all method calls on
local variables. My reasoning is as follows:
struct T
{
int get(int v) const;
void set(int v);
}
Those methods of T can be thought of as free functions with these
signatures:
int get(ref const T obj, int v);
void set(ref T obj, int v);
And these kinds of method calls:
T obj;
int n = obj.get(v);
obj.set(n);
...can be thought of as being converted to these free function
calls:
T obj;
int n = .get(obj, v);
.set(obj, n);
I don't know what the compiler does or doesn't do, but it is
*as_if* the compiler did this conversion from method calls to
free functions.
Now it's obvious, given those free function signatures, that if
you disallow passing function-local variables as non-scope
references, you also disallow this code:
void func()
{
T obj;
obj.set(123);
}
Because that would effectively be the same as:
void func()
{
T obj; // obj is a local variable
.set(obj, 123); // obj is passed as non-scope ref
}
Then, you might ask, why don't those methods of T correspond to
these free function signatures:
int get(scope ref const T obj, int v);
void set(scope ref T obj, int v);
And the answer is obviously that it would prevent these kinds of
methods:
struct T
{
int v;
ref T increment()
{
v++;
return this;
}
}
...because that would then convert to this free function
signature:
ref T increment(scope ref T obj)
{
obj.v++;
return obj; // Can't return a reference to a scope argument
}