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

Error compiling problem case #4 from nll-rfc #46361

Closed
fpoli opened this issue Nov 29, 2017 · 8 comments
Closed

Error compiling problem case #4 from nll-rfc #46361

fpoli opened this issue Nov 29, 2017 · 8 comments
Labels
A-NLL Area: Non Lexical Lifetimes (NLL) C-bug Category: This is a bug. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.

Comments

@fpoli
Copy link
Contributor

fpoli commented Nov 29, 2017

UPDATE: This example works now, but needs someone to add a test. See mentoring instructions below.


I'm trying to compile some examples using nonlexical lifetimes. To do so, I'm compiling rustc using the master branch, and the -Z nll compiler option.

rustc 1.24.0-dev
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.24.0-dev
LLVM version: 4.0

By compiling "Problem case 4: mutating &mut references" from nll-rfc, I get some errors.

Program
struct List<T> {
    value: T,
    next: Option<Box<List<T>>>,
}

fn to_refs<T>(mut list: &mut List<T>) -> Vec<&mut T> {
    let mut result = vec![];
    loop {
        result.push(&mut list.value);
        if let Some(n) = list.next.as_mut() {
            list = &mut n;
        } else {
            return result;
        }
    }
}

fn main() {
    println!("Hello World!");
}
Output of `rustc -g -Zverbose -Znll nll-problem-case-4.rs`:
error[E0597]: `n` does not live long enough
  --> nll-problem-case-4.rs:11:25
   |
11 |             list = &mut n;
   |                         ^ does not live long enough
...
14 |         }
   |         - borrowed value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 6:1...
  --> nll-problem-case-4.rs:6:1
   |
6  | / fn to_refs<T>(mut list: &mut List<T>) -> Vec<&mut T> {
7  | |     let mut result = vec![];
8  | |     loop {
9  | |         result.push(&mut list.value);
...  |
15 | |     }
16 | | }
   | |_^

error[E0499]: cannot borrow `list.value` as mutable more than once at a time
  --> nll-problem-case-4.rs:9:26
   |
9  |         result.push(&mut list.value);
   |                          ^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
16 | }
   | - mutable borrow ends here

error[E0499]: cannot borrow `list.next` as mutable more than once at a time
  --> nll-problem-case-4.rs:10:26
   |
10 |         if let Some(n) = list.next.as_mut() {
   |                          ^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
16 | }
   | - mutable borrow ends here

error[E0506]: cannot assign to `list` because it is borrowed
  --> nll-problem-case-4.rs:11:13
   |
9  |         result.push(&mut list.value);
   |                          ---------- borrow of `list` occurs here
10 |         if let Some(n) = list.next.as_mut() {
11 |             list = &mut n;
   |             ^^^^^^^^^^^^^ assignment to borrowed `list` occurs here

error: aborting due to 4 previous errors

My questions are:

  • Am I enabling correctly the experimental nll? What confuses me is that I compiled rustc with ./configure --enable-debug --enable-debuginfo, but I still don't see the debug!("mir_borrowck done"); message from the compiler.
  • Is "problem case 4" supposed to compile without errors in the future, when nll will be stable?
@kennytm kennytm added C-bug Category: This is a bug. WG-compiler-nll A-NLL Area: Non Lexical Lifetimes (NLL) labels Nov 29, 2017
@matthewjasper
Copy link
Contributor

Am I enabling correctly the experimental nll

You need to pass -Z borrowck=mir or -Z borrowck=compare as well as -Z nll for now.
The example should have list = n on line 11 (n is already a mutable reference).
After that it still fails to compile. (Even worse it gains an error)

Output with -Z borrowck=compare -Znll
An immutable local variable or function argument

[Variables]: expressions/variables.html
[temporay]: expressions.html#temporary-lifetimes
error[E0499]: cannot borrow `list.value` as mutable more than once at a time (Ast)
--> <source>:11:26
   |
11 |         result.push(&mut list.value);
   |                          ^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
18 | }
  | - mutable borrow ends here
error[E0499]: cannot borrow `list.next` as mutable more than once at a time (Ast)
--> <source>:12:26
   |
12 |         if let Some(n) = list.next.as_mut() {
   |                          ^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
18 | }
   | - mutable borrow ends here
error[E0506]: cannot assign to `list` because it is borrowed (Ast)
--> <source>:13:13
   |
11 |         result.push(&mut list.value);
   |                          ---------- borrow of `list` occurs here
12 |         if let Some(n) = list.next.as_mut() {
13 |             list = n;
   |             ^^^^^^^^ assignment to borrowed `list` occurs here
error[E0499]: cannot borrow `list.value` as mutable more than once at a time (Mir)
--> <source>:11:21
   |
11 |         result.push(&mut list.value);
   |                     ^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
error[E0506]: cannot assign to `n` because it is borrowed (Mir)
--> <source>:12:21
   |
12 |         if let Some(n) = list.next.as_mut() {
   |                     ^ assignment to borrowed `n` occurs here
13 |             list = n;
   |             -------- borrow of `n` occurs here
error[E0506]: cannot assign to `list` because it is borrowed (Mir)
--> <source>:13:13
   |
11 |         result.push(&mut list.value);
   |                     --------------- borrow of `list` occurs here
12 |         if let Some(n) = list.next.as_mut() {
13 |             list = n;
   |             ^^^^^^^^ assignment to borrowed `list` occurs here
error[E0499]: cannot borrow `**n` as mutable more than once at a time (Mir)
--> <source>:13:13
   |
13 |             list = n;
   |             ^^^^^^^^ mutable borrow starts here in previous iteration of loop
error: aborting due to 7 previous errors
Compiler exited with result code 101

@nikomatsakis
Copy link
Contributor

You can now use #![feature(nll)]

@nikomatsakis
Copy link
Contributor

With some small tweaks (unrelated to NLL), the example compiles now.

#![feature(nll)]

struct List<T> {
    value: T,
    next: Option<Box<List<T>>>,
}

fn to_refs<T>(mut list: &mut List<T>) -> Vec<&mut T> {
    let mut result = vec![];
    loop {
        result.push(&mut list.value);
        if let Some(n) = list.next.as_mut() {
            list = n;
        } else {
            return result;
        }
    }
}

fn main() {
    println!("Hello World!");
}

@nikomatsakis
Copy link
Contributor

We don't have a test specifically targeting this case, I don't think. It'd be good to make one. It should go in this directory:

https://github.com/rust-lang/rust/tree/master/src/test/run-pass/nll

@nikomatsakis nikomatsakis added E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Jan 16, 2018
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Jan 16, 2018

Mentoring instructions

Add a modified version of the example from this example into src/test/run-pass/nll with a suitable license. We should also modify the main() function to actually execute the code.

@ritiek
Copy link
Member

ritiek commented Jan 20, 2018

I'll add the test.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jan 25, 2018
…nikomatsakis

NLL test for mutating &mut references

As mentioned in rust-lang#46361.

cc @nikomatsakis?
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jan 25, 2018
…nikomatsakis

NLL test for mutating &mut references

As mentioned in rust-lang#46361.

cc @nikomatsakis?
@nikomatsakis
Copy link
Contributor

Closed by #47609

@arielb1
Copy link
Contributor

arielb1 commented Feb 6, 2019

keywords: copy-vs-move, copy vs move, orphaned borrow, overwriting reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NLL Area: Non Lexical Lifetimes (NLL) C-bug Category: This is a bug. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.
Projects
None yet
Development

No branches or pull requests

6 participants