You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is kind of an ugly corner case, so it could be argued that it should be left as-is, but we could be generating an opAssign that works when we aren't. So, I don't know if this is really a bug or just an enhancement request. It could also be argued that once @disable gets involved, you really need to implement stuff manually, since it does get kind of weird otherwise. But I'm creating this issue so that the current situation is at least documented.
In any case, this code
```void main(){ import std.traits; static struct Member { @disable void opAssign(Member) {} void opAssign(ref Member) {} } static struct S { Member member; } Member m; Member m2; m = m2; m = Member.init; S s; S s2; s = s2; s = S.init;}```
results in
```q.d(16): Error: function `q.main.Member.opAssign` cannot be used because it is annotated with `@disable`q.d(20): Error: generated function `q.main.S.opAssign` cannot be used because it is annotated with `@disable`q.d(21): Error: generated function `q.main.S.opAssign` cannot be used because it is annotated with `@disable````
This code
```void main(){ import std.traits; static struct Member { @disable void opAssign(Member) {} void opAssign(ref Member) {} } mixin listOpAssign!Member; pragma(msg, ""); static struct S { Member member; } mixin listOpAssign!S;}template listOpAssign(T){ static if(__traits(hasMember, T, "opAssign")) { pragma(msg, "Overloads of opAssign for " ~ T.stringof); pragma(msg, "---"); static foreach(sym; __traits(getOverloads, T, "opAssign")) { pragma(msg, typeof(sym).stringof ~ ": " ~ (__traits(isDisabled, sym) ? "disabled" : "NOT disabled")); } } else pragma(msg, T.stringof ~ " has no opAssign");}```
prints
```Overloads of opAssign for Member---void(Member __param_0): disabledvoid(ref Member __param_0): NOT disabledOverloads of opAssign for S---ref S(S p): disabled```
So, Member is as expected. The rvalue overload is @disabled (and thus results in a compilation error when used), and the lvalue overload works just fine.
On the other hand, with S, only a single overload is created, and it's @disabled in spite of the fact that it doesn't need to be. The obvious implementation would be
```ref opAssign(S p){ this.member = p.member;}ref opAssign(ref S p){ this.member = p.member;}```
And because Member has a working opAssign that takes an lvalue, this could work.
Now, the reverse situation can't work, I don't think (at least not without doing some gymnastics with extra copies of S's member field) - that is when Member has an @disabled lvalue overload and a working rvalue overload. That currently results in exactly the same @disabled signature for opAssign on Member. However, it becomes problematic to implement opAssign in S even though there is a working one in Member, because while you might pass an rvalue to S's opAssign, S's opAssign will then naturally need to use an lvalue to assign to its member field, and that overload of Member's opAssign is @disabled. It _could_ be worked around by creating a copy that's an rvalue, but that seems like it's going too far for a compiler-generated function, and anyone who really wants that could do it themselves.
So, I don't know if we want to fix this situation or not, but it did surprise me, since I expected that since Member had a working opAssign, S would get one as well, and it doesn't.
The text was updated successfully, but these errors were encountered:
Jonathan M Davis reported this on 2024-11-11T04:19:59Z
Transferred from https://issues.dlang.org/show_bug.cgi?id=24854
Description
The text was updated successfully, but these errors were encountered: