In addition to ground type information about any type, Rust also stores information about a types reference level, mutability, and lifetime. In a declaration, if none of these are provided, then a type will be inferred as: by value, immutable, and having implied lifetime.
Each of these type decorations are binary: a type is either referenced by value or by reference, a type is either mutable or immutable, and a type can only have an explicit or implicit lifetime. All these combinations, for a type T, are written as follows from left to right:
|by value||implicit||mutable||mut T|
|by value||explicit||immutable||'a T|
|by value||explicit||mutable||'a mut T|
|by reference||implicit||mutable||&mut T|
|by reference||explicit||immutable||&'a T|
|by reference||explicit||mutable||&'a mut T|
Sharing by reference is a great performance improvement for large values. In practice, most code that works with values can work directly with references as well without change. There are many inferences that the compiler can make to remove the friction of sharing a value by reference.
For most sharing, it is implied that the value won't change just by sharing a reference. This custom is made explicit in Rust through the mutability type decoration. If a value is allowed to change inside a function then it must be marked as such explicitly. Also, types that are immutable are not allowed to be 'upgraded' to mutable inside of functions. This way we can enforce mutability throughout our programs.
Lifetimes that are implicit are still passed to the borrow checker. The borrow checker is a compiler tool that enforces rules about when a value is created and destroyed. Explicit lifetimes allow the programmer to define even stronger guarantees about when a value will be created and destroyed.