Rust's scalar types are precise on purpose. Where many languages give you one fuzzy 'number,' Rust makes you say exactly what you mean — and that precision is a feature.
Integers
Integers come in signed (i8, i16, i32, i64, i128) and unsigned (u8 … u128) flavors, where the number is the bit width. There's also isize/usize, sized to the machine's pointer width — usize is what you index collections with. The default, when inference has nothing else to go on, is i32.
Floats, bool, char
f64 is the default float (full double precision); f32 when you need half the memory. bool is true/false. char is a full Unicode scalar — four bytes, so it holds an emoji or a Hangul syllable, not just ASCII. That's a real difference from C's one-byte char.
Overflow is defined, not undefined
Add past a type's max and Rust has a clear answer: debug builds panic (so you catch the bug in testing), release builds wrap (two's complement, for speed). Neither is the C-style undefined behavior that breeds security holes. When you want explicit behavior, say so: wrapping_add, checked_add (returns an Option), saturating_add (clamps to the max).
checked_* methods where overflow is plausible.Inference plus annotation
You usually let the compiler infer the type, but annotate when it matters: let big: u64 = 1; or a suffix like 1u64. When you parse a string to a number, you must say which number — that's the most common place you'll annotate a scalar.