On Saturday, 27 June 2015 at 00:13:08 UTC, kinke wrote:
On Thursday, 25 June 2015 at 10:10:42 UTC, Jonathan M Davis wrote:
Whether a reference escapes is an orthogonal issue. The return attribute is for dealing with that. The function should be able to return by ref or not and still accept both rvalues and lvalues for its parameters. As long as the temporary variable created for holding an rvalue exists for the duration of the statement that the function call is in, it doesn't matter.

When I was talking about escaping references, I didn't mean returned references; I meant storing a pointer to a ref parameter somewhere outside (global/instance variable).

That's a completely orthogonal issue to ref or auto ref. That's an @system operation (since taking the address of a local variable is @system), and it's up to you to not screw it up. scope might cover that if it were fully ironed out, since that does involve escaping, but it also might not, since it's an @system operation and thus up to you not to screw it up. Regardless, it has nothing to do with whether the function accepts lvalues and rvalues with the same parameter. You have a safety issue regardless if you're talking about taking a pointer to an argument (or to some portion of the argument), since there's no guarantee that the lifetime of the pointer is shorter than that of the argument. That depends entirely on what the argument was or what you do with the pointer, and very few variables have a global lifetime, so whether the argument passed to the ref parameter referred to a local variable is pretty much irrelevant. You have to know what you're doing with you take the address of a variable and make sure that you do it right.

Safety with regards to ref is an entirely different issue, because that's @safe code. Also, whether the function might return its ref parameter by ref is orthogonal to whether it accepted an rvalue by ref or not, since whether you want to do that or not doesn't necessarily have anything to with what's being returned from the function (rather, it has to do with what you want the function to accept), and you have a safety issue even without having any kind of ref which accepts rvalues, because all it requires is multiple layers of functions which return by ref, and you're screwed anyway. e.g.

ref int id(ref int i)
{
    return i;
}

ref int foo(ref int i)
{
    ++i;
    return id(i);
}

ref int bar()
{
    int i;
    return foo(i);
}

We introduced the return attribute (currently only with -dip25) to fix this problem. So, with that, we eliminate the safety problem with ref itself, and we can safely have auto ref accept rvalues by having it assign them to a temporary variable first. The rules with returning by ref would then be the same with auto ref as ref and require the return attribute to return a parameter. And all of this is within @safe code.

Any issues with taking pointers to arguments is firmly in @system territory and is thus completely orthogonal. Even if scope were to be implemented in a way that prevented it, it would still have nothing to do with whether the function accepted both rvalues and lvalues with the same parameter.

In the meantime, what about making all `ref` params accept rvalues

Please, please, no. ref indicates that your intention is to mutate the argument. Having it accept rvalues completely destroys that and makes it that much harder to understand what a function is supposed to do. By having a separate attribute such as auto ref which also accepts rvalues, we cleanly separate out the code which just wants to accept both rvalues and lvalues for efficiency purposes and the code that actually wants to take its argument by ref so that it can mutate it.

- Jonathan M Davis

Reply via email to