Bug 23747 – 'auto ref' function return signature does not flag escaping a reference to local variable

Status
RESOLVED
Resolution
INVALID
Severity
minor
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2023-02-27T00:00:28Z
Last change time
2023-02-28T09:32:23Z
Assigned to
No Owner
Creator
Mike S

Comments

Comment #0 by Michael.Shah — 2023-02-27T00:00:28Z
Per the spec on 'auto ref' https://dlang.org/spec/function.html#auto-ref-functions, I am not seeing the same behavior with 'auto ref' for flagging escaped local references as shown in the section on ref-functions: https://dlang.org/spec/function.html#ref-functions ``` // Tested on: // DMD64 D Compiler v2.102.1 import std.stdio; // The compiler will correctly // flag this as a local variable 'i' escaping. //ref int Func1(){ // int i=1; // return i; //} // BUGGY Behavior // 'i' should be inferred as an 'int, thus a // 'ref int' return value same as above. ref auto Func2(){ int i=2; return i; } // BUGGY Behavior // Same as above, with explicit return type auto ref int Func3(){ int i=3; return i; } // Correct behavior // Compiler flags `p` escaping a reference to local variable //ref int* Func4(){ // int i=4; // int* p = &i; // return p; //} // BUGGY behavior ref auto Func5(){ int i=4; int* p = &i; return p; } void main(){ auto two = Func2(); writeln(two, ":", typeid(two)); auto three = Func3(); writeln(three, ":", typeid(three)); auto five = Func5(); writeln(five, ":", typeid(five)); } ```
Comment #1 by razvan.nitu1305 — 2023-02-27T12:10:10Z
This bug report is invalid. All of the `auto ref` functions work as expected. `Auto ref` does not mean "ref + type deduction", but rather "deduce if a function may return by ref + type deduction". In all the situations presented, the compiler sees that it returns a reference to the stack and therefore chooses to drop the ref and return by value. You can add this code and see the types of the functions: pragma(msg, typeof(&Func1)); -> int function() ref pragma(msg, typeof(&Func2)); -> int function() pure nothrow @nogc @safe I guess the spec indeed is misleading by stating that "they become ref functions if all return expressions are lvalues". Actually, its more like "they become ref functions, if possible".
Comment #2 by Michael.Shah — 2023-02-27T23:06:33Z
Ah noted, that is perhaps my mistake then. Looking at the specification again with this in mind, I now see how 'auto ref' is deducing the 'refness' of a function. This means 'auto ref' snd 'ref auto' have different meanings then to be clear? - 'auto ref' deducing if it is possible to return by reference, and 'ref auto' explicitly indicating return by reference, and deduce the type (e.g. auto may be a double if possible return values are 1.0 and 1)
Comment #3 by razvan.nitu1305 — 2023-02-28T09:32:23Z
(In reply to Mike S from comment #2) > Ah noted, that is perhaps my mistake then. Looking at the specification > again with this in mind, I now see how 'auto ref' is deducing the 'refness' > of a function. > > This means 'auto ref' snd 'ref auto' have different meanings then to be > clear? > > - 'auto ref' deducing if it is possible to return by reference, and 'ref > auto' explicitly indicating return by reference, and deduce the type (e.g. > auto may be a double if possible return values are 1.0 and 1) No, `auto ref` or `ref auto` is the same thing. If you want to have a ref return type that is deduced you can simply omit the return type. The following example showcases that `auto ref` and `ref auto` are the same thing: // dmd -c test.d auto ref fun() { int x; return x; } ref auto fun2() { int x; return x; } int t; auto ref fun3() { return t; } ref auto fun4() { return t; } ref fun5() { return t; } ref fun6() { int x; return x; // error } pragma(msg, typeof(&fun)); pragma(msg, typeof(&fun2)); pragma(msg, typeof(&fun3)); pragma(msg, typeof(&fun4)); pragma(msg, typeof(&fun5));