auto ref is on the docket

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Fri Jun 26 18:18:17 PDT 2015


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


More information about the Digitalmars-d mailing list