External Issue: Integer Literal Corrupting Expression

27209, "damianmoz", "Integer Literal Corrupting Expression", "2025-05-03T01:58:12Z"

Integer literals seem to be doing bad things to my integer expressions.

Over 5 years ago, Chapel's floating point expressions gave me grief for ages with their interesting handling of literals, implicit conversions, param definitions, and so on. My attempts at an explanation of the problems I encountered were woeful. My somehow Michael saw through the words, identified the issues, and addressed them. Not quite sure of the details but they work.

It looks like a similar or related issue exists with integral types. I hope my explanations are better this time.

While I have a way around the issues with coercions all over the place, I hate using a sledge hammer. Such a solution flies in the face of having easy to read code that reflects the underling mathematics. I want the algebra behind my algorithm, and the code to implement it, to correlate.

Here is my take (which could be obscured by some other underlying problem that I cannot see):

The problem seems to stem from the default typing of integral literals. From what I can see, in floating points arithmetic, Chapel downgrades the type priority of literals when they mix with an explicitly typed identifier in an expression. Did I get that right Michael? That way, they do not impact what the programmer is saying he or she wants. This appears to not be the case with integer literals based on some recent experience. Note that I could be pointing at the wrong culprit.

The problem in the previous paragraph then fights with Chapel's integer implicit conversions rules which I do not believe are wrong but are where the problem manifests itself and breaks my code. They were the source of many, many lost days of debugging time and frustration over a week ago.

Every expression has a type. It is not open for negotiation, or as the programmer, I should be able to optionally demand it. That type needs to propagate. Integer literals in an expression should not affect that type. Those literals have a generic type rather than an explicit type and they should never affect the type of an expression containing either explicitly typed identifiers or what I like to call an anonymous identifier, e.g. 1:int(16).

And Chapel has this concept that an integral expression can auto-promote. As I read the LIA (language independent arithmetic) standard, IEC 10967, this is illegal. As some standards are a bit strange, and IEC 10967 is so very dry that it makes my head hurt, let's ignore it but keep its spirit. Mind you, if integers were instead floating point numbers, it would most certainly be illegal as per IEEE 754. So, it is very shaky ground. Any auto-promotion is at odds with most other languages, which means that if one is porting code from another language to Chapel, or using Chapel as a reference language to publish an algorithm, the former cases have an obscure source of error which will be hard to find and the latter case is a ticking time bomb.

For practical examples, it appears that Chapel division of an unsigned integer does not evaluate to an unsigned integer? For starters, that violates mathematics. And incrementing a uint(w) by 1 somehow morphs into an int(2*w). Trying to avoidance overflow by some auto-expansion of the set of numbers that a basic type represents is never applicable in the former case and applicable one one in a billion (1 in 2^30) times for the latter. Besides, I need to identify overflows in my code and fix them. If I have an overflow, it means I screwed up hugely. A new user looking at it thought that the current approach seemed to be about burying that condition and hoping it went away. Instead, I need to fix my bug. That uplifting of the type is also not generic - what happens if one is working with the largest integral type supported. It fails. While it is unlikely with int(64), it still fails and is problem waiting to happen. And what about an array of DSPs, an ideal application for Chapel, with no support for an int(64)?

Also, the above seems to result in param and const declarations of integral expression showing inconsistent behavior. The param is wrong. The const is correct. But let's leave that bug for now. If the underlying problems that I have noted here are fixed, that bug will likely fall out in the wash.

While I have some suggestions, I need to better understand the deeper issues better before I offer them. And others may have a better ones so then I do not have to put my ignorance on show.