Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
tl;dr, the lifetime of "second" is static The heart of your confusion is this: Since we are taking a long-lived reference r to a string slice inner which is destroyed at the end of its scope, ...
Answer
#2: Post edited
- ## tl;dr, the lifetime of `"second"` is `static`
- The heart of your confusion is this:
- > Since we are taking a long-lived reference r to a string slice inner which is destroyed at the end of its scope,
- `inner` is gone at the end of its scope, yes. However, its *value* still lives on.
We have to think about the difference between *values* and *variables*. `r` doesn't reference `inner`, it references `"second"`. What's probably confusing you is that `inner` has a reference as its value.- ```rust
- r = inner;
- ```
This performs a copy of the value `inner`. We are **not** referencing `inner`. `"second"` is a string literal. It has a lifetime of `static`. After the assignment, the value of `r` is a `&'static str`. Indeed, we can actually just specify this and confirm that this compiles cleanly:- ```rust
- let s: &'static str = "first";
- let mut r: &'static str = s;
- println!("First ref is {}", r);
- {
- let inner: &'static str = "second";
- r = inner;
- }
- println!("Second ref is {}", r);
- ```
- If this still confuses you, let's work through a different example:
- ```rust
- let s = 1;
- let mut r = s;
- println!("First r is {}", r);
- {
- let inner = 2;
- r = inner;
- }
- println!("Second r is {}", r);
- ```
- This should much more clearly show what's going on. We're just passing around values; who cares that `inner` dies at the end of its scope.
- -----
- I said at the beginning that
- > `r` doesn't reference `inner`, it references `"second"`.
- What would `r` referencing `inner` look like? Well, we'd borrow it instead of copying its value. (We also have to borrow `s` for parity)
- ```rust
- let s: &str = "first";
- let mut r: &&str = &s;
- println!("First ref is {}", r);
- {
- let inner: &str = "second";
- r = &inner;
- }
- println!("Second ref is {}", r); // !!!!!
- ```
- ```
- |
- 7 | r = &inner;
- | ^^^^^^ borrowed value does not live long enough
- 8 | }
- | - `inner` dropped here while still borrowed
- 9 | println!("Second ref is {}", r); // !!!!!
- | - borrow later used here
- ```
- As expected!
- -----
- This is getting kind of long, but on a final note, look at how this introduces a double reference. Let's think about lifetimes!
- ```rust
- let s: &str = "first"; // &'static str
- let mut r: &&str = &s; // &'<s> &'static str
- println!("First ref is {}", r);
- {
- let inner: &str = "second"; // &'static str
- r = &inner; // &'<inner> &'static str
- }
- println!("Second ref is {}", r); // !!!!!
- ```
For this purpose, `'<s>` means "has the same lifetime as `s`".
- ## tl;dr, the lifetime of `"second"` is `static`
- The heart of your confusion is this:
- > Since we are taking a long-lived reference r to a string slice inner which is destroyed at the end of its scope,
- `inner` is gone at the end of its scope, yes. However, its *value* still lives on.
- We have to think about the difference between *values* and *variables*. `r` doesn't reference `inner`, it references `"second"`. What's probably confusing you is that `inner` has a reference as its value, and the lifetime of the *reference* is not the same as the lifetime of the *referenc**ed*** value.
- ```rust
- r = inner;
- ```
- This performs a copy of the value of `inner`. We are **not** referencing `inner`. Now, what is the value of `inner`? `"second"` is a string literal. It has a lifetime of `static`. Therefore, `inner` has a value of type `&'static str`.
- After the assignment, the value of `r` thus also a `&'static str`. Indeed, we can actually just specify this and confirm that this compiles cleanly:
- ```rust
- let s: &'static str = "first";
- let mut r: &'static str = s;
- println!("First ref is {}", r);
- {
- let inner: &'static str = "second";
- r = inner;
- }
- println!("Second ref is {}", r);
- ```
- If this still confuses you, let's work through a different example:
- ```rust
- let s = 1;
- let mut r = s;
- println!("First r is {}", r);
- {
- let inner = 2;
- r = inner;
- }
- println!("Second r is {}", r);
- ```
- This should much more clearly show what's going on. We're just passing around values; who cares that `inner` dies at the end of its scope.
- -----
- I said at the beginning that
- > `r` doesn't reference `inner`, it references `"second"`.
- What would `r` referencing `inner` look like? Well, we'd borrow it instead of copying its value. (We also have to borrow `s` for parity)
- ```rust
- let s: &str = "first";
- let mut r: &&str = &s;
- println!("First ref is {}", r);
- {
- let inner: &str = "second";
- r = &inner;
- }
- println!("Second ref is {}", r); // !!!!!
- ```
- ```
- |
- 7 | r = &inner;
- | ^^^^^^ borrowed value does not live long enough
- 8 | }
- | - `inner` dropped here while still borrowed
- 9 | println!("Second ref is {}", r); // !!!!!
- | - borrow later used here
- ```
- As expected!
- -----
- This is getting kind of long, but on a final note, look at how this introduces a double reference. Let's think about lifetimes!
- ```rust
- let s: &str = "first"; // &'static str
- let mut r: &&str = &s; // &'<s> &'static str
- println!("First ref is {}", r);
- {
- let inner: &str = "second"; // &'static str
- r = &inner; // &'<inner> &'static str
- }
- println!("Second ref is {}", r); // !!!!!
- ```
- For this purpose, `'<s>` means "has the same lifetime as `s`".
- This illustrates the point I made earlier: The lifetime of the reference is not the same as the lifetime of the referenc*ed*. At `r = &inner;`, we can see that we have those two lifetimes, the lifetime of `inner` and the lifetime of `"second"`, and those two are not the same.
#1: Initial revision
## tl;dr, the lifetime of `"second"` is `static` The heart of your confusion is this: > Since we are taking a long-lived reference r to a string slice inner which is destroyed at the end of its scope, `inner` is gone at the end of its scope, yes. However, its *value* still lives on. We have to think about the difference between *values* and *variables*. `r` doesn't reference `inner`, it references `"second"`. What's probably confusing you is that `inner` has a reference as its value. ```rust r = inner; ``` This performs a copy of the value `inner`. We are **not** referencing `inner`. `"second"` is a string literal. It has a lifetime of `static`. After the assignment, the value of `r` is a `&'static str`. Indeed, we can actually just specify this and confirm that this compiles cleanly: ```rust let s: &'static str = "first"; let mut r: &'static str = s; println!("First ref is {}", r); { let inner: &'static str = "second"; r = inner; } println!("Second ref is {}", r); ``` If this still confuses you, let's work through a different example: ```rust let s = 1; let mut r = s; println!("First r is {}", r); { let inner = 2; r = inner; } println!("Second r is {}", r); ``` This should much more clearly show what's going on. We're just passing around values; who cares that `inner` dies at the end of its scope. ----- I said at the beginning that > `r` doesn't reference `inner`, it references `"second"`. What would `r` referencing `inner` look like? Well, we'd borrow it instead of copying its value. (We also have to borrow `s` for parity) ```rust let s: &str = "first"; let mut r: &&str = &s; println!("First ref is {}", r); { let inner: &str = "second"; r = &inner; } println!("Second ref is {}", r); // !!!!! ``` ``` | 7 | r = &inner; | ^^^^^^ borrowed value does not live long enough 8 | } | - `inner` dropped here while still borrowed 9 | println!("Second ref is {}", r); // !!!!! | - borrow later used here ``` As expected! ----- This is getting kind of long, but on a final note, look at how this introduces a double reference. Let's think about lifetimes! ```rust let s: &str = "first"; // &'static str let mut r: &&str = &s; // &'<s> &'static str println!("First ref is {}", r); { let inner: &str = "second"; // &'static str r = &inner; // &'<inner> &'static str } println!("Second ref is {}", r); // !!!!! ``` For this purpose, `'<s>` means "has the same lifetime as `s`".