Happens on at least 2.050, 2.051.
import core.stdc.stdio; // Pollutes asm less than std.stdio.
struct Foo {
uint dummy = 0;
uint k = 0;
alias dummy this; // Yes, this line is necessary for reproducing the bug.
// This needs to be a function to reproduce the bug. Setting k directly
// doesn't cut it.
void put(uint element) {
k += element;
}
// rhs must be const to reproduce the bug.
void put(const Foo rhs) {
k += rhs.k;
}
}
void main() {
Foo foo1, foo2;
foo1.put(10);
foo2.put(42);
foo1.put(foo2);
printf("%d\n", foo1.k); // 10, should be 52
}
Comment #1 by k.hara.pg — 2011-06-21T19:36:13Z
More simple case:
----
struct S
{
int dummy;
alias dummy this;
}
int foo(int){ return 1; }
int foo(const(S)){ return 2; }
void main()
{
S s;
assert(foo(s) == 2);
}
----
It is the reason of this problem that the type matching levels through normal and alias this have same basis.
Bug still here in 2.059.
Kenji, what happened to your pull ?
Comment #4 by jens.k.mueller — 2012-11-13T02:36:38Z
Today I ran into this bug. Unfortunately it tooks quite some time until I had a minimal example that exemplified the problem. Then I could search the database to find this report here.
I leave my minimal example here for reference.
struct A
{
B b;
alias b this;
}
struct B
{
static struct Value
{
}
Value value;
B[] bs;
alias value this;
bool opEquals(ref const B rhs) const // remove const in front of B and it works
{
return this.bs == rhs.bs;
}
}
unittest
{
A a;
a.bs ~= B.init;
B b;
b.bs ~= B.init;
assert(b.opEquals(a)); // fails
}
This is Linux and dmd2.060.
This issue is a blocker for me because I can't use const and alias this anymore. I have to remove the const which makes my code error-prone.
Comment #5 by k.hara.pg — 2014-02-09T23:10:13Z
*** Issue 12117 has been marked as a duplicate of this issue. ***
Comment #6 by schuetzm — 2014-07-22T17:52:03Z
Just tested with latest DMD git. Jens Mueller's example passes now, but the other ones still fail.
Comment #8 by razvan.nitu1305 — 2018-09-18T22:22:00Z
*** Issue 9354 has been marked as a duplicate of this issue. ***
Comment #9 by bugzilla — 2018-10-06T09:08:57Z
I simplified it a bit more, so it happens at compile time:
struct S {
int dummy;
alias dummy this;
}
int foo(int){ return 1; }
int foo(const(S)){ return 2; }
void test() {
static assert(foo(cast(const)S.init) == 2); // pass
static assert(foo(S.init) == 2); // fail
}
Here's the trouble. With alias this, the conversion of S to int is considered an 'exact' match, while the conversion of S to const is considered a 'constant' match, which is not as good as 'exact'. Hence, the 'exact' is selected and foo(int) is called.
The levels of conversion are:
nomatch
convert
constant
exact
We could change an alias this conversion to a 'convert' match, but it is unknown how much breakage this will cause. It seems to be a rather drastic change.
The compiler source code is the TypeStruct.implicitConvTo() function in mtype.d.
Comment #10 by razvan.nitu1305 — 2018-10-08T10:55:12Z