Tuples mutable?

let mut tup = ("ken", 23.3, true, 'a', "rust");
println!("tup.0 = {:?}.", tup.0);
tup.4 = "What in the world is this??";
println!("tup.4 = {:?}. ", tup );

Rust docs say tuples are immutable.

The above code compiles and works. Are mutable tuples on the stack with string spaces preallocated?

Or is this new to Rust and mutable tuples are now kept on the heap?

I am on rustc 1.64.0 (a55dd71d5 2022-09-19)

Wondering.

Thanks,
Ken Wagner

Where does it say that?

The variable tup is on the stack.

Its type is: (&str, f64, bool, char, &str). Note that these are references to strings (technically, to string slices), not the strings themselves.

A string literal like "rust" has type &str, a reference to a string slice.

The string itself (the str that the tuple element refers to) lives elsewhere. In this case, it is in static memory that is loaded with the program. The strings are compiled into the program image.

Tuples have a fixed type (you can't change a tuple element to have a different type) and fixed length (you can't add a new type to the end of an existing tuple) but elements in the tuple can be mutated if the variable is declared as mutable.

1 Like

It says here: Data Types - The Rust Programming Language

In most cases, what you'll see under the hood (with Godbolt or similar) is approximately this:

  • A region allocated in the .static part of your program to hold the sequence "ken", "rust", "tup.0 = ", "What in the world is this??", and "tup.4 = "`. This area is mapped into memory when your program is loaded at a known location.

  • The tuple tup represented on the stack, in a continuous region that's at least (size of pointer) + (size of f64) + (size of bool) + (size of char) + (size of pointer) long. Note that all of those sizes are compile-time constants.

  • The program writes pointers pointing into the .static region into the stack regions representing tup.0 and tup.4, at the appropriate time in your program's execution.

This is actually a gross simplification, and (especially in release builds) the actual generated code may be very different from this, but this is a reasonable rote translation and I hope helps understand what's going on. The tuple itself is like allocated on the stack, and the strings you're using are allocated statically.

1 Like

I sense that &str is actually a pointer to a heap address thus making tuple elements of string type mutable. The docs say the length is fixed, so, I guess the pointer approach is valid. The pointers never change in length.

Thus I can change the contents of a &str slice which is on the heap. Yes?

Allocated statically on the stack?

They are pointers (that's what the & in the type means), but not necessarily to the heap. In this case, the strings don't live in the heap, but rather in a static area of memory that contains all the string literals that exist in your program.

The "length" in this context means "the number of elements of the tuple". In your case, the tuple length is 5 and isn't changing.

I reread the docs and they (for tuples) refer to fixed length which I mistakenly took to mean immutable. Thanks, tczajia.

You can't extend a string slice even if you have an &mut str, but if you had a String yes you could append to it even inside a tuple.

The strings? No. In a rote translation, they'd be copied into the program's static segment and loaded into memory at startup. They'd stay there throughout the life of the program, only leaving memory when the program is unloaded by the OS after it exits.

The static segment is closer to "heap" than "stack," but it's not really either of those things. It's a separate region defined by the loader and usually made read-only. The tuple is mutable, so you can change what strings the tuple refers to, but the strings themselves - at least the ones you're using - are read-only.

If you want a mutable string, there are a few ways to get one - a String, which allocates a buffer on the heap for you, or a [char; N] array, which may live on the stack, or Vec<u8>, can all provide storage that can be converted to &str or &mut str in the right contexts.

The word "immutable" isn't anywhere on that page.

My error. Said length could not be changed. I took it to mean immutable. Thanks H2CO3.

My thanks to all of you. I am learning Rust. It is an amazing tool. Using VS Code. This community is very prompt and clearly helpful. I am understanding more & more why Rust is so free of aggravating bugs.

5 Clicks (or is it Clacks) for Rustaceans!!