You could also replace all the casting with their literal values:
int256 constant REAL_BITS = 128;
int256 constant REAL_FBITS = 40;
int256 constant REAL_IBITS = REAL_BITS - REAL_FBITS;
int128 constant REAL_ONE = 1 << 40;
int128 constant REAL_HALF = REAL_ONE >> 1;
int128 constant REAL_TWO = REAL_ONE << 1;
In your example, the compiler is having a hard time solving the types issue. Anyways, when using
immutable variables, the compiler will replace them wherever they appear with their literal type. So there is no problem if you use literal types directly as I showed.
In solidity, we can make any arithmetic operation with literal numbers, even if they go way beyond their range of value, but at the end we need to fit them in the range we want to use for them.
For example, we could do this:
uint32 n = (2**800 + 1) - 2**800;
As we see, 2 ** 800 goes way beyond the maximum value range that Solidity supports, which is 2 ** 64. But, since we are extracting 2 ** 800, the result is below our expected type in the example which is
uint32 and it works fine.