Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why disallow re-using the same value in a format! macro

Tags:

rust

Given:

fn main() {
    println!("{0} {0:?}", 10);
}

I get:

main.rs:2:27: 2:29 error: argument redeclared with type `?` when it was previously ``
main.rs:2     println!("{0} {1:?}", 10);
                                    ^~
error: aborting due to previous error

I am forced to do:

println!("{0} {1:?}", 10, 10);
// OR
println!("{} {:?}", 10, 10);

Why is such a limit imposed upon me?

like image 746
tshepang Avatar asked Jan 13 '15 19:01

tshepang


1 Answers

It's due to a limitation in the formatting system.

Internally, println! (more accurately, format_args!) packs its arguments into an array, pairing each argument with its formatting type. For example, the following expression:

println!("{2} {0:?} {1:x}", 1, 2, 3);

produces this argument array:

match (&1, &2, &3) {
    (__arg0, __arg1, __arg2) => [
        ::std::fmt::argument(::std::fmt::Debug::fmt, __arg0),
        ::std::fmt::argument(::std::fmt::LowerHex::fmt, __arg1),
        ::std::fmt::argument(::std::fmt::Display::fmt, __arg2)
        ]
}

(By the way, you can see the full expansion using rustc -Z unstable-options --pretty=expanded main.rs)

This explains why your example doesn't work: if you wanted the first argument (__arg0) to be both Debug and Display, then where would you put the second type?

There's no way of lifting this restriction without complicating the system too much, so sadly we'll just have to work around it.

like image 156
Lambda Fairy Avatar answered Oct 31 '22 23:10

Lambda Fairy