Shouldn't this work?

I am saying the compiler’s heuristics can be made simpler,
and more intelligent, to understand how to correctly deal with this situation.

The process can go something like this.

Here:

m = (m <= UInt32::MAX) ? m.to_u64 : m.to_u128

the value of m doesn’t change.
m will be a UInt type of its orignal value no matter which branch is taken.

m is not, nor can ever be, a Union of two types at runtime.

m is only used here.

def powmodint(b, e, m)
  r = typeof(m).new(1)
  b = b % m;  b = typeof(m).new(b)
  while e > 0
    r = (r &* b) % m if e.odd?
    e >>= 1
    b = (b &* b) % m
  end
  r
end

m is used to perform numerical computations with.

As far as the compiler should be concerned, the above code should
pose no conflicts, or create unresolved paradoxes, for the given heuristics.
(In fact, if you make the types in both branches the same it compiles.)

Now for this example:

m = (m <= UInt32::MAX) ? m.to_u64 : m.to_s

This should return a compiler error because m is no longer
assured to be an Int type which can perform numeric computations.

Thus I am saying it is algorithmically too rigid for the compiler
to label m to be a Union of two types here, when the heuristics
of the runtime clearly state m is assured to be just one Int type.

At the worse, maybe the compiler should issue a warning to identify
a possilbe runtime conflict, but that should be all that is necessary.