Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move constructor is silently ignored if no copy constructor is declared #20942

Open
maxsamukha opened this issue Mar 3, 2025 · 4 comments
Open

Comments

@maxsamukha
Copy link

From the specification (https://dlang.org/spec/struct.html#struct-move-constructor): "3. If a move constructor is declared, also declare a copy constructor". The subitem can be ambiguously interpreted as a requirement or recommendation.

struct S
{
    int x;
    static int moves;

    this(S s)
    {
        ++moves;
    }

    /+ Uncomment to make `this(S)` behave as a move constructor
    this(ref S s) 
    {
    }
    +/
}

void main()
{
    S s;
    auto s2 = __rvalue(s);
    assert(S.moves == 1);
}

The move constructor is silently ignored if the copy constructor is not declared. If that's an intended behavior (in the absence of a copy constructor, treat the move constructor as an ordinary constructor), it should be clarified in the specification. Otherwise, there should be an error/warning/deprecation.

@TurkeyMan
Copy link
Contributor

Funny you bring this up! I just divined from Walter today actually that he had trouble with the implementation where there was some code breakage relating to existing structs that already had something like a move constructor... so he banked on the fact that it was previously impossible to define both a copy and move constructor, and only in that previously impossible case are the move semantics activated.

I was surprised to learn this and I think it's not good, but I also recognise that it creates a migration path.
So yes, right now you must define both to enable move semantics, and if you fail to do that, you get surprising behaviour! I intend to push that in the future we deprecate the case where a struct only has a move constructor so that it will eliminate the confusion.

In the event that you want to describe a move-only type, you would define both but @disable the copy. I haven't tested that case yet myself, but I think it's an important case to support and I have it in mind for unit tests.

@maxsamukha
Copy link
Author

maxsamukha commented Mar 3, 2025

I've just tested the case with the copy constructor explicitly disabled. It seems to behave as expected (__rvalue invokes the move constructor, copy construction fails to compile).

@TurkeyMan
Copy link
Contributor

Great. There's a bunch of other edge cases that will need comprehensive tests. I have a test suite that's not pushed anywhere yet which discovered several edge cases. The initial PR is not complete by any means, but we're making progress after so many years, so that's good!

@maxsamukha
Copy link
Author

Yeah, it's refreshing to see you stirring up the D swamp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants