Another example of why this is a bad idea:

In std.parallelism, I have a function called TaskPool.put, which takes a Task object by reference, takes its address and puts it on the task queue. This is used for scoped tasks. However, it's safe because Task has a destructor that waits for the task to be finished and out of the task queue before destroying the stack frame it's on and returning.

Why can't we just establish a strong convention that, if a function truly escapes the address of a ref parameter (meaning it actually lives longer than the lifetime of the function), you take a pointer instead of a ref? It's not like escaping ref parameters unintentionally is a common source of bugs.

My point is that any rule we come up with will always be conservative. D is a **systems language** and needs to give the benefit of the doubt to assuming the programmer knows what he/she is doing. If you want extra checks, that's what SafeD is for.

On 8/14/2011 10:20 AM, Andrei Alexandrescu wrote:
Walter and I have had a long discussion and we thought we'd bring an
idea for community review.

We believe it would be useful for safety purposes to disallow escaping
addresses of ref parameters. Consider:

class C {
int * p;
this(ref int x) {
p = &x; // escapes the address of a ref parameter
}
}

Such code is accepted today. We believe it is error-prone and dangerous,
particularly because the caller has no syntactic cue that the address of
the parameter is passed into the function (in this case constructor).
Worse, such a function cannot be characterized as @safe.

So we want to make the above an error. The workaround is obvious - just
take int* as a parameter instead of ref int. What a function can do with
a ref parameter in general is:

* use it directly just like a local;

* pass it down to other functions (which may take it by value or
reference);

* pass its address down to pure functions because a pure function cannot
escape the address anyway (cool insight by Walter);

* take its address as long as the address doesn't outlive the frame of
the function.

The third bullet is not easy to implement as it requires flow analysis,
but we may start with a conservative version first. Probably there won't
be a lot of broken code anyway.

Please chime in with any comments you might have!


Thanks,

Andrei

Reply via email to