It's becoming a recurring pattern in newer languages that number literals are their own magical type (usually backed by a bigint or bigfloat) that only coerce into a concrete type when they first come into contact, so to say, with a typed variable or expression.
Though note that the implementation in Rust is much less magical than that of, say, Go. Every numeric literal expression has a concrete type. When that type can be inferred from context (using the ordinary type inference rules), it is. When it can't be inferred from context, the compiler forces integer literals to i32 and float literals to f64; if that causes additional type errors to occur, then Rust requires the user to insert type annotations where necessary rather than trying to be smart about it (this can all be observed in the error messages in the OP). IOW, code using the numeric literal fallback types only compiles when it makes no semantic difference what the type is (modulo `unsafe`, as ever).
This mostly happens in small code examples and test cases/doctests, e.g. `fn main() { dbg!(42); }` only compiles because of the existence of this fallback.