17

I just started a tutorial in Rust and I can't get my head around the limitation of tuple printing:

fn main() {
    // Tuple definition
    let short = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
    let long = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

    println!("{:?}", short); // Works fine
    println!("{:?}", long);  // ({integer}...{integer})` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug`
}

In my ignorant view the printing could be easily achieved by iterating over the entire tuple — this would allow displaying without size constraint. If the solution would be that simple it would be implemented, what am I missing here?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
magu_
  • 4,766
  • 3
  • 45
  • 79

2 Answers2

21

Printing tuples is currently implemented using a macro that only works up to 12 elements.

Functionality to statically iterate/manipulate tuples has been proposed, but has been postponed (see e.g. this RFC). There was some concerns about the implementation of these (e.g. you'd expect to be able to get the head & tail of a tuple, but there is actually no guarantee that a tuple will be stored in the same order as you specified, because the compiler is allowed to optimize for space, which means getting the tail wouldn't be a trivial operation).

As for why you need special support for that, consider the following tuple:

let mixed = (42, true, 3.14, "foo");

How you would iterate this tuple, given that all its elements have a different type? This can't simply be done using regular iterators and a for loop. You would need some new type-level syntax, which Rust is currently lacking.

mcarton
  • 27,633
  • 5
  • 85
  • 95
  • Hm, yes this makes sense. I still feel that the mixed case could be solved. But I guess the pressure to do so wasn't big enough. – magu_ Aug 14 '18 at 17:48
  • 2
    Yes, it is likely that the drawbacks and concerns about the implementations were too important for little benefit (big tuples are quite rare, and small tuples can be dealt with quite easily using macros). Note that big arrays do suffer the same problems and are much more common, but as @Tim mentioned, const generics should fix their case. – mcarton Aug 14 '18 at 17:57
  • @mcarton: I'm not sure it's just a matter of benefits/drawbacks as much as it's a matter of timing. When setting up the priorities, const generics and variadic generics were pushed back in favor of more pressing concerns: NLL and async, notably. Const generics is already slated to see some work before the end of year (there have been internal refactorings going on already to prepare the terrain), and I'm sure that at some point variadic generics will also be worked on... but there's little pressure to improve tuples right now and it'll take time to do so properly. – Matthieu M. Aug 15 '18 at 14:15
  • @MatthieuM. Sure, but "We don't have time to define/implement feature X" is also a drawback of "feature X". NLL for example also took a while to get to the point they are now and we could have said "We don't have time", but the benefit of them were big enough that time was actually allocated to this. – mcarton Aug 15 '18 at 15:28
  • @mcarton: Oh sure. There's definitely prioritization going on. My point was more that the feature has not been outright rejected; it's just that it's known to be a big feature, which will take time and focus to get right, and there's not much of either available because other features are judged more pressing. Interestingly, variadic generics would probably have been a greater priority had the language not supported tuples as built-in types :) – Matthieu M. Aug 15 '18 at 15:36
  • Yes, that C++ tuples are just built out of variadic generics is actually really nice feature. Although C++ being C++, you sometimes need to sacrifice a sheep to get it to work, so let's hope Rust will get those right-er :) – mcarton Aug 15 '18 at 16:31
3

Debug is only implemented on tuples up to 12 elements. This is why printing short works, but long fails.

Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
  • 5
    AFAIK, there is no relation between tuples and const generics. Const generics could allow eg. to implement `Debug` on arbitrary sized arrays, but not tuples, as they still don't provide syntax to represent an arbitrary sized tuple and access an arbitrary index. – mcarton Aug 14 '18 at 17:04
  • The RFC you point to does not even contain the word "tuple". I think const generics could be a base for it, but are definitely not enough. – mcarton Aug 14 '18 at 17:12
  • The type of an array can be precisely determined by the combination of its element type and its length. This is not the case for tuples, since every element can have a different type. Describing "all tuples" would need some very fancy new type-level syntax. – Peter Hall Aug 14 '18 at 17:18
  • @mcarton Removed the RFC-Part. Confused it with arrays. Thanks for pointing out! – Tim Diekmann Aug 14 '18 at 21:40