Xojo Can't Compare
By Thom McGrath on
I will never fault a developer for their bugs, because it's part of the job. We are imperfect humans trying to teach perfect computers how to do their jobs. But sometimes the bug fixing process goes wrong, and that's what this is all about.
When a compiler has an arithmetic bug, it's embarrassing, but it happens. The bug gets fixed, and you move on with your life. When an arithmetic bug exists for 12 years without being fixed, that's disgraceful. When the developer categorically refuses to fix the bug, it's downright indefensible.
Xojo has a problem comparing integers of differing types. This is because it tries to find a common type between the two types being compared, but there's no common type for many of the integer types.
Here's an example of the problem:
Var FirstValue As UInt32 = 4294967295 Var SecondValue As Int32 = -2147483648 If FirstValue > SecondValue Then // Won't Reach Here End If
The block will never be entered because FirstValue and SecondValue are considered equal. In an effort to compare the two, the compiler converts
FirstValue into an Int32, which becomes the same value as
SecondValue. While some developers will say the two types should not be compared, there's two issues I have with this logic.
- My first grader can figure out which is larger. So should the compiler.
- Xojo's target audience is people that don't understand the nuances of binary data.
The bug becomes even more nasty though. Consider this code:
Var Value As UInt32 = 4294967295 If Value > 100 Then // Won't Reach Here End If
In a 32-bit application, this block will also never be entered for the same reason.
Value gets converted to an Int32 to match the type of the literal 100.
The workaround is to cast the literal into a UInt32:
Var Value As UInt32 = 4294967295 If Value > CType(100, UInt32) Then // You Will Reach Here End If
In a 64-bit application, comparing to 100 will work fine because
Value will be converted to an Int64 which has no problem containing the value. However the problem still exists in 64-bit applications once larger values are reached:
Var Value As UInt64 = 18446744073709551615 If Value > 100 Then // Won't Reach Here End If
A 64-bit application really just means it'll be harder to notice the bug. It's still there.
When I original ran into the bug, I found Case #11935 and added my sample project. It was opened and verified 10 years ago, while I was working for Xojo. That really bothered me that we let this was issue slip through the cracks. Turns out the original report is even older. Case #2218 is the 12 year old original, but closed as by design. Aaron Ballman makes the case that changing how the literal is interpreted will lead to subtle bugs, and he's absolutely right.
The issue at hand is that only solves the problem when comparing against a literal. The issue is the comparison itself, not the literal. That's why Case #11935 is much more interesting, as Thomas Tempelmann proposes a solution. I'm not a compiler engineer, so I'm not sure how viable it is, but it's a potential solution.
In an effort to get some attention in the issue, I made a forum thread, and boy did it get attention. A few other solutions were proposed, such as using basic logic or doing the comparison with infinite precision integers. Just to reiterate, I'm not certain how viable each solution is, but there are potential solutions.
Xojo's response did not go as I expected. After 176 replies, they closed the forum post without any rules having been broken. Originally, their argument was that fixing the bug may break legacy code. It's a legit concern with any fix, but I can't think of any way that fixing a broken comparison would lead to broken code. I've asked Xojo for an example, which they haven't provided. Nobody has been able to come up with an example of code that relies on comparisons being done incorrectly.
If the bug were fixed, all of the above examples would begin to work, including the one with the explicit cast into UInt32. As much as I want this bug fixed, my intention is to prove Xojo right. I want to see code that would work worse with this fix in place than without the fix. So far I have been unable to do so.
As that argument fell apart, Xojo's reasoning was shifted to a combination of "it's not a bug" and "it's not worth fixing." Logically, it can't be both. It's either not a bug and therefore can't be fixed, or it's it is a bug but not worth fixing. And because of that, I have to believe that Xojo's excuse is just that: an excuse.
On top of that, all the bugs reported on the issue have been closed. This prevents them from being ranked, and Xojo uses rank to evaluate their priorities. Part of their logic is since it's unranked, it doesn't affect a lot of people. But since it's closed, it can't be ranked. This equates to a "stick your fingers in your ears and pretending it's not happening" tactic.
I believe the real reason they refuse to fix this bug is that they just can't. Xojo does not have a compiler engineer anymore. They don't have somebody on staff who is able to write the unit tests, evaluate the behavior, make the changes, and test the results. I know even if I were still with Xojo, I wouldn't be able to.
This is an embarrassing bug and indefensible response. Please spread this. Put pressure on Xojo to fix the bug. Make noise. Based on the closing of the forum post, Xojo's goal is to ignore this until we forget about it. So my goal is to get this into the eyes of potential customers. What customer would want a tool that can't get its comparisons right?