Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non lexical lifetimes not mentioned in Chapter 4 #2077

Closed
Shreyas4991 opened this issue Sep 4, 2019 · 3 comments
Closed

Non lexical lifetimes not mentioned in Chapter 4 #2077

Shreyas4991 opened this issue Sep 4, 2019 · 3 comments

Comments

@Shreyas4991
Copy link

Shreyas4991 commented Sep 4, 2019

Brief Description

There is no mention of non-lexical lifetimes, or lifetimes at all for that matter, in chapter 4, leading to questions such as this and the comments below the question.

Details

The issue is that non-lexical lifetimes, and lifetimes themselves are not discussed in the context of ownership and references. In fact, chapter 4 is full of lines which imply that the lifetime of a borrow is tied to its lexical scope, and there are none that suggest otherwise. Thus, someone approaching rust from a different language or an earlier version of rust (2015 edition for instance) will have no idea that an unused mutable borrow might have a more limited lifetime than the block scope. This is what led me to ask that SO question. I list out the lines from the book which discuss the issue of when a reference is invalidated. While the lines from chapter 4 section 01 concern ownership and not references, sections 01 and 02 form a continuum when reading the book. When they are read together, it leaves the reader with the strong impression that the lifetime of a variable and by extension references to it are restricted by lexical scope. Here are the lines:

  • In chapter 4-01 :
    • "the memory is automatically returned once the variable that owns it goes out of scope".
    • "When the owner goes out of scope, the value will be dropped."
  • In chapter 4-02:
    • "Mutable references have one big restriction: you can have only one mutable reference to a particular piece of data in a particular scope"
    • "The &s1 syntax lets us create a reference that refers to the value of s1 but does not own it. Because it does not own it, the value it points to will not be dropped when the reference goes out of scope."
    • "The scope in which the variable s is valid is the same as any function parameter’s scope"
    • "But mutable references have one big restriction: you can have only one mutable reference to a particular piece of data in a particular scope": This line is probably the most misleading one and the code sample in the SO question reflects that.
    • Immediately after the previous line, the book explains that to hold multiple mutable references we can add more blocks to restrict the scope of mutable references: "As always, we can use curly brackets to create a new scope, allowing for multiple mutable references, just not simultaneous ones:". This line is followed up with this code snippet
       let mut s = String::from("hello");
       {
           let r1 = &mut s;
       } // r1 goes out of scope here, so we can make a new reference with no problems.
      let r2 = &mut s;

The code sample above, listed in the book, is one of the textbook use cases where NLL actually makes a difference if r1 is not used any further.

Summary

There is no mention of lifetimes and the possibility that a mutable borrow might have a lifetime smaller than its lexical scope. Someone coming from C++ or rust 2015 might be justified in assuming that a mutable borrow is its lexical scope and might be confused by the compiler's output as I was in the SO question.

Proposed Solution

I suggest that in the discussion about references and borrowing in chapter 4 section 02, immediately after references are introduced:

  1. A brief subsection must be written, with a description of lifetimes of borrows.
  2. All references to the word scope in the lines mentioned above must be replaced with the word lifetime after this subsection.
  3. The code listing that I have mentioned above, and the text surrounding it, must be modified to explain how the lifetime of a borrow affects our ability to define multiple mutable borrows. This is to ensure that the reader is not left with the impression that new blocks are necessary to restrict the section of code for which a mutable reference is valid even when its NLL ends before the next mutable reference is defined.
@trentj
Copy link

trentj commented Sep 5, 2019

I agree that the book is not super clear on this point, but not all of the mentions of "scope" in the chapter are incorrect:

  • "the memory is automatically returned once the variable that owns it goes out of scope".
  • "When the owner goes out of scope, the value will be dropped."

With or without NLL, borrow checking does not influence when values are dropped. These sentences are just describing how RAII works in Rust.

  • "The &s1 syntax lets us create a reference that refers to the value of s1 but does not own it. Because it does not own it, the value it points to will not be dropped when the reference goes out of scope."

Same but in the negative. The value of s1 will be dropped when s1 goes out of scope, but it will not be dropped when (the temporary) &s1 goes out of scope. The book is illustrating that a borrowed thing is different from an owned thing.

  • "The scope in which the variable s is valid is the same as any function parameter’s scope"

Is true, but I'm not sure why the book highlights this; I would not have assumed otherwise.

@Shreyas4991
Copy link
Author

Shreyas4991 commented Sep 5, 2019

I agree that the points you mentioned are correct. But combined with the other points I mentioned, they create the idea that lifetime of borrows is tied to scope. I have mentioned this here

While the lines from chapter 4 section 01 concern ownership and not references, sections 01 and 02 form a continuum when reading the book. When they are read together, it leaves the reader with the strong impression that the lifetime of a variable and by extension references to it are restricted by lexical scope

The purpose of adding those lines was to point out how scope is emphasised while no mention is made of a borrow's lifetime. Of course, the first and fourth points under chapter 4-02 are technically not correct

In chapter 4-02:

  • "Mutable references have one big restriction: you can have only one mutable reference to a particular piece of data in a particular scope"
  • "But mutable references have one big restriction: you can have only one mutable reference to a particular piece of data in a particular scope": This line is probably the most misleading one and the code sample in the SO question reflects that.

So my suggestion is that all occurrences of "scope" after a brief subsection on lifetime of a borrow in chapter 4-02, be edited.

@carols10cents
Copy link
Member

Closing as a duplicate of #1939. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants