It's bad if it alters values (e.g. rounding). Promotion from one number representation to another (as long as it preserves values) isn't bad. This is trickier than it might seem, but Virgil has a good take on this (https://github.com/titzer/virgil/blob/master/doc/tutorial/Nu...). Essentially, it only implicitly promotes values in ways that don't lose numeric information and thus are always reversible.
In the example, Virgil won't let you pass "1000.00" to an integer argument, but will let you pass "100" to the double argument.
Depends on what you want from such a hierarchy, of course, but there is for example an injection i32 -> f64 (and if you consider the i32 operations to be undefined on overflow, then it’s also a homomorphism wrt addition and multiplication). For a more general view, various Schemes’ takes on the “numeric tower” are informative.
// OK implicit promotions
def x1: i20;
def f1: float = x1;
def x2: i21;
def f2: float = x2;
def x3: i22;
def f3: float = x3;
def x4: i23;
def f4: float = x4;
// compile error!
def x5: i24;
def f5: float = x5; // requires rounding
This also applies to casts, which are dynamically checked. // runtime error if rounding alters value
def x5: i24;
def f5: float = float.!(x5);