www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 20752] New: __traits(isReturnOnStack, func) is incomplete and

https://issues.dlang.org/show_bug.cgi?id=20752

          Issue ID: 20752
           Summary: __traits(isReturnOnStack, func) is incomplete and
                    can't be trusted
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: pro.mathias.lang gmail.com

Since half of the logic for NRVO is in the backend, this traits simply cannot
be relied on and is mostly useless.
For example, the following compiles and triggers the assert with DMD:

```
import std.meta;
import std.traits;
import std.stdio;

T deserializeFull (T) (scope ubyte[] delegate(size_t) dg)
{
    static if (is(T == ulong))
    {
        ulong ret = *cast(ulong*)(dg(ulong.sizeof).ptr);
        return ret;
    }
    else static if (is(T == ulong*))
    {
        return null;
    }
    else static if (is(T == struct))
    {
        Target convert (Target) ()
        {
            auto x = deserializeFull!Target(dg);
            return x;
        }
        auto enableNRVO = T(staticMap!(convert, Fields!T));
        return enableNRVO;
    }
    else
        static assert(0);
}

struct FooBar
{
    this(Repeat!(6, ulong) vals, ulong* ignored)
    {
        this.tupleof[0 .. vals.length] = vals;
        this.ptr = &this.a;
    }

    ulong a;
    ulong b;
    ulong c;
    ulong d;
    ulong e;
    ulong f;
    ulong* ptr;
}

struct WrapMe { FooBar fb; FooBar xc; }

void main ()
{
    //FooBar f;
    ubyte[WrapMe.sizeof] binary = 42;
    ubyte[] tmp = binary;

    scope ubyte[] delegate(size_t v) getter = (v) {
            scope(success) tmp = tmp[v .. $];
            return tmp[0 .. v];
        };
    auto final_ = deserializeFull!WrapMe(getter);
    writeln("ptr: ", final_.fb.ptr, " == ", &final_.fb.a);
    assert(final_.fb.ptr is &final_.fb.a);
    static assert(__traits(isReturnOnStack, deserializeFull!WrapMe));
}
```

LDC v1.20.1 compiles and run this just fine, but not DMD:
```
% dmd -run repro.d
ptr: 7FFEE998E3D8 == 7FFEE998E520
core.exception.AssertError repro.d(61): Assertion failure
----------------
??:? _d_assertp [0x10628dcbd]
??:? _Dmain [0x10627192a]
```

I would expect a compilation error, or the assert to pass.

--
Apr 19 2020