www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Bug in tuple comparison?

reply Magnus Lie Hetland <magnus hetland.org> writes:
I guess this is getting old by now ... but I've come across yet another bug :->

This one is a bit obscure, and deals with comparing tuples in 
contracts. It seems that some type information about the result is lost 
when entering an out-block, or something. At least, DMD (2.052, OS X) 
is unable to infer types properly, and is therefore unable to compare 
tuples in some cases. Sample program follows. (Similar behavior occurs 
for other comparison operators as well.)

import std.typecons;
T[] func(T)(T[] arg)
out(result) {
    auto a = result[0];
    auto b = arg[0];
    auto c = result[0];
    // assert(c < a); // Doesn't work
    // assert(a < c); // Doesn't work
    // assert(c < b); // Doesn't work
    assert(b < c); // Works
}
body {
    return arg;
}
void main() {
    alias Tuple!(real, uint) Entry;
    func(new Entry[100]);
}

The error (when uncommenting one of the lines that don't work, e.g., 
line 7) is:

tuplecmpbug.d(7): Error: template 
std.typecons.Tuple!(real,uint).Tuple.opCmp(R) if (isTuple!(R)) does not 
match any function template declaration
tuplecmpbug.d(7): Error: template 
std.typecons.Tuple!(real,uint).Tuple.opCmp(R) if (isTuple!(R)) cannot 
deduce template function from argument types 
!()(const(Tuple!(real,uint)))

I take it this is a bug (or am I just missing something)? Is it a known 
bug? (Sorry if it's in the tracker; it can be hard to find equivalents 
there...)

-- 
Magnus Lie Hetland
http://hetland.org
Mar 24 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Magnus Lie Hetland:

 I guess this is getting old by now ... but I've come across yet another bug :->

The out(result) turns the result into a const, this causes some troubles you see in this simpler program: import std.typecons; void main() { alias Tuple!(int) T; const T t = T(); bool b = t == t; } Further reduction: struct Tuple(T) { bool opEquals(R)(R rhs) { return false; } } void main() { const Tuple!int t; bool b = t == t; } Bye, bearophile
Mar 24 2011
next sibling parent reply Magnus Lie Hetland <magnus hetland.org> writes:
On 2011-03-24 18:25:30 +0100, bearophile said:

 Magnus Lie Hetland:
 
 I guess this is getting old by now ... but I've come across yet another bug :->

The out(result) turns the result into a const,

Riiight! Yes, I've seen that it's const, and (naughtily) cast away the constness (without modifying anything) in some cases. It didn't occur to me that that was the problem here. :) (In my original program, I didn't notice that I had gotten one of the values from outside the out-block, while the other was from the result. I guess I was "primed" to think that that wasn't the problem ;) So the issue, then, I take it, is that you *can* compare a non-const tuple to a const-tuple, but you *cannot* compare a const-tuple to a non-const tuple (as per casting rules)? Makes sense. Would have been nice with a slightly more obvious error message, but I guess that's always a problem with templates in any form ;) Aanyway -- glad the bug was just in my code/brain :D Thanks for the help, - M -- Magnus Lie Hetland http://hetland.org
Mar 24 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Regardless, this _is_ a bug.

I agree. The second reduction I've written seems fit for Bugzila. Bye, bearophile
Mar 24 2011
parent bearophile <bearophileHUGS lycos.com> writes:
 I agree. The second reduction I've written seems fit for Bugzila.

http://d.puremagic.com/issues/show_bug.cgi?id=5783
Mar 24 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
 On 2011-03-24 18:25:30 +0100, bearophile said:
 Magnus Lie Hetland:
 I guess this is getting old by now ... but I've come across yet another
 bug :->

The out(result) turns the result into a const,

Riiight! Yes, I've seen that it's const, and (naughtily) cast away the constness (without modifying anything) in some cases. It didn't occur to me that that was the problem here. :) (In my original program, I didn't notice that I had gotten one of the values from outside the out-block, while the other was from the result. I guess I was "primed" to think that that wasn't the problem ;) So the issue, then, I take it, is that you *can* compare a non-const tuple to a const-tuple, but you *cannot* compare a const-tuple to a non-const tuple (as per casting rules)? Makes sense. Would have been nice with a slightly more obvious error message, but I guess that's always a problem with templates in any form ;) Aanyway -- glad the bug was just in my code/brain :D Thanks for the help,

If you const-ness affects comparison, that _is_ a bug. Currently, a struct's opEquals should take a "const ref Type rhs" and Tuple isn't doing that. So, that's a bug in Tuple. There are a number of const-correctness bugs in druntime and Phobos though - the mother of them all being http://d.puremagic.com/issues/show_bug.cgi?id=1824 Regardless, this _is_ a bug. - Jonathan M Davis
Mar 24 2011