On Friday, 14 April 2023 at 10:31:58 UTC, kdevel wrote:
> But in fact it is returned unless it is return ref
.
When using return ref
, return scope
, scope
etc., you should be using the latest compiler and annotate functions you want checked with @safe
. In previous versions, the compiler would often conflate return ref
and return scope
, and it was also inconsistent in whether it would do checks in @safe
, @system
, and even 'default/unannotated' functions.
Now, it is more consistent, performing checks in @safe
code only.
> I don't get it! Is there any legitimate use of returning a ref such that it outlives the matching argument's lifetime? If not: Isn't this return ref
completely redundant?
The annotation is needed because the compiler can't always figure out what you're doing with a ref
parameter:
ref int mysteryFunc(ref int x) @safe; // external implementation
ref int escape() @safe
{
int local; // allocated on stack frame, should not escape this function
return mysteryFunc(local); // is this safe?
}
Is this indeed @safe
? It is, provided that mysteryFunc
doesn't return its parameter x
. It can be implemented like this for example:
ref int mysteryFunc(ref int x) @safe
{
x++;
return *(new int);
}
But it wouldn't be safe if x
were returned, so the compiler must know about that when it happens, hence return ref
:
ref int mysteryFunc(return ref int x) @safe
{
return x;
}
Now the compiler can catch that return mysteryFunc(local)
is unsafe. Note that if mysteryFunc
is a template function, nested function, or returns auto
, then the compiler infers attributes automatically, including return ref
. Then you can still write it as mysteryFunc(ref int x)
and it will automatically be treated as return ref
.