May 06, 2023
https://issues.dlang.org/show_bug.cgi?id=23901

          Issue ID: 23901
           Summary: Spurious "Cannot move object [...] with internal
                    pointer"
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: wrong-code
          Severity: regression
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: dlang-bugzilla@thecybershadow.net

The error in the test case below emitted by Phobos. However, I suspect that it is a DMD code generation bug, because:

1. It disappeared when something in the DMD backend changed; 2. It does not manifest with LDC.

Poorly reduced test case:

////////////////////////////////// test.d ///////////////////////////////// public import std.algorithm.mutation : move;

import std.functional : forward;

auto functor3(int* state)
{
    struct Functor
    {
        int* state;

        this(int* i)
        {
        }
    }

    forward!state;

    return Functor();
}

auto functor4(alias fun, State...)(State state)
{
    struct Functor
    {
        State state;

        this(State state)
        {
            this.state = state;
        }

        auto opCall()
        {
            return state[0];
        }
    }

    return Functor(state);
}

auto functor5(State)(State )
{
    struct Functor
    {
        this(State);

        auto opCall()
        {
        }
    }

    return Functor();
}

auto functor6(alias fun, State...)(State state)
{
    struct Functor
    {
        State state;

        this(State state)
        {
            this.state = state;
        }

        auto opCall()
        {
            fun(state);
        }
    }

    return Functor(state);
}

auto functor7(alias fun, State...)(State state)
{
    struct Functor
    {
        State state;

        this(State state)
        {
            this.state = state;
        }

        auto opCall()
        {
            fun(state);
        }
    }

    return Functor(state);
}

auto functor8(alias fun, State)(State )
{
    struct Functor
    {
    }

    return Functor();
}

auto functor9(alias fun, State)(State state)
{
    return state;
}

auto functor10(State)(State state)
{
    struct Functor
    {
        State state;

        this(State state)
        {
            this.state = move(state);
        }

    }

    return Functor(state);
}

auto valueFunctor1(Value)(Value value) { return functor4!(v => v)(value); }

auto valueFunctor2(Value)(Value value) { return functor5(value); }

auto select1(Cond, T, F)(Cond cond, T t, F f)
{
    static fun(Cond cond, T t, F f)
    {
        cond()
            ? t()
            : f;
    }
    return functor6!fun(cond, t, f);
}

auto select2(Cond)(Cond cond)
{
    return cond;
}

auto tuple(Values...)(Values values)
{
    struct Tuple
    {
        Values values;
    }
    return Tuple(values);
}

auto tupleMap1(alias pred, Values...)(Values values)
{
    return tuple(values);
}

auto formattingFunctor1(T)(T values)
{
    return functor10(forward!values);
}

auto stringifiable1(F)(F functor)
{
    struct Stringifiable
    {
        F functor;

        void toString()
        {
            functor();
        }
    }
    return Stringifiable(functor);
}

auto fmtIf1(Cond, T, F)(Cond cond, T t, F f)
{
    static fun(X, Sink...)(X x)
    {
        x().formattingFunctor1;
    }
    return select1(
        cond.valueFunctor1,
        functor7!fun(t),
        functor8!fun(f),
    ).stringifiable1;
}

auto fmtIf2(Cond, T, F)(Cond cond, T t, F f)
{
    static fun()
    {
    }

    return select2(
        cond.valueFunctor2,
    );
}

auto fmtSeq1(Values...)(Values values)
{
    return
        values
        .tupleMap1!(value=> fmt);
}

int i;

struct Wand
{
    @property endl()
    {
        return functor3(&i);
    }
}

void main()
{
    Wand wand;
    auto v =
        fmtIf1(true,
            () => fmtSeq1(
                fmtIf2(true,
                    "",
                    "",
                ),
                wand.endl,
            ),
            "",
        )
        ;
    v.toString();
}
///////////////////////////////////////////////////////////////////////////

Introduced in https://github.com/dlang/dmd/pull/9434

--