`return ref`, DIP25, and struct/class lifetimes
Dicebot via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon May 16 08:33:09 PDT 2016
tl; dr: DIP25 is so heavily under-implemented in its current
shape it can be considered 100% broken and experimenting will
uncover even more glaring holes.
To be more precise, judging by experimental observation,
currently dip25 only works when there is explicitly a `ref`
return value in function or method. Any escaping of reference
into a pointer confuses it completely:
ref int wrap ( return ref int input )
{
return input;
}
ref int badWrapper()
{
int x = 5;
return wrap(x); // Error: escaping reference to local
variable x
}
void main()
{
auto badWrap = badWrapper();
}
vs
struct S
{
int* ptr;
}
S wrap ( return ref int input )
{
return S(&input);
}
S badWrapper()
{
int x = 5;
return wrap(x); // OK!
}
void main()
{
auto badWrap = badWrapper();
}
vs
struct S
{
int* ptr;
}
ref S wrap ( return ref int input )
{
static S tmp; // spot another hole :)
tmp = S(&input);
return tmp;
}
ref S badWrapper()
{
int x = 5;
return wrap(x); // Error: escaping reference to local
variable x
}
void main()
{
auto badWrap = badWrapper();
}
You can probably spot the pattern here - compiler matches `return
ref` in parameter declaration to `ref` in return value and
enforces identical lifetime for those. No `ref` in return value -
no enforcing, but it will also happily accept nonsense `return
ref` annotations.
Theoretically it was supposed to be protected by `@safe`
attribute as one can't take address of local variable in safe
code. But there isn't any way to write such wrapper struct
without using pointers AFAIK.
In your actual example putting `return` on `get` method
annotation is additionally very misleading because it only
implies ensuring result does not outlive struct instance itself -
but it gets passed around by value anyway.
More information about the Digitalmars-d-learn
mailing list