June 13, 2021
On 13.06.21 04:58, Walter Bright wrote:
> You're right. @system then.

Even an @system function must obey the spec (as long as it's called correctly). An @system `move` still wouldn't be allowed to do `target = source;` when `source` is `scope`.

A way forward could be leaving `scope` off:

----
void move(ref int* source, ref int* target) @safe
{
    target = source; /* ok now */
}
----

Then one has to use @trusted when calling `move` one `scope` things:

----
void main() @safe
{
    int* source1;
    int* target1;
    move(source1, target1); /* non-scope things just work */

    int local;
    int* source2 = &local;
    () @trusted { /* scope things need @trusted */
        scope int* target2;
        move(source2, target2);
    } ();
}
----

As always, applying @trusted correctly is hard and prone to errors.

If you don't want to change the language, it seems to me that replacing `move` with a function that has the parameters swapped is the way to go.
June 13, 2021

On Friday, 11 June 2021 at 10:27:19 UTC, Dennis wrote:

>

On Friday, 11 June 2021 at 03:12:29 UTC, Walter Bright wrote:

>

Hence a simple solution:

Make move() @trusted.

I don't think that makes sense. move is @safe anyway for non-scope inputs, and for scope inputs you wouldn't want it to lie about its interface (pretending it's scope when it isn't). Also you don't want it to call a @system move constructor in @safe code.

>

Write an @safe alternative to move() with the parameters swapped.

What would that alternative be called?

Challenge: Provide a code example illustrating how the existing variant of move compiles when it shouldn't—or errors when it shouldn't—while the alternative form works correctly.

I actually couldn't do it... it may be harder than we suspect.

June 13, 2021

On Sunday, 13 June 2021 at 11:59:49 UTC, ZachAttack! wrote:

>

Challenge: Provide a code example illustrating how the existing variant of move compiles when it shouldn't—or errors when it shouldn't—while the alternative form works correctly.

I actually couldn't do it... it may be harder than we suspect.

Ok I found out how to do it. It requires the arguments being passed to move to be qualified with scope:

void move1(ref int* source, scope ref int* target) @safe {
    target = source;
}

void move2(scope ref int* target, return ref int* source) @safe {
    target = source;
}

void main() @safe {
    scope int* src;
    scope int* tgt;
    move2(tgt, src); // pass
    move1(src, tgt); // Error: scope variable `src` assigned to non-scope parameter
    () @trusted{ move1(src, tgt); }(); // passes correctly
}

The source parameter in move1 above cannot be marked scope without an error. Thus, the error when move1 is called is unavoidable.

Apparently, only those moves involving scope variables—a very small percentage—will be falsely flagged by the compiler as unsafe.

If this is the only price that is being paid for the language limitation, it would seem impossible to justify a language change.

Therefore, I suspect Walter's "simple" solution, involving no language change, is the best one.

However, marking move (or functions like it) as @system is overkill.

Since only a very small percentage of calls to move and similar functions will be flagged wrongly, I believe the right solution is to document functions of this form, saying that otherwise @safe calls to them may occasionally need to be wrapped in @trusted blocks, to avoid the compiler falsely identifying them as having escaping pointers.

June 15, 2021

On Saturday, 12 June 2021 at 23:21:02 UTC, Walter Bright wrote:

>

Consider:

a = b;

Naturally, it moves right to left. We already have a word for that in the library, "emplace".

emplace is currently used to construct an object on top of uninitialized memory. I don't think adding an overload to emplace that acts as move is going to work; even if it doesn't give overload conflicts, it will become difficult to determine whether emplace(x, y) is a move that destructs x or emplacement that initializes x with y.

Also not that currently moveEmplace exists, and it has the same (source, target) parameter order as move.

How about defining moveTo(source, target) and moveFrom(target, source) with an alias move = moveTo for backwards compatibility?

1 2 3 4 5 6
Next ›   Last »