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.