[Issue 20752] New: __traits(isReturnOnStack, func) is incomplete and can't be trusted

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Apr 20 02:08:44 UTC 2020


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 at puremagic.com
          Reporter: pro.mathias.lang at 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 at repro.d(61): Assertion failure
----------------
??:? _d_assertp [0x10628dcbd]
??:? _Dmain [0x10627192a]
```

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

--


More information about the Digitalmars-d-bugs mailing list