auto ref escaping local variable

Ali Çehreli via Digitalmars-d digitalmars-d at puremagic.com
Tue Jan 24 00:47:31 PST 2017


On 01/24/2017 12:12 AM, Patrick Schluter wrote:
 > On Tuesday, 24 January 2017 at 06:51:40 UTC, Stefan Koch wrote:
 >> On Tuesday, 24 January 2017 at 00:52:34 UTC, Robert burner Schadek 
wrote:
 >>> I have this program that used to compile with 72 but with 73 dmd is
 >>> complaining that
 >>> "Error: escaping reference to local variable t"
 >>>
 >>> auto ref f2(T)(auto ref T t, auto ref T s) {
 >>>     return t;
 >>> }
 >>>
 >>> auto ref f1(T)(auto ref T t, auto ref T s) {
 >>>     return f2(t, s);
 >>> }
 >>>
 >>> unittest {
 >>>     int a = f1(1,2);
 >>> }
 >>>
 >>> I'm not sure why, or how to fix that.
 >>>
 >>> https://issues.dlang.org/show_bug.cgi?id=17117
 >>
 >> Seems to work as expected.
 >> The literals 1,2 cannot be ref.
 >> Therefore it's a normal parameter.
 >> A function parameter is the same as a local
 >> hence retuning a ref to it will cause this to happen.
 >
 > Depends on what auto ref is supposed to do, I suppose. What is the
 > heuristic used to determine if it should handle a parameter as a
 > reference or as a copy?

Lvalues are passed by reference and rvalues are copied.

 > In the case of f1(1,2) it's obvious, as it is impossible to have a
 > reference on the literals, but for f(t, s); both are possible. In the
 > case of int and small parameter types sizes a copy would be faster.
 > So the question is, does auto ref use a reference as soon as it is
 > possible to have a ref, or should it do so only when it "knows" that it
 > is better for performance? I imagine, it's actually the first option.
 > (just thinking loud).

No, it has nothing to do with performance.

The problem with auto ref is that in the case of rvalues, what you have 
is a local variable, which makes it almost given that when it's 'auto 
ref', it better be 'auto ref const' because you don't want to mutate 
anyway because your mutations would be lost in the case of rvalues.

I'm under the impression (and started to write a blog post about) that 
the following two overloads is better than 'auto ref' (const or not). 
Given S is a struct,

   void foo(const(S));        // Takes rvalue
   void foo(ref const(S));    // Takes lvalue

Those two work with all kinds of S arguments: lvalue, rvalue, imuttable, 
different kinds of member indirections, etc.

If one wants mutability, or special handling for say, immutable, than 
add more overloads:

   void foo(const(S));        // Takes rvalue
   void foo(ref const(S));    // Takes lvalue except the following
   void foo(ref S);           // Takes mutable lvalue

etc.

Ali



More information about the Digitalmars-d mailing list