# Integer Promotion Weirdness

**URL:** <https://chapel.discourse.group/t/integer-promotion-weirdness/33886>\
**Category:** Users\
**Created:** [June 5, 2024, 1:59am UTC](https://chapel.discourse.group/t/integer-promotion-weirdness/33886 "2024-06-05T01:59:08Z")\
**Posts on this page:** 1\
**Showing post:** 29

<div class="post-metadata">

**Author:** ![mppf](https://avatars.discourse-cdn.com/v4/letter/m/94ad74/32.png) [@mppf](https://chapel.discourse.group/u/mppf)\
**Post date:** [December 18, 2025, 1:50pm UTC](https://chapel.discourse.group/t/integer-promotion-weirdness/33886/29 "2025-12-18T13:50:18Z")

</div>

> [@damianmoz](#):
>
> If you run with my idea that a lone naked literal defaults when evaluated to the smallest type that can capture the data, it is like calling
> 
> ```Chapel
> foo(42:int(8))
> 
> ```
> 
> which means it calls the first.

Indeed at some point during development of the fixes (that resolved the `real` problems for you), we had test failures because `sin(1)` started to return `real(32)` rather than `real(64)`.

Perhaps it would be more consistent to choose the “smallest type that fits”, but this will lead to casts in such a `sin` case. In other words, it trades casts in your situation for casts in another situation. It does not remove the need for casts.

> [@damianmoz](#):
>
> ```Chapel
> t + 42
> 
> ```
> 
> as anything other than the type of `t` is baffling. And there is no warning by default.

At some point in the development of the branch that fixed `real` behavior, I had the rule that specifying a non-default type would cause it to be preferred. So that `127:uint(32) + 42` would be a `uint(32)`. This made some sense to me in concept but led to test failures and I wasn’t able to end up at an internally consistent solution. The main complaint I have about it is that the “default size” integer (`int(64)`) behaves differently than the others. What if you want to request a default-sized integer? You wouldn’t be able to.

In theory, we could have the type system separate an “untyped” or “default” literal from a typed one, so that `1:int(64)` and `1` have different types. Even if we got it to work, it would be a pretty big development effort and a breaking change. For one thing, we would need to have a way to write “default size int” as a different type from “int(64)” and use that in various standard libraries. But, at least we could keep the current behavior for `foo(42)` and `sin(1)`.

Lastly, the easiest solution of all would be to add integer decorators like C has (e.g. `42i64`). However that wouldn’t be much use to you if the code you are considering here is generic.

> [@damianmoz](#):
>
> That value `xp` will never overflow. It is 169. I need to say
> 
> ```Chapel
> param xp = t + 42:(t.type);
> 
> ```
> 
> to get the desired result Ugly.

There are several ways to write this that are less ugly, IMO.

First, the parentheses you have are unnecessary

```Chapel
param xp = t + 42:t.type;

```

You could store the type into a separate variable to simplify if you have multiple such expressions:

```Chapel
type tt = t.type;
param xp = t + 42:tt;

```

You can specify the type of the param variables (although there are cases where this can result in compilation error; if `t` is close to the maximum value of its type):

```Chapel
param xp: t.type = t + 42;

```

Lastly, if you are writing a `param`-returning function, you can cast on the return (or specify the return type if you are not worried about integer overflow/underflow)

```Chapel
param xp = t + 42;
return xp: t.type;

```

---

_[View the full topic](https://chapel.discourse.group/t/integer-promotion-weirdness/33886)._
