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));