D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6906 - Cannot assign value into associative array if contains opAssign
Summary: Cannot assign value into associative array if contains opAssign
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2011-11-07 12:24 UTC by Jesse Phillips
Modified: 2013-09-07 10:01 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jesse Phillips 2011-11-07 12:24:00 UTC
This code fails to compile because the struct S implement opAssign and the compiler tries using it rather than the associative arrays insert.

    void main() {
       S[string] ss;
       S s;
    
       ss["hello"] = s;
    }
    
    struct S {
       void opAssign(int i) {
       }
    }

test.d(6): Error: function test.S.opAssign (int i) is not callable using argument types (S)
test.d(6): Error: cannot implicitly convert expression (s) of type S to int
test.d(6): Error: function test.S.opAssign (int i) is not callable using argument types (S)
test.d(6): Error: cannot implicitly convert expression (s) of type S to int
PS C:\Documents and Settings\jphillips\src\Juno> dmd test.d
test.d(5): Error: function test.S.opAssign (int i) is not callable using argument types (S)
test.d(5): Error: cannot implicitly convert expression (s) of type S to int
test.d(5): Error: function test.S.opAssign (int i) is not callable using argument types (S)
test.d(5): Error: cannot implicitly convert expression (s) of type S to int
Comment 1 Don 2011-11-07 23:07:16 UTC
I don't think this is a bug. I think the behaviour is intuitive.
ss["hello"] = s; looks like an assignment, and it currently behaves like one.
This code doesn't compile, either:

       S[2] ss;
       S s;
       ss[0] = s;

As you've defined it, S cannot participate in any assignment of any kind. You can't even write:
S s;
S t;
t = s;
Comment 2 Jesse Phillips 2011-11-08 07:16:04 UTC
Can I then say you aren't able to define opAssign for a struct and have it work for associative arrays:

    void main() {
       S[string] ss;
       S s;

       ss["hello"] = s;
    }

    struct S {
       void opAssign(int i) {
       }
       void opAssign(S s) {
           this = s;
       }
    }

/tmp$ ./test
Segmentation fault
Comment 3 Don 2011-11-08 22:59:29 UTC
(In reply to comment #2)
> Can I then say you aren't able to define opAssign for a struct and have it work
> for associative arrays:
> 
> /tmp$ ./test
> Segmentation fault

That's definitely a problem, but I don't think it has anything to do with AAs. This also creates a stack overflow:


    void main() {
       S s;
       S t;
       t = s;
    }

    struct S {
       void opAssign(S s) {
           this = s;
       }
    }

Obviously it's changing 'this = XXX' into 'this.opAssign(XXX)'.
Comment 4 Kenji Hara 2013-09-07 10:01:04 UTC
(In reply to comment #0)
> This code fails to compile because the struct S implement opAssign and the
> compiler tries using it rather than the associative arrays insert.
> 
>     void main() {
>        S[string] ss;
>        S s;
> 
>        ss["hello"] = s;
>     }
> 
>     struct S {
>        void opAssign(int i) {
>        }
>     }
> 
> test.d(6): Error: function test.S.opAssign (int i) is not callable using
> argument types (S)
> test.d(6): Error: cannot implicitly convert expression (s) of type S to int
> test.d(6): Error: function test.S.opAssign (int i) is not callable using
> argument types (S)
> test.d(6): Error: cannot implicitly convert expression (s) of type S to int
> PS C:\Documents and Settings\jphillips\src\Juno> dmd test.d
> test.d(5): Error: function test.S.opAssign (int i) is not callable using
> argument types (S)
> test.d(5): Error: cannot implicitly convert expression (s) of type S to int
> test.d(5): Error: function test.S.opAssign (int i) is not callable using
> argument types (S)
> test.d(5): Error: cannot implicitly convert expression (s) of type S to int

From 2.062, the code could work.

Even if a struct has only non-identity opAssign methods, identity assignment would be rewritten to the field-to-field assignment.

struct S
{
    int val;
    void opAssign(int i) {}
}

void main()
{
    S s;
    S s2;

    s = s2; // Rewite as: s.tupleof = s2.tupleof;
    s = 1;  // Rewrite as: s.opAssign(1)
}