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

NLL: Improve move error loop detection (was "First shot at #54015") #54343

Merged
merged 4 commits into from
Oct 2, 2018
Merged

NLL: Improve move error loop detection (was "First shot at #54015") #54343

merged 4 commits into from
Oct 2, 2018

Conversation

blitzerr
Copy link
Contributor

@blitzerr blitzerr commented Sep 19, 2018

Closes #54015

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 19, 2018
@memoryruins memoryruins added A-NLL Area: Non-lexical lifetimes (NLL) NLL-diagnostics Working towards the "diagnostic parity" goal labels Sep 19, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:15:32]    Compiling rustc_metadata_utils v0.0.0 (file:///checkout/src/librustc_metadata_utils)
[00:15:32]    Compiling rustc_mir v0.0.0 (file:///checkout/src/librustc_mir)
[00:15:32]    Compiling rustc_typeck v0.0.0 (file:///checkout/src/librustc_typeck)
[00:15:33]    Compiling rustc_allocator v0.0.0 (file:///checkout/src/librustc_allocator)
[00:15:34] error[E0425]: cannot find value `mois` in this scope
[00:15:34]   --> librustc_mir/borrow_check/error_reporting.rs:89:78
[00:15:34]    |
[00:15:34] 89 |             if let Some((reported_place, _)) = self.move_error_reported.get(&mois) {
[00:15:34] 
[00:15:34] 
[00:15:34] error[E0425]: cannot find value `mois` in this scope
[00:15:34]   --> librustc_mir/borrow_check/error_reporting.rs:92:40
[00:15:34]    |
[00:15:34] 92 |                            mois={:?}", mois);
[00:15:34] 
[00:15:34] 
[00:15:34] error[E0425]: cannot find value `mois` in this scope
[00:15:34]    --> librustc_mir/borrow_check/error_reporting.rs:185:17
[00:15:34] 185 |                 mois,
[00:15:34]     |                 ^^^^ not found in this scope
[00:15:34] 
[00:15:47] error: aborting due to 3 previous errors

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
@nikomatsakis nikomatsakis added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 19, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:46:59] ....................................................................................................
[00:47:03] ....................................................................................................
[00:47:06] ....................................................................................................
[00:47:09] ....................................................................................................
[00:47:12] .................................................F...................................i..............
[00:47:18] ........................................i.i..ii.....................................................
[00:47:22] ....................................................................................................
[00:47:24] ........................................................i...........................................
[00:47:28] ....................................................................................................

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates look good. It'd be nice, if you're up for it, to separate the "rustfmt run" into its own commit (I usually do this by rebasing and "inserting" a rustfmt commit before the "meat").

The main concern though is that the output looks wrong; but then I see there's a travis failure, maybe it just needs to be updated?


/// True if we traversed a back edge while walking from the point
/// of error to the move site.
traversed_back_edge: bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

| ^ value used here after move
LL | while true { while true { while true { x = y; x.clone(); } } }
| - value moved here
| ^ value moved here in previous iteration of loop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, interesting. This doesn't quite look right, since this location is not a move.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the current output?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect to see "value used here after move", and the "value moved here..." annotation somewhere else.

@nikomatsakis
Copy link
Contributor

Ah, no, the travis failure is that the //~ ERROR annotations in the test are out of date:

[00:52:23] ---- [ui] ui/liveness/liveness-move-in-while.rs stdout ----
[00:52:23] 
[00:52:23] error: /checkout/src/test/ui/liveness/liveness-move-in-while.rs:18: unexpected error: '18:24: 18:25: borrow of moved value: `y` [E0382]'
[00:52:23] 
[00:52:23] error: /checkout/src/test/ui/liveness/liveness-move-in-while.rs:18: expected error not found: use of moved value: `y`
[00:52:23] 
[00:52:23] error: /checkout/src/test/ui/liveness/liveness-move-in-while.rs:19: expected error not found: use of moved value: `y`

@blitzerr
Copy link
Contributor Author

joydeep$ rustc +stage2 src/test/ui/liveness/liveness-move-in-while.rs
error[E0382]: borrow of moved value: y
--> src/test/ui/liveness/liveness-move-in-while.rs:18:24
|
18 | println!("{}", y); //~ ERROR borrow of moved value: y
| ^ value moved here in previous iteration of loop
|
= note: move occurs because y has type std::boxed::Box<isize>, which does not implement the Copy trait

error: aborting due to previous error

For more information about this error, try rustc --explain E0382.

@blitzerr
Copy link
Contributor Author

blitzerr commented Sep 22, 2018

That is the current error when we compile the file.
I was sure if it compiles, it must be correct but apparently not :(

Expected:

   |
8 |         println!("{}", y); //~ ERROR use of moved value: `y`
   |                       ^ value used here after move
9 |         while true { while true { while true { x = y; x.clone(); } } }
   |                                                   - value moved here in previous iteration of loop
   |

But we are getting:

|
18 | println!("{}", y); //~ ERROR borrow of moved value: y
|                   ^ value moved here in previous iteration of loop
|

It completely ate up this line

9 |         while true { while true { while true { x = y; x.clone(); } } }
   |                                                   - value moved here in previous iteration of loop

@bors
Copy link
Contributor

bors commented Sep 23, 2018

☔ The latest upstream changes (presumably #54229) made this pull request unmergeable. Please resolve the merge conflicts.

@blitzerr
Copy link
Contributor Author

         let move_site_vec = self.get_moved_indexes(context, mpi);
         debug!(
-            "report_use_of_moved_or_uninitialized: mois={:?}",
+            "report_use_of_moved_or_uninitialized: vec<mois,back_edge>={:?}",
             move_site_vec
         );

-        let mois = move_site_vec.clone().into_iter().map(|x| x.moi).collect();
+        let mois = move_site_vec
+            .clone()
+            .into_iter()
+            .map(|x| {
+                let location = self.move_data.moves[x.moi].source;
+                let span = self.mir.source_info(location).span;
+                debug!("moi {:?}: {:?}", x.moi, span);
+                x.moi
+            })
+            .collect();
         if move_site_vec.is_empty() {
             let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();

@@ -137,12 +146,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     ""
                 };

-                if move_site.traversed_back_edge {
+                // if move_site.traversed_back_edge {
+                //     is_loop_move = true;
+                //     err.span_label(
+                //         span,
+                //         format!("value moved{} here in previous iteration of loop", move_msg),
+                //     );
+                // }
+                if span == move_span {
+                    is_loop_move = true;
                     err.span_label(
                         span,
                         format!("value moved{} here in previous iteration of loop", move_msg),
                     );
-                    is_loop_move = true;
                 } else {
                     err.span_label(move_span, format!("value moved{} here", move_msg));
                     move_spans.var_span_label(&mut err, "variable moved due to use in closure");

@blitzerr
Copy link
Contributor Author

@nikomatsakis

This change is basically the same error reporting with the back-edge calculation done (but not used).
Compiled with stage 2 this is the output

>$ rustc +stage2 ./src/test/ui/liveness/liveness-move-in-while.rs
error[E0382]: borrow of moved value: `y`
  --> ./src/test/ui/liveness/liveness-move-in-while.rs:18:24
   |
18 |         println!("{}", y); //~ ERROR borrow of moved value: `y`
   |                        ^ value moved here in previous iteration of loop
   |
   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.

Compiled with stage 1, this is the output:

>$ rustc +stage1 ./src/test/ui/liveness/liveness-move-in-while.rs
error[E0382]: borrow of moved value: `y`
  --> ./src/test/ui/liveness/liveness-move-in-while.rs:18:24
   |
18 |         println!("{}", y); //~ ERROR borrow of moved value: `y`
   |                        ^ value borrowed here after move
19 |         while true { while true { while true { x = y; x.clone(); } } }
   |                                                    - value moved here
   |
   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.

@blitzerr blitzerr closed this Sep 27, 2018
@blitzerr blitzerr reopened this Sep 27, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:45:43] 
[00:45:43] running 4308 tests
[00:45:46] ....................................................................................................
[00:45:49] ....................................................................................................
[00:45:51] ........F...................................F...F.......................F...........................
[00:45:54] ....FF.....................................F................F.......................................
[00:45:57] .........................F..........................................................................
[00:46:05] ....................................................................................................
[00:46:10] ................................i...........i.......................................................
[00:46:13] ...................................................iiiii............................................
[00:46:16] ....................................................................................................
---
[00:46:34] ....................................................................................................
[00:46:36] ...................................................................................................i
[00:46:39] ....................................................................................................
[00:46:42] ....................................................................................................
[00:46:45] ................................F..........................................F........................
[00:46:51] ....................................................................................................
[00:46:54] ....................................................................................................
[00:46:57] ....................................................................................................
[00:47:00] ....................................................................................................
[00:47:00] ....................................................................................................
[00:47:03] ................................................................................................i...
[00:47:06] ....................................................................................................
[00:47:09] ........................................................i.i..ii.....................F...............
[00:47:13] .....................F.F.......................F............................F.........F.............
[00:47:16] ......F...................................................................................i.........
[00:47:22] ....................................................................................................
[00:47:24] ....................................................................................................
[00:47:27] ....................................................................................................
[00:47:31] ...............................i....................................................................
[00:47:31] ...............................i....................................................................
[00:47:35] ....................................................................................................
[00:47:38] ....................................................................................................
[00:47:42] .............................................................................................i......
[00:47:45] ...........................................................................................F...F....
[00:47:48] ....................................................................................................
ing::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semantics at all and are trivial to duplicate. An\nexample is `i32` and the other number types. We don't have to call `.clone()` to\nclone them, because they are marked `Copy` in addition to `Clone`.  Implicit\ncloning is more convenient in this case. We can mark our own types `Copy` if\nall their members also are marked `Copy`.\n\nIn the example below, we implement a `Point` type. Because it only stores two\nintegers, we opt-out of ownership semantics with `Copy`. Then we can\n`let p2 = p1` without `p1` being moved.\n\n```\n#[derive(Copy, Clone)]\nstruct Point { x: i32, y: i32 }\n\nfn main() {\n    let mut p1 = Point{ x: -1, y: 2 };\n 53] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:47:53] ---- [ui] ui/borrowck/borrowck-drop-from-guard.rs stdout ----
[00:47:53] diff of stderr:
[00:47:53] 
[00:47:53] 2   --> $DIR/borrowck-drop-from-guard.rs:22:23
[00:47:53] 2   --> $DIR/borrowck-drop-from-guard.rs:22:23
[00:47:53] 3    |
[00:47:53] 4 LL |         Some(_) if { drop(my_str); false } => {}
[00:47:53] -    |                           ------ value moved here
[00:47:53] +    |                           ------ value moved here 
[00:47:53] 6 LL |         Some(_) => {}
[00:47:53] 7 LL |         None => { foo(my_str); } //~ ERROR [E0382]
[00:47:53] 8    |                       ^^^^^^ value used here after move
[00:47:53] 
[00:47:53] The actual stderr differed from the expected stderr.
[00:47:53] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-drop-from-guard/borrowck-drop-from-guard.stderr
[00:47:53] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-drop-from-guard/borrowck-drop-from-guard.stderr
[00:47:53] To update references, rerun the tests and pass the `--bless` flag
[00:47:53] To only update this specific test, also pass `--test-args borrowck/borrowck-drop-from-guard.rs`
[00:47:53] error: 1 errors occurred comparing output.
[00:47:53] status: exit code: 1
[00:47:53] status: exit code: 1
[00:47:53] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/borrowck/borrowck-drop-from-guard.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-drop-from-guard/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "borrowck=mir" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-drop-from-guard/auxiliary" "-A" "unused"
[00:47:53] ------------------------------------------
[00:47:53] 
[00:47:53] ------------------------------------------
[00:47:53] stderr:
[00:47:53] stderr:
[00:47:53] ------------------------------------------
[00:47:53] {"message":"use of moved value: `my_str`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()` can still use `value_cloned`,\n    let _sum = value_cloned + 1;\n    // even though the borrow only ends here.\n}\n```\n\nYou can find more information about borrowing in the rust-book:\nhttp://doc.rust-lang.org/stable/book/references-and-borrowing.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":1597,"byte_end":1605,"line_start":68,"line_end":68,"column_start":17,"column_end":25,"is_primary":false,"text":[{"text":"        let x = &mut h.0;","highlight_start":17,"highlight_end":25}],"label":"borrow of `h.0` occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":1615,"byte_end":1618,"line_start":69,"line_end":69,"column_start":9,"column_end":12,"is_primary":true,"text":[{"text":"        h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed","highlight_start":9,"highlight_end":12}],"label":"use of borrowed `h.0`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":1775,"byte_end":1776,"line_start":71,"line_end":71,"column_start":14,"column_end":15,"is_primary":false,"text":[{"text":"        drop(x);","highlight_start":14,"highlight_end":15}],"label":"borrow later used here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0503]: cannot use `h.0` because it was mutably borrowed\n  --> /checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs:69:f borrowed `*e`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":3597,"byte_end":3598,"line_start":125,"line_end":125,"column_start":14,"column_end":15,"is_primary":false,"text":[{"text":"        drop(x);","highlight_start":14,"highlight_end":15}],"label":"borrow later used here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0503]: cannot use `e.0` because it was mutably borrowed\n  --> /checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs:121:20\n   |\nLL |         let x = e.x();\n   |                 - borrow of `*e` occurs here\nLL |         match *e {\nLL |             Baz::X(value) => value\n   |                    ^^^^^ use of borrowed `*e`\n...\nLL |         drop(x);\n   |              - borrow later used here\n\n"}
[00:47:53] {"message":"cannot use `u.a` because it was mutably borrowed","code":{"code":"E0503","explanation":"\nA value was used after it was mutably borrowed.\n\nExample of erroneous code:\n\n```compile_fail,E0503\nfn main() {\n    let mut value = 3;\n    // Create a mutable borrow of `value`. This borrow\n    // lives until the end of this function.\n    let _borrow = &mut value;\n    let _sum = value + 1; // error: cannot use `value` because\n                          //        it was mutably borrowed\n}\n```\n\nIn this example, `value` is mutably borrowed by `borrow` and cannot be\nused to calculate `sum`. This is not possible because this would violate\nRust's mutability rules.\n\nYou can fix this error by limitinsuggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":6194,"byte_end":6195,"line_start":188,"line_end":188,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"            &[_, x.., _] => println!(\"{:?}\", x),","highlight_start":18,"highlight_end":19}],"label":"use of borrowed `v`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs","byte_start":6455,"byte_end":6456,"line_start":193,"line_end":193,"column_start":14,"column_end":15,"is_primary":false,"text":[{"text":"        drop(x);","highlight_start":14,"highlight_end":15}],"label":"borrow later used here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0503]: cannot use `v[..]` because it was mutably borrowed\n  --> /checkout/src/test/ui/borrowck/borrowck-describe-lvalue.rs:188:18\n   |\nLL |         let x = &mut v;\n   |                 ------ borrow of `v` occurs here\n...\nLL |             &[_, x.., _] => println!(\"{:?}\", x),\n   |                  ^ use of borrowed `v`\n...\nLL |         drop(x);\n   |              - borrow later used here\n\n"}
[00:47:53] {"message":"cannot use `e` because it was mutably borrowed","code":{"code":"E0503","explanation":"\nA value was used after it was mutably borrowed.\n\nExample of erroneous code:\n\n```compile_fail,E0503\nfn main() {\n    let mut value = 3;\n    // Create a mutable borrow of `value`. This borrow\n    // lives until the end of this function.\n    let _borrot{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semaeferences, rerun the tests and pass the `--bless` flag
[00:47:53] To only update this specific test, also pass `--test-args borrowck/borrowck-move-out-from-array.rs`
[00:47:53] 
[00:47:53] error in revision `mir`: 1 errors occurred comparing output.
[00:47:53] status: exit code: 1
[00:47:53] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/borrowck/borrowck-move-out-from-array.rs" "--target=x86_64-unknown-linux-gnu" "--cfg" "mir" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-move-out-from-array.mir/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "borrowck=mir" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-move-out-from-array.mir/auxiliary" "-A" "unused"
[00:47:53] ------------------------------------------
[00:47:53] 
[00:47:53] ------------------------------------------
[00:47:53] stderr:
[00:47:53] stderr:
[00:47:53] ------------------------------------------
[00:47:53] {"message":"use of moved value: `a[..]`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ;\n    println!(\"p1: {}, {}\", p1.x, p1.y);\n    println!(\"p2: {}, {}\", p2.x, p2.y);\n}\n```\n\nAlternatively, if we don't control the struct's definition, or mutable shared\nownership is truly required, we can use `Rc` and `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/borrowck/borrowck-uninit-field-access.rs","byte_start":1021,"byte_end":1033,"line_start":38,"line_end":38,"column_start":18,"column_end":30,"is_primary":false,"text":[{"text":"    let _moved = line1.origin;","highlight_start":18,"highlight_end":30}],"label":"value moved here ","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-uninit-field-access.rs","byte_start":1047,"byte_end":1061,"line_start":39,"line_end":39,"column_start":13,"column_end":27,"is_primary":true,"text":[{"text":"    let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`","highlight_start":13,"highlight_end":27}],"labenonrecv-autoref.rs","byte_start":5787,"byte_end":5788,"line_start":167,"line_end":167,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    i[i[3]] = 4;","highlight_start":7,"highlight_end":8}],"label":"immutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs","byte_start":5785,"byte_end":5786,"line_start":167,"line_end":167,"column_start":5,"column_end":6,"is_primary":false,"text":[{"text":"    i[i[3]] = 4;","highlight_start":5,"highlight_end":6}],"label":"mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs","byte_start":5785,"byte_end":5792,"line_start":167,"line_end":167,"column_start":5,"column_end":12,"is_primary":false,"text":[{"text":"    i[i[3]] = 4;","highlight_start":5,"highlight_end":12}],"label":"borrow later used here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable\n  --> /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:167:7\n   |\nLL |     i[i[3]] = 4;\n   |     --^----\n   |     | |\n   |     | immutable borrow occurs here\n   |     mutable borrow occurs here\n   |     borrow later used here\n\n"}
[00:47:53] {"message":"cannot borrow `i` as immutable because it is also borrowed as mutable","code":{"code":"E0502","explanation":"\nThis error indicates that you are trying to borrow a variable aruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership sion of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semantics at all and are trivial to duplicate. An\nexample is `i32` and the other number types. We don't have to call `.clone()` to\nclone them, because they are marked `Copy` in addition to `Clone`.  Implicit\ncloning is more convenient in this case. We can mark our own types `Copy` if\nall their members also are marked `Copy`.\n\nIn the example below, we implement a `Point` type. Because it only stores two\nintegers, we opt-out of ownership semantics with `Copy`. Then we can\n`let p2 = p1` without `p1` being moved.\n\n```\n#[derive(Copy, Clone)]\nstruct Point { x: i32, y: i32 }\n\nfn main() {\n    let mut p1 = Point{ x: -1, y: 2 };\n    let p2 = p1;\n    p1.x = 1;\n    println!(\"p1: {}, {}\", p1.x, p1.y);\n    println!(\"p2: {}, {}\", p2.x, p2.y);\n}\n```\n\nAlternatively, if we don't control the struct's definition, or mutable shared\nownership is truly required, we can use `Rc` and `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-eeference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/nll/move-subpaths-moves-root.rs","byte_start":537,"byte_end":540,"line_start":15,"line_end":15,"column_start":10,"column_end":13,"is_primary":false,"text":[{"text":"    drop(x.0);","highlight_start":10,"highlight_end":13}],"label":"value moved here ","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/nll/move-subpaths-moves-root.rs","byte_start":552,"byte_end":553,"line_start":16,"line_end":16,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    drop(x);","highlight_start":10,"highlight_end":11}],"label":"value used here after move","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value: `x`\n  --> /checkout/src/test/ui/nll/move-subpaths-moves-root.rs:16:10\n   |\nLL |     drop(x.0);\n   |          --- value moved here \nLL |     drop(x);\n   |          ^ value used here after move\n   |\n   = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait\n\n"}
Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition" "2018" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/try-block/try-block-maybe-bad-lifetime/auxiliary" "-A" "unused"
[00:47:53] ------------------------------------------
[00:47:53] 
[00:47:53] ------------------------------------------
[00:47:53] stderr:
[00:47:53] stderr:
[00:47:53] ------------------------------------------
[00:47:53] {"message":"cannot assign to `i` because it is borrowed","code":{"code":"E0506","explanation":"\nThis error occurs when an attempt is made to assign to a borrowed value.\n\nExample of erroneous code:\n\n```compile_fail,E0506\nstruct FancyNum {\n    num: u8,\n}\n\nfn main() {\n    let mut fancy_num = FancyNum { num: 5 };\n    let fancy_ref = &fancy_num;\n    fancy_num = FancyNum { num: 6 };\n    // error: cannot assign to `fancy_num` because it is borrowed\n\n    println!(\"Num: {}, Ref: {}\", fancy_num.num, fancy_ref.num);\n}\n```\n\nBecause `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't\nbe assigned to a new value as it would invalidate the reference.\n\nAlternatively, we can move out of `fancy_num` into a second `fancy_num`:\n\n```\nstruct FancyNum {\n    num: u8,\n}\n\nfn main() {\n    let mut fancy_num = FancyNum { num: 5 };\n    let moved_num = fancy_num;\n    fancy_num = FancyNum { num: 6 };\n\n    println!(\"Num: {}, Moved num: {}\", fancy_num.num, moved_num.num);\n}\n```\n\nIf the value has to be borrowed, try limiting the lifetime of the borrow using\na scoped block:\n\n```\nstruct FancyNum {\n    num: u8,\n}\n\nfn main() {\n    let mut fancy_num = Fan

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

Copy link
Member

@davidtwco davidtwco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really great! Just a couple small things I noticed when taking a look at this.

src/librustc_mir/borrow_check/error_reporting.rs Outdated Show resolved Hide resolved
debug!(
"report_use_of_moved_or_uninitialized: current_location={:?}",
l
location
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could you add is_back_edge to this debug! too? It's useful if someone else ever needs to make a change here and work out what is happening from the logging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. That is a good point.

@@ -134,8 +152,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
format!("value moved{} here in previous iteration of loop", move_msg),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: perhaps add a comma in this message too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@davidtwco
Copy link
Member

I couldn't this to the above review below since you didn't change these lines, but could you change the error message in the below snippet to have a comma so all of the "iteration of loop" messages are consistent? (I'm pretty sure this still makes sense gramatically)

ie. borrow captured here by closure in later iteration of loop becomes borrow captured here by closure, in later iteration of loop

let message = if is_in_closure {
"borrow captured here by closure in later iteration of loop"
} else {
"borrow used here in later iteration of loop"
};

Before this patch running the following command would generate the given output:
$ rustc +stage1 src/test/ui/liveness/liveness-move-in-while.rs -Zborrowck=mir -Ztwo-phase-borrows
error[E0382]: borrow of moved value: `y`
 --> src/main.rs:8:24
  |
8 |         println!("{}", y); //~ ERROR use of moved value: `y`
  |                        ^ value borrowed here after move
9 |         while true { while true { while true { x = y; x.clone(); } } }
  |                                                    - value moved here
  |
  = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait

We want to give the user more hint by telling them that the value was moved in the previous iteration of the
loop. After this patch, the error message adds the phrase "in previous iteration of loop" and in totality
looks like this:

$ rustc +stage1 src/test/ui/liveness/liveness-move-in-while.rs -Zborrowck=mir -Ztwo-phase-borrows
error[E0382]: borrow of moved value: `y`
  --> src/test/ui/liveness/liveness-move-in-while.rs:17:24
   |
17 |         println!("{}", y); //~ ERROR use of moved value: `y`
   |                        ^ value borrowed here after move
18 |         while true { while true { while true { x = y; x.clone(); } } }
   |                                                    - value moved here, in previous iteration of loop
   |
   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:46:32] running 4308 tests
[00:46:35] ....................................................................................................
[00:46:38] ....................................................................................................
[00:46:41] ....................................................................................................
[00:46:44] ....................F......................................................................F........
[00:46:50] .......................i............................................................................
[00:46:55] ....................................................................................................
[00:47:00] ................................i...........i.......................................................
[00:47:03] ...................................................iiiii............................................
---
[00:47:50] ....................................................................................................
[00:47:54] ................................................................................................i...
[00:47:57] ....................................................................................................
[00:48:00] ........................................................i.i..ii.....................................
[00:48:03] ..............................................F.....................................................
[00:48:10] ....................................................................................................
[00:48:13] ....................................................................................................
[00:48:15] ....................................................................................................
[00:48:18] ....................................................................................................
---
[00:48:45] 
[00:48:45] ---- [ui] ui/borrowck/borrowck-mut-borrow-linear-errors.rs#mir stdout ----
[00:48:45] diff of stderr:
[00:48:45] 
[00:48:45] 4 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
[00:48:45] 5    |                    ----      ^^^^^^ second mutable borrow occurs here
[00:48:45] -    |                    borrow used here in later iteration of loop
[00:48:45] -    |                    borrow used here in later iteration of loop
[00:48:45] +    |                    borrow used here, in later iteration of loop
[00:48:45] 8 ...
[00:48:45] 9 LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
[00:48:45] 10    |                              ------ first mutable borrow occurs here
[00:48:45] 13   --> $DIR/borrowck-mut-borrow-linear-errors.rs:25:30
[00:48:45] 14    |
[00:48:45] 14    |
[00:48:45] 15 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
[00:48:45] -    |                    ---- borrow used here in later iteration of loop
[00:48:45] +    |                    ---- borrow used here, in later iteration of loop
[00:48:45] 17 LL |             //[mir]~^ ERROR [E0499]
[00:48:45] 18 LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
[00:48:45] 19    |                              ^^^^^^ second mutable borrow occurs here
[00:48:45] 
[00:48:45] The actual stderr differed from the expected stderr.
[00:48:45] The actual stderr differed from the expected stderr.
[00:48:45] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir/bome\n```\n\nPlease note that in rust, you can either have many immutable references, or one\nmutable reference. Take a look at\nhttps://doc.rust-lang.org/stable/book/references-and-borrowing.html for more\ninformation. Example:\n\n\n```\nlet mut i = 0;\nlet mut x = &mut i; // ok!\n\n// or:\nlet mut i = 0;\nlet a = &i; // ok!\nlet b = &i; // still ok!\nlet c = &i; // still ok!\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs","byte_start":1066,"byte_end":1072,"line_start":27,"line_end":27,"column_start":30,"column_end":36,"is_primary":false,"text":[{"text":"            _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":30,"highlight_end":36}],"label":"first mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs","byte_start":868,"byte_end":874,"line_start":23,"line_end":23,"column_start":30,"column_end":36,"is_primary":true,"text":[{"text":"            1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":30,"highlight_end":36}],"label":"second mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs","byte_start":858,"byte_end":862,"line_start":23,"line_end":23,"column_start":20,"column_end":24,"is_primary":false,"text":[{"text":"            1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":20,"highlight_end":24}],"label":"borrow used here, in la        _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":30,"highlight_end":36}],"label":"first mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs","byte_start":967,"byte_end":973,"line_start":25,"line_end":25,"column_start":30,"column_end":36,"is_primary":true,"text":[{"text":"            2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":30,"highlight_end":36}],"label":"second mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs","byte_start":858,"byte_end":862,"line_start":23,"line_end":23,"column_start":20,"column_end":24,"is_primary":false,"text":[{"text":"            1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]","highlight_start":20,"highlight_end":24}],"label":"borrow used here, in later iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0499]: cannot borrow `x` as mutable more than once at a time\n  --> /checkout/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.rs:25:30\n   |\nLL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]\n   |                    ---- borrow used here, in later iteration of loop\nLL |             //[mir]~^ ERROR [E0499]\nLL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]\n   |                              ^^^^^^ second mutable borrow occurs here\nLL |                                       ^^^^^^ mutable borrow starts here in previous iteration of loop\n\n"}
[00:48:45] {"message":"aborting due to 3 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 3 previous errors\n\n"}
[00:48:45] {"message":"For more information about this error, try `rustc --explain E0499`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0499`.\n"}
[00:48:45] ------------------------------------------
[00:48:45] 
[00:48:45] thread '[ui] ui/borrowck/borrowck-mut-borrow-linear-errors.rs#mir' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3258:9
[00:48:45] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:48:45] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:48:45] 
[00:48:45] ---- [ui] ui/borrowck/issue-41962.rs stdout ----
[00:48:45] diff of stderr:
[00:48:45] 
[00:48:45] 20   --> $DIR/issue-41962.rs:17:21
[00:48:45] 21    |
[00:48:45] 22 LL |         if let Some(thing) = maybe {
[00:48:45] -    |                     ^^^^^ value moved here in previous iteration of loop
[00:48:45] +    |                     ^^^^^ value moved here, in previous iteration of loop
[00:48:45] 24    |
[00:48:45] 25    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
[00:48:45] 
[00:48:45] 
[00:48:45] The actual stderr differed from the expected stderr.
[00:48:45] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/issue-41962/issue-41962.stderr
[00:48:45] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/issue-41962/issue-41962.stderr
[00:48:45] To update references, rerun the tests and pass the ed to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semantics at all and are trivial to duplicate. An\nexample is `i32` and the other number types. We don't have to call `.clone()` to\nclone them, because they are marked `Copy` in addition to `Clone`.  Implicit\ncloning is more convenient in this case. We can mark our own types `Copy` if\nall their members also are marked `Copy`.\n\nIn the example/src/test/ui/borrowck/issue-41962.rs","byte_start":593,"byte_end":598,"line_start":17,"line_end":17,"column_start":21,"column_end":26,"is_primary":false,"text":[{"text":"        if let Some(thing) = maybe {","highlight_start":21,"highlight_end":26}],"label":"value moved here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of partially moved value: `maybe` (Ast)\n  --> /checkout/src/test/ui/borrowck/issue-41962.rs:17:30\n   |\nLL |         if let Some(thing) = maybe {\n   |                     -----    ^^^^^ value used here after move\n   |                     |\n   |                     value moved here\n   |\n   = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait\n\n"}
[00:48:45] {"message":"use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast)","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semantics at all and are trivial to duplicate. An\nexample is `i32` and the other number types. We don't have to call `.clone()` to\nclone them, because they are marked `Copy` in addition to `Clone`.  Implicit\ncloning is more convenient in this case. We can mark our own types `Copy` if\nall their members also are   println!(\"p2: {}, {}\", p2.x, p2.y);\n}\n```\n\nAlternatively, if we don't control the struct's definition, or mutable shared\nownership is truly required, we can use `Rc` and `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/borrowck/issue-41962.rs","byte_start":593,"byte_end":598,"line_start":17,"line_end":17,"column_start":21,"column_end":26,"is_primary":true,"text":[{"text":"        if let Some(thing) = maybe {","highlight_start":21,"highlight_end":26}],"label":"value moved here, in previous iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value (Mir)\n  --> /checkout/src/test/ui/borrowck/issue-41962.rs:17:21\n   |\nLL |         if let Some(thing) = maybe {\n   |                     ^^^^^ value moved here, in previous iteration of loop\n   |\n   = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait\n\n"}
[00:48:45] {"message":"aborting due to 3 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 3 previous errors\n\n"}
[00:48:45] {"message":"For more information about this error, try `rustc --explain E0382`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0382`.\n"}
[00:48:45] ------------------------------------------
[00:48:45] 
[00:48:45] thread '[ui] ui/borrowck/issue-41962.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3258:9
[00:48:45] 
[00:48:45] 
[00:48:45] ---- [ui] ui/nll/closures-in-loops.rs stdout ----
[00:48:45] diff of stderr:
[00:48:45] 
[00:48:45] 4 LL |         || x; //~ ERROR
[00:48:45] 5    |         ^^ - use occurs due to use in closure
[00:48:45] 6    |         |
[00:48:45] -    |         value moved into closure here in previous iteration of loop
[00:48:45] +    |         value moved into closure here, in previous iteration of loop
[00:48:45] 8    |
[00:48:45] 9    = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
[00:48:45] 
[00:48:45] 
[00:48:45] The actual stderr differed from the expected stderr.
[00:48:45] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/nll/closures-in-loops/closures-in-loops.stderr
[00:48:45] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/nll/closures-in-loops/closures-in-loops.stderr
[00:48:45] To update references, rerun the tests and pass the `--bless` flag
[00:48:45] To only update this specific test, also pass `--test-args nll/closures-in-loops.rs`
[00:48:45] error: 1 errors occurred comparing output.
[00:48:45] status: exit code: 1
[00:48:45] status: exit code: 1
[00:48:45] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/nll/closures-in-loops.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/nll/closures-in-loops/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/nll/closures-in-loops/auxiliary" "-A" "unused"
[00:48:45] ------------------------------------------
[00:48:45] 
[00:48:45] ------------------------------------------
[00:48:45] stderr:
[00:48:45] stderr:
[00:48:45] ------------------------------------------
[00:48:45] {"message":"use of moved value: `x`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a refpe. Because it only stores two\nintegers, we opt-out of ownership semantics with `Copy`. Then we can\n`let p2 = p1` without `p1` being moved.\n\n```\n#[derive(Copy, Clone)]\nstruct Point { x: i32, y: i32 }\n\nfn main() {\n    let mut p1 = Point{ x: -1, y: 2 };\n    let p2 = p1;\n    p1.x = 1;\n    println!(\"p1: {}, {}\", p1.x, p1.y);\n    println!(\"p2: {}, {}\", p2.x, p2.y);\n}\n```\n\nAlternatively, if we don't control the struct's definition, or mutable shared\nownership is truly required, we can use `Rc` and `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/nll/closures-in-loops.rs","byte_start":636,"byte_end":638,"line_start":18,"line_end":18,"column_start":9,"column_end":11,"is_primary":true,"text":[{"text":"        || x; //~ ERROR","highlight_start":9,"highlight_end":11}],"label":"value moved into closure here, in previous iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/nll/closures-in-loops.rs","byte_start":639,"byte_end":640,"line_start":18,"line_end":18,"column_start":12,"column_end":13,"is_primary":false,"text":[{"text":"        || x; //~ ERROR","highlight_start":12,"highlight_end":13}],"label":"use occurs due to use in closure","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value: `x`\n  --> /checkout/src/test/ui/nll/closures-in-loops.rs:18:9\n   |\nLL |         || x; //~ ERROR\n   |         ^^ - use occurs due to use in closure\n   |         |\n   |         value moved into closure here, in previous iteration of loop\n   |\n   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait\n\n"}
[00:48:45] {"message":"cannot borrow `x` as mutable more than once at a time","code":{"code":"E0499","explanation":"\nA variable was borrowed as mutable more than once. Erroneous code example:\n\n```compile_fail,E0499\nlet mut i = 0;\nlet mut x = &mut i;\nlet mut a = &mut i;\n// error: cannot borrow `i` as mutable more than once at a time\n```\n\nPlease note that in rust, you can either have many immutable references, or one\nmutable reference. Take a look at\nhttps://doc.rust-lang.org/stable/book/references-and-borrowing.html for more\ninformation. Example:\n\n\n```\nlet mut i = 0;\nlet mut x = &mut i; // ok!\n\n// or:\nlet mut i = 0;\nlet a = &i; // ok!\nlet b = &i; // still ok!\nlet c = &i= String::new()); //~ ERROR","highlight_start":16,"highlight_end":18}],"label":"closures are constructed here in different iterations of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/nll/closures-in-loops.rs","byte_start":921,"byte_end":922,"line_start":32,"line_end":32,"column_start":20,"column_end":21,"is_primary":false,"text":[{"text":"        v.push(|| *x = String::new()); //~ ERROR","highlight_start":20,"highlight_end":21}],"label":"borrows occur due to use of `x` in closure","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0524]: two closures require unique access to `x` at the same time\n  --> /checkout/src/test/ui/nll/closures-in-loops.rs:32:16\n   |\nLL |         v.push(|| *x = String::new()); //~ ERROR\n   |                ^^  - borrows occur due to use of `x` in closure\n   |                |\n   |                closures are constructed here in different iterations of loop\n\n"}
[00:48:45] {"message":"aborting due to 3 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 3 previous errors\n\n"}
[00:48:45] {"message":"Some errors occurred: E0382, E0499, E0524.","code":null,"level":"","spans":[],"children":[],"rendered":"Some errors occurred: E0382, E0499, E0524.\n"}
[00:48:45] {"message":"For more information about an error, try `rustc --explain E0382`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about an error, try `rustc --explain E0382`.\n"}
[00:48:45] 
[00:48:45] -------------------path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[00:48:45] 
[00:48:45] 
[00:48:45] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[00:48:45] Build completed unsuccessfully in 0:03:16
[00:48:45] Build completed unsuccessfully in 0:03:16
[00:48:45] Makefile:58: recipe for target 'check' failed
[00:48:45] make: *** [check] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:116b0c36
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@nikomatsakis nikomatsakis changed the title [Work in progress] First shot at rust-lang/rust/issues/54015 First shot at #54015 Sep 28, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_fold:end:system_info

Network availability confirmed.
Setting APT mirror in /etc/apt/sources.list: http://us-central1.gce.archive.ubuntu.com/ubuntu/
travis_fold:start:update_heroku
Updating Heroku
$ heroku version
heroku/7.16.0 linux-x64 node-v10.10.0
travis_fold:end:update_heroku
Installing APT Packages
travis_time:start:12105678
$ travis_apt_get_update
travis_time:end:12105678:start=1538152080608349244,finish=1538152085611784486,duration=5003435242
---
[00:51:17] ....................................................................................................
[00:51:20] ................................................................i...................................
[00:51:23] ....................................................................................................
[00:51:26] ....................................................................................................
[00:51:29] .............iiiiiiiii..............................................................................
[00:51:35] ....................................................................................................
[00:51:35] ....................................................................................................
[00:51:38] ..........................................................FF.....................................i..
[00:51:41] ....................................................................................................
[00:51:44] .........................................................i.i..ii......F.............................
[00:51:51] .......i...................................................................................i........
[00:51:54] ..............i.....................................................................................
[00:51:57] ....................................................................................................
[00:52:00] ............................i..i..i.....................i...i.............ii.......................i
---
[00:52:18] ..............................................................................................i.....
[00:52:21] ....................................................................................................
[00:52:25] ....................................................................................................
[00:52:28] ....................................................................................................
[00:52:30] .........i.ii.ii.ii.............................i...................................................
" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/liveness/liveness-move-call-arg.nll/auxiliary" "-A" "unused"
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] ------------------------------------------
[00:52:30] stderr:
[00:52:30] stderr:
[00:52:30] ------------------------------------------
[00:52:30] {"message":"use of moved value: `x`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/liveness/liveness-move-call-arg.rs","byte_start":589,"byte_end":590,"line_start":19,"line_end":19,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"        take(x); //~ ERROR use of moved value: `x`","highlight_start":14,"highlight_end":15}],"label":"value moved here, in previous iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value: `x`\n  --> /checkout/src/test/ui/liveness/liveness-move-call-arg.rs:19:14\n   |\nLL |         take(x); //~ ERROR use of moved value: `x`\n   |              ^ value moved here, in previous iteration of loop\n   |\n   = note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait\n\n"}
[00:52:30] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:52:30] {"message":"For more information about this error, try `rustc --explain E0382`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0382`.\n"}
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] thread '[ui (nll)] ui/liveness/liveness-move-call-arg.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3258:9
[00:52:30] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:52:30] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:52:30] 
[00:52:30] ---- [ui (nll)] ui/liveness/liveness-move-in-loop.rs stdout ----
[00:52:30] diff of stderr:
[00:52:30] 
[00:52:30] 2   --> $DIR/liveness-move-in-loop.rs:21:25
[00:52:30] 3    |
[00:52:30] 4 LL |                     x = y; //~ ERROR use of moved value
[00:52:30] -    |                         ^ value moved here in previous iteration of loop
[00:52:30] +    |                         ^ value moved here, in previous iteration of loop
[00:52:30] 6    |
[00:52:30] 7    = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
[00:52:30] 
[00:52:30] 
[00:52:30] The actual stderr differed from the expected stderr.
[00:52:30] The actual stderr differed from the expected stderr.
[00:52:30] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/liveness/liveness-move-in-loop.nll/liveness-move-in-loop.nll.stderr
[00:52:30] To update references, rerun the tests and pass the `--bless` flag
[00:52:30] To only update this specific test, also pass `--test-args liveness/liveness-move-in-loop.rs`
[00:52:30] error: 1 errors occurred comparing output.
[00:52:30] status: exit code: 1
[00:52:30] status: exit code: 1
[00:52:30] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/liveness/liveness-move-in-loop.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/liveness/liveness-move-in-loop.nll/a" "-Zborrowck=mir" "-Ztwo-phase-borrows" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/liveness/liveness-move-in-loop.nll/auxiliary" "-A" "unused"
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] ------------------------------------------
[00:52:30] stderr:
[00:52:30] stderr:
[00:52:30] ------------------------------------------
[00:52:30] {"message":"use of moved value: `y`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remove(0);\n    println!(\"{} {}\", s1, s2);\n}\n```\n\nIf we control the definition of a type, we can implement `Clone` on it ourselves\nwith `#[derive(Clone)]`.\n\nSome types have no ownership semantics at all and are trivial to duplicate. An\nexample is `i32` and the other number types. We don't have to call `.clone()` to\nclone them, because they are marked `Copy` in addition to `Clone`.  Implicit\ncloning is more convenient in this case. We can mark our own types `Copy` if\nall their members also are marked `Copy`.\n\nIn the example below, we implement a `Point` type. Because it only stores two\nintegers, we opt-out of ownership semantics with `Copy`. Then we can\n`let p2 = p1` without `p1` being moved.\n\n```\n#[derive(Copy, Clone)]\nstruct Point { x: i32, y: i32 }\n\nfn main() {\n    let mut p1 = Point{ x: -1, y: 2 };\n    let p2 = p1;\n    p1.x = 1;\n    println!(\"p1: {}, {}\", p1.x, p1.y);\n    println!(\"p2: {}, {}\", p2.x, p2.y);\n}\n```\n\nAlternatively, if we don't control the struct's definition, or mutable shared\nownership is truly required, we can use `Rc` and `RefCell`:\n\n```\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));\n    let y = x.clone();\n    x.borrow_mut().s = 6;\n    println!(\"{}\", x.borrow().s);\n}\n```\n\nWith this approach, x and y share ownership of the data via the `Rc` (reference\ncount type). `RefCell` essentially performs runtime borrow checking: ensuring\nthat at most one writer or multiple readers can access the data at any one time.\n\nIf you wish to learn more about ownership in Rust, start with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/liveness/liveness-move-in-loop.rs","byte_start":682,"byte_end":683,"line_start":21,"line_end":21,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"                    x = y; //~ ERROR use of moved value","highlight_start":25,"highlight_end":26}],"label":"value moved here, in previous iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value: `y`\n  --> /checkout/src/test/ui/liveness/liveness-move-in-loop.rs:21:25\n   |\nLL |                     x = y; //~ ERROR use of moved value\n   |                         ^ value moved here, in previous iteration of loop\n   |\n   = note: move occurs because `y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait\n\n"}
[00:52:30] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:52:30] {"message":"For more information about this error, try `rustc --explain E0382`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0382`.\n"}
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] thread '[ui (nll)] ui/liveness/liveness-move-in-loop.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3258:9
[00:52:30] 
[00:52:30] 
[00:52:30] ---- [ui (nll)] ui/moves/move-in-guard-2.rs stdout ----
[00:52:30] diff of stderr:
[00:52:30] 
[00:52:30] 2   --> $DIR/move-in-guard-2.rs:20:24
[00:52:30] 3    |
[00:52:30] 4 LL |         (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
[00:52:30] -    |                        ^ value moved here in previous iteration of loop
[00:52:30] +    |                        ^ value moved here, in previous iteration of loop
[00:52:30] 6    |
[00:52:30] 7    = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
[00:52:30] 
[00:52:30] 
[00:52:30] The actual stderr differed from the expected stderr.
[00:52:30] The actual stderr differed from the expected stderr.
[00:52:30] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/moves/move-in-guard-2.nll/move-in-guard-2.nll.stderr
[00:52:30] To update references, rerun the tests and pass the `--bless` flag
[00:52:30] To only update this specific test, also pass `--test-args moves/move-in-guard-2.rs`
[00:52:30] error: 1 errors occurred comparing output.
[00:52:30] status: exit code: 1
[00:52:30] status: exit code: 1
[00:52:30] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/moves/move-in-guard-2.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/moves/move-in-guard-2.nll/a" "-Zborrowck=mir" "-Ztwo-phase-borrows" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/moves/move-in-guard-2.nll/auxiliary" "-A" "unused"
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] ------------------------------------------
[00:52:30] stderr:
[00:52:30] stderr:
[00:52:30] ------------------------------------------
[00:52:30] {"message":"use of moved value: `x`","code":{"code":"E0382","explanation":"\nThis error occurs when an attempt is made to use a variable after its contents\nhave been moved elsewhere. For example:\n\n```compile_fail,E0382\nstruct MyStruct { s: u32 }\n\nfn main() {\n    let mut x = MyStruct{ s: 5u32 };\n    let y = x;\n    x.s = 6;\n    println!(\"{}\", x.s);\n}\n```\n\nSince `MyStruct` is a type that is not marked `Copy`, the data gets moved out\nof `x` when we set `y`. This is fundamental to Rust's ownership system: outside\nof workarounds like `Rc`, a value cannot be owned by more than one variable.\n\nSometimes we don't need to move the value. Using a reference, we can let another\nfunction borrow the value without changing its ownership. In the example below,\nwe don't actually have to move our string to `calculate_length`, we can give it\na reference to it with `&` instead.\n\n```\nfn main() {\n    let s1 = String::from(\"hello\");\n\n    let len = calculate_length(&s1);\n\n    println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize {\n    s.len()\n}\n```\n\nA mutable reference can be created with `&mut`.\n\nSometimes we don't want a reference, but a duplicate. All types marked `Clone`\ncan be duplicated by calling `.clone()`. Subsequent changes to a clone do not\naffect the original variable.\n\nMost types in the standard library are marked `Clone`. The example below\ndemonstrates using `clone()` on a string. `s1` is first set to \"many\", and then\ncopied to `s2`. Then the first character of `s1` is removed, without affecting\n`s2`. \"any many\" is printed to the console.\n\n```\nfn main() {\n    let mut s1 = String::from(\"many\");\n    let s2 = s1.clone();\n    s1.remotart with the chapter in the\nBook:\n\nhttps://doc.rust-lang.org/book/first-edition/ownership.html\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/moves/move-in-guard-2.rs","byte_start":611,"byte_end":612,"line_start":20,"line_end":20,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":"        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`","highlight_start":24,"highlight_end":25}],"label":"value moved here, in previous iteration of loop","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0382]: use of moved value: `x`\n  --> /checkout/src/test/ui/moves/move-in-guard-2.rs:20:24\n   |\nLL |         (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`\n   |                        ^ value moved here, in previous iteration of loop\n   |\n   = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait\n\n"}
[00:52:30] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:52:30] {"message":"For more information about this error, try `rustc --explain E0382`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0382`.\n"}
[00:52:30] ------------------------------------------
[00:52:30] 
[00:52:30] 
[00:52:30] thread '[ui (nll--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always" "--compare-mode" "nll"
[00:52:30] 
[00:52:30] 
[00:52:30] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[00:52:30] Build completed unsuccessfully in 0:05:37
[00:52:30] Build completed unsuccessfully in 0:05:37
[00:52:30] make: *** [check] Error 1
[00:52:30] Makefile:58: recipe for target 'check' failed

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:0bdb61dd
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
---
travis_time:end:0b40ce26:start=1538155313451780278,finish=1538155313457621553,duration=5841275
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:1b69677a
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:0eedf112
travis_time:start:0eedf112
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:1841c878
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@nikomatsakis
Copy link
Contributor

@bors r

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Oct 2, 2018

📌 Commit 671e77d has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 2, 2018
@bors
Copy link
Contributor

bors commented Oct 2, 2018

⌛ Testing commit 671e77d with merge 2bd5993...

bors added a commit that referenced this pull request Oct 2, 2018
@bors
Copy link
Contributor

bors commented Oct 2, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 2bd5993 to master...

@bors bors merged commit 671e77d into rust-lang:master Oct 2, 2018
@pnkfelix pnkfelix changed the title First shot at #54015 NLL: Improve move error loop detection (was "First shot at #54015") Oct 3, 2018
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) NLL-diagnostics Working towards the "diagnostic parity" goal S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants