2

I am confused by the difference between literals and non-literals (the ones that go on the heap, I do not know what they are called). For example, taking the String type as an example:

We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t always suitable for every situation in which you want to use text. One reason is that they’re immutable. ...

I do not understand the above, as we have already seen an example like this:

let mut a = "a"; // this is String literal here, so sitting on the stack
a = "b";
println!("a is being changed to...{}", a); // this is the same String literal sitting on the stack?

Clearly literals can be mutable in Rust. What is the difference between the two, other than the fact that literals go into the stack, while non-literals go into the heap?

I am trying to understand why I shouldn't just use mutable literals in my code, considering that the stack is faster than the heap.

// a is mutable literal
let mut a = "a";
a = "b";
// b is mutable 'non-literal'
let mut b = String::from("a");
b = String::from("b");
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Kayote
  • 14,579
  • 25
  • 85
  • 144
  • 3
    Possible duplicate of [What does the word "literal" mean?](https://stackoverflow.com/questions/485119/what-does-the-word-literal-mean) – trent Jan 23 '18 at 21:36
  • My question is more specific to Rust Ownership. I will edit to make it more specific. Thanks. – Kayote Jan 23 '18 at 21:37
  • 4
    The meaning of the word "literal" is not specific to Rust and it appears to me this is your main confusion. `"a"` is a literal; `a` is not. – trent Jan 23 '18 at 21:38
  • It may well be, however, that answer doesn't help. – Kayote Jan 23 '18 at 21:45
  • 2
    In your example the value `a` is an identifier with a value of "a" which is a string literal. Therefore `a` is a mutable value that can be changed from an immutable string literal to another one if desired. – squiguy Jan 23 '18 at 21:48
  • thank you for the title edit, yes, that is what I am asking. – Kayote Jan 23 '18 at 21:53
  • 1
    The third piece of the puzzle is probably [What are the differences between Rust's `String` and `str`?](https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str) – trent Jan 23 '18 at 21:59

1 Answers1

15

Clearly literals can be mutable in Rust

First, you need to understand what a literal is. Literals are never mutable because they are literally written in the source code and compiled into the final binary. Your program does not change your source code!

An example showing that you cannot modify a literal:

fn main() {
    1 += 2;
}
error[E0067]: invalid left-hand side expression
 --> src/main.rs:2:5
  |
2 |     1 += 2;
  |     ^ invalid expression for left-hand side

On the other hand, a literal can be copied into a variable and then the variable can be changed, but we still are not mutating the literal 1:

fn main() {
    let mut a = 1;
    a += 2;
}

To be honest, I don't know what I would call a "non-literal". A literal is a specific type of expression, but there are other types of things in a program besides expressions. It's kind of like saying "cats" and "non-cats" — does that second group include dogs, mushrooms, sand, and/or emotions?


the fact that literals go into the stack, while non-literals go into the heap

Those two qualities aren't really directly related. It's pretty easy to have non-literals on the stack:

fn main() {
    let a = 1;
    let b = 2;
    let c = a + b;
}

All three variables are on the stack, but there is no literal 3 anywhere in the source code.

Right now, Rust doesn't allow for a literal value to have a heap-allocation, but that's a language-specific thing that might change over time. Other languages probably allow it.

In fact, you have to go out of your way in Rust to put something on the heap. Types like Box, Vec, and String all call functions to allocate space on the heap. The only way for your code to use heap memory is if you use these types, other types that use them, or types which allocate heap memory in some other way.


What is the reason we cannot use String literal data-type

There is no String literal — none. The source code "foo" creates a literal of type &'static str. These are drastically different types. Specifically, the Rust language can work in environments where there is no heap; no literal could assume that it's possible to allocate memory.

have to specifically use String::from()

String::from converts from &str to a String; they are two different types and a conversion must be performed.

Clearly, as per the example, in my code, both can be mutable

No, they cannot. It is impossible to start with let mut foo = "a" and modify that "a" to become anything else. You can change what that foo points to:

let mut foo = "a";
                foo
     +-----------+
     |
     |
 +---v---+              
 |       |              
 |  "a"  |           
 |       |     
 +-------+         
foo = "b";
                  foo
                   +----------+
                              |
                              |
   +-------+              +---v---+
   |       |              |       |
   |  "a"  |              |  "b"  |
   |       |              |       |
   +-------+              +-------+

Neither "a" nor "b" ever change, but what foo points to does.

This isn't specific to Rust. Java and C# strings are also immutable, for example, but you can reassign a variable to point to a different immutable string.


See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thank you for this. Would you please explain the String confusion I have. I.e. What is the reason we cannot use `String` literal data-type & have to specifically use `String::from()` as mentioned & linked in the docs. Clearly, as per the example, in my code, both can be mutable & thus the references changed for the variables. – Kayote Jan 23 '18 at 22:51
  • 3
    @Kayote So-called "string literals" are not of type `String`, but of type `&'static str`: [this question has more](https://stackoverflow.com/questions/37149831/what-is-the-difference-between-these-3-ways-of-declaring-a-string-in-rust). – trent Jan 23 '18 at 23:42
  • That answers my question. Thank you both for the help. – Kayote Jan 24 '18 at 08:09