roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
4.4k stars 309 forks source link

Improve `Num.intCast`'s signedness handling #3416

Open JanCVanB opened 2 years ago

JanCVanB commented 2 years ago

As @rtfeldman proposed in chat:

1) Change Num.intCast so that all the current numeric conversion functions get two new checks: panic if trying to convert a negative number to an unsigned number, and panic if the number is too big to fit in the target size. (These checks would be emitted based on monomorphization, so e.g. the negativeness check would only get emitted when converting from signed to unsigned, and the "too big to fit" check would only get emitted when converting to a type with a lower maximum value)

2) Introduce new numeric conversion functions that have longer names, and have no checks but their names suggest the behavior in the event of error cases like this (similar to Num.add vs Num.addWrap)

because it would be based on emitting, in a lot of cases there would be no runtime overhead compared to today in practice

e.g. when converting a U8 to an I32, that would be a zero-overhead conversion because there's no possibility of failure

but converting I32 to U8 could fail in two different ways (the I32 could be negative, or it could be too big to fit in U8), so both checks would get emitted, and you'd get a panic rather than silently wrong answers - just like with Num.add

...

which is also how Num.add and Num.addWrap work - you still have access to the lowest-level operation, but it has a longer name so you're incentivized to reach for the less error-prone one if you're not sure which you want

JanCVanB commented 2 years ago

This would have prevented my confusion in #3381.