return by auto ref horribly broken ?
Zach the Mystic
reachBUTMINUSTHISzach at gOOGLYmail.com
Tue Feb 19 10:58:59 PST 2013
On Tuesday, 19 February 2013 at 10:16:47 UTC, monarch_dodra wrote:
> On Monday, 18 February 2013 at 21:32:13 UTC, Zach the Mystic
> wrote:
>> On Monday, 18 February 2013 at 11:10:38 UTC, monarch_dodra
>> wrote:
>>> I think I'm opening a can of worms here, in regards to
>>> inferring the escape of references, but a quick investigation
>>> showed me that return by auto-ref is horribly broken.
>>>
>>> Basically, the only thing it does is check if the very last
>>> value it returns is a ref, but a ref to what? The
>>> possibilities of returning a ref to a local are HUGE. For
>>> example, simple returning the index of a tuple, or of a
>>> static array, and you're in it deep:
>>>
>>> //----
>>> import std.typecons;
>>>
>>> auto ref foo(T)(auto ref T t)
>>> {
>>> return t[0];
>>> }
>>>
>>> void main()
>>> {
>>> int* p = &foo(tuple(1, 2));
>>> }
>>> //----
>>>
>>> Here, both foo will return a ref to a local. But the compiler
>>> won't see, and more importantly, it gets blind sided because
>>> it *can't* see it (AFAIK).
>>
>> If you take the address of a value returning type, you must
>> either ban doing it outright or treat the assigned pointer as
>> dangerous. To take the address of a value type returned from
>> the stack is especially dangerous - I can see banning it
>> outright and I don't know what the spec currently says about
>> this.
>
> What I wanted to show was that since the code compiled, foo
> returned by ref. At this point, the assigned pointer shouldn't
> even be considered as "dangerous", since we are already in
> undefined behavior.
Well, "extra dangerous" then, undefined, and probably should be
detected and made illegal.
> I could have replaced the code with:
> "int a = foo(tuple(1, 2));"
>
> The bug would have been less obvious, but there are chances
> this creates a (very) hard to catch bug.
Well, my guess would be that this is actually safe, because a is
assigned by value here and not by reference. (Unless you're
saying that foo ends up smashing tuple(1,2)'s location, but yeah,
this is referring to a part of the stack which should be
considered 'void'.)
>> My assumption would be that the only legal version of this
>> would be the one which returns 'ref'. But tuple(1,2) is an
>> rvalue struct type if I'm not mistaken, which means it would
>> be passed as a value. The compiler should not allowed a type
>> passed as a value (or any part of that value) to be returned
>> as a reference, right? So I don't see a way to take the
>> address of this result legally. I don't think it should return
>> a reference at all with 'tuple(1,2)'. That's all I know.
>
> Indeed, there is no way to take the address of the returned
> value in this case, since it shouldn't return by ref.
>
> But it does...
I will start by assuming it's a bug and not a problem with
language design. There are clear points at which it cannot be
justified to be considered legal, from my perspective. I'll file
it as a bug.
http://d.puremagic.com/issues/show_bug.cgi?id=9537
My guess is that 'foo' doesn't realize that 't[0]' is a reference
derived from a local parameter.
More information about the Digitalmars-d
mailing list