I wrote a struct that having a std.datetime.SysTime member.
However this struct cannot copy from scope variable.

I think because SysTime has a immutable(TimeZone) member and it cannot copy to out of scope.

--------
struct A { SysTime timestamp; }

A createA() @safe
{
    scope a = A(Clock.currTime());

    // Error: scope variable a may not be returned
    return a;

    // OK
//return A(SysTime(a.timestamp.stdTime, a.timestamp.timezone));
}
--------
https://run.dlang.io/is/e3AID7

There is a similar situation when struct has string enum member.

--------
enum Tag { tag = "tag" }

struct A { Tag tag; }

A createA() @safe
{
    scope a = A(Tag.tag);

    // Error: scope variable a may not be returned
    return a;

    // NG
    // return A(a);
    // return A(a.tag);
}
--------
https://run.dlang.io/is/Y8v5RX

I have an unsightly workaround.

--------
import std;

enum Tag
{
    tag = "tag"
}

/// scope tag to unscope.
Tag unscope(scope Tag tag) @nogc nothrow pure @safe
{
    static foreach (e; EnumMembers!Tag)
    {
        if (e == tag)
        {
            return e;
        }
    }

    assert(false);
}

struct A
{
    Tag tag;

    /// add this for construct from value.
    this (Tag tag) @nogc nothrow pure @safe scope
    {
        this.tag = tag;
    }

    /// add this for copy to out of scope.
    this (ref scope const A a) @nogc nothrow pure @safe scope
    {
        this.tag = a.tag.unscope;
    }

    // cannot use formal copy constructor.
    /+
this (ref return scope const A a) @nogc nothrow pure @safe scope
    {
        this.tag = a.tag.unscope;
    }
    +/
}

A createA() @safe
{
    scope a = A(Tag.tag);

    // OK
    return A(a);
}
--------

I understand those errors are DIP1000 language design.
However I suppose that DIP1000 check can permit immutable pointer in some cases.

Is there a better workaround, practices or patterns?

Reply via email to