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: