ref is unsafe

Tommi tommitissari at hotmail.com
Thu Jan 10 06:53:04 PST 2013


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
}


More information about the Digitalmars-d mailing list