D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2701 - Can't declare struct, assign lvalue via opAssign in same statement
Summary: Can't declare struct, assign lvalue via opAssign in same statement
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86 Windows
: P2 normal
Assignee: No Owner
URL:
Keywords: rejects-valid, spec
Depends on:
Blocks:
 
Reported: 2009-03-01 19:34 UTC by David Simcha
Modified: 2015-06-09 01:21 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description David Simcha 2009-03-01 19:34:42 UTC
struct Bar {
    uint num;

    Bar opAssign(uint otherNum) {
        num = otherNum;
        return this;
    }
}

void main() {
    uint foo = 1;
    Bar bar = foo;  // Error:  e2ir:  cannot cast from uint to Bar.
    Bar bar2;
    bar2 = foo;   // Works.
}

Not sure if this is actually a valid bug, since the spec states that "The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type."  However, if the previous sentence does implicitly disallow this from working, it should be stated more clearly, instead of in a single sentence of language legalese.
Comment 1 Daniel Keep 2009-03-01 20:59:44 UTC
You can't use opAssign for initialisation; you have to use opCall.  Specifically,

Bar bar = foo;

is rewritten as:

Bar bar = Bar(foo);

which is further rewritten as:

Bar bar = Bar.opCall(foo);

I'm not sure if this is documented explicitly anywhere; I just remember this from when it was implemented.
Comment 2 David Simcha 2010-08-15 21:11:33 UTC
I'm closing this, since this appears to be what C'tors are for.  The following example demonstrates.  Perhaps this should be better documented, though.

struct Bar {
    uint num;

    this(uint otherNum) {
        opAssign(otherNum);
    }

    Bar opAssign(uint otherNum) {
        num = otherNum;
        return this;
    }
}

void main() {
    int foo = 1;
    Bar bar = foo;  // Error:  e2ir:  cannot cast from uint to Bar.
    Bar bar2;
    bar2 = foo;   // Works.
}