> There's some complexity there that I guess I just don't know.
It's because the format string itself is checked to be consistent with the types of arguments given. If there's an inconsistency, you get a compile time error. Most printf-style functions in other programming languages don't do this.
The language doesn't have varargs (to say nothing of type-safe generic variable-type args), so you'd have to pass in a slice of references e.g.
print!(..., a, b, c)
would become
print(..., &[&a, &b, &c])
Which is not exactly sexy, plus all these references would have to implement a matching trait, whereas currently formatting different values can involve different traits depending on the format specifier e.g. a plain `{}` is Display but `{:?}` is Debug and `{:x}` is LowerHex. You can have a type which implements LowerHex but neither Debug nor Display if that makes sense.
It's because the format string itself is checked to be consistent with the types of arguments given. If there's an inconsistency, you get a compile time error. Most printf-style functions in other programming languages don't do this.