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

Treat generators as if they have an arbitrary destructor #49943

Merged
merged 2 commits into from
May 2, 2018

Conversation

pnkfelix
Copy link
Member

Conservatively assume dropping a generator touches its upvars, via locals' destructors.

Fix #49918

@rust-highfive
Copy link
Collaborator

r? @cramertj

(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 Apr 13, 2018
@pnkfelix
Copy link
Member Author

r? @Zoxc

@rust-highfive rust-highfive assigned Zoxc and unassigned cramertj Apr 13, 2018
@pnkfelix
Copy link
Member Author

pnkfelix commented Apr 13, 2018

(as noted in the comments in code, in principle we could do something smarter here, in terms of recursively analyzing the locals of the generator to see if we can prove e.g. that none of them have destructors. But that is complex and this is simple.)

@rust-highfive
Copy link
Collaborator

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:00:57] configure: rust.quiet-tests     := True
---
[00:42:55] ...............................................................................i....................
[00:43:00] ......................i.............................................................................
[00:43:04] ....................................................................................................
[00:43:08] ....................................................................................................
[00:43:11] ....................................................................................................
[00:43:15] ..........................................................................F.........................
[00:43:21] ....................................................................................................
[00:43:27] ....................................................................................................
[00:43:33] ....................................................................................................
[00:43:40] ..................i...........................................................................i.....
[00:43:46] ....................................................................................................
[00:43:52] ........ii..........................................................................................
---
[00:44:03] + error[E0597]: `*cell` does not live long enough
[00:44:03] +   --> $DIR/dropck.rs:19:40
[00:44:03] +    |
[00:44:03] + LL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
[00:44:03] +    |                                        ^^^^ borrowed value does not live long enough
[00:44:03] + ...
[00:44:03] + LL | }
[00:44:03] +    | - `*cell` dropped here while still borrowed
[00:44:03] +    |
[00:44:03] +    = note: values in a scope are dropped in the opposite order they are created
[00:44:03] +
[00:44:03] 1 error[E0597]: `ref_` does not live long enough
[00:44:03] 2   --> $DIR/dropck.rs:23:18
[00:44:03] 3    |
[00:44:03]
[00:44:03] 12    |
[00:44:03] 13    = note: values in a scope are dropped in the opposite order they are created
---
[00:44:03] /checkout/src/test/ui/update-references.sh '/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui' 'generator/dropck.rs'
[00:44:03]
[00:44:03] error: 1 errors occurred comparing output.
[00:44:03] status: exit code: 101
[00:44:03] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/generator/dropck.rs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--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/generator/dropck.stage2-x86_64-unknown-linux-gnu" "-Crpath" "-O" "-Zmiri" "-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/generator/dropck.stage2-x86_64-unknown-linux-gnu.aux" "-A" "unused"
[00:44:03] stdout:
[00:44:03] ------------------------------------------
[00:44:03]
[00:44:03] ------------------------------------------
[00:44:03] stderr:
[00:44:03] -----------------------are created","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0597]: `*cell` does not live long enough\n  --> /checkout/src/test/ui/generator/dropck.rs:19:40\n   |\nLL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));\n   |                                        ^^^^ borrowed value does not live long enough\n...\nLL | }\n   | - `*cell` dropped here while still borrowed\n   |\n   = note: values in a scope are dropped in the opposite order they are created\n\n"}
[00:44:03] {"message":"`ref_` does not live long enough","code":{"code":"E0597","explanation":"\nThis error occurs because a borrow was made inside a variable which has a\ngreater lifetime than the borrowed one.\n\nExample of erroneous code:\n\n```compile_fail,E0597\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet mut x = Foo { x: None };\nlet y = 0;\nx.x = Some(&y); // error: `y` does not live long enough\n```\n\nIn here, `x` is created before `y` and therefore has a greater lifetime. Always\nkeep in mind that values in a scope are dropped in the opposite order they are\ncreated. So to fix the previous example, just make the `y` lifetime greater than\nthe `x`'s one:\n\n```\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet y = 0;\nlet mut x = Foo { x: None };\nx.x = Some(&y);\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/generator/dropck.rs","byte_start":832,"byte_end":834,"line_start":21,"line_end":21,"column_start":11,"column_end":13,"is_primary":false,"text":[{"text":"    gen = || {","highlight_start":11,"highlight_end":13}],"label":"capture occurs here","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/dropck.rs","byte_start":920,"byte_end":924,"line_start":23,"line_end":23,"column_start":18,"column_end":22,"is_primary":true,"text":[{"text":"        let _d = ref_.take(); //~ ERROR `ref_` does not live long enough","highlight_start":18,"highlight_end":22}],"label":"borrowed value does not live long enough","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/dropck.rs","byte_start":1096,"byte_end":1097,"line_start":28,"line_end":28,"column_start":1,"column_end":2,"is_primary":false,"text":[{"text":"}","highlight_start":1,"highlight_end":2}],"label":"borrowed value dropped before borrower","suggested_replacement":null,"expansion":null}],"children":[{"message":"values in a scope are dropped in the opposite order they are created","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0597]: `ref_` does not live long enough\n  --> /checkout/src/test/ui/generator/dropck.rs:23:18\n   |\nLL |     gen = || {\n   |           -- capture occurs here\nLL |         // but the generator can use it to drop a `Ref<'a, i32>`.\nLL |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough\n   |                  ^^^^ borrowed value does not live long enough\n...\nLL | }\n   | - borrowed value dropped before borrower\n   |\n   = note: values in a scope are dropped in the opposite order they are created\n\n"}
[00:44:03] {"message":"aborting due to 2 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 2 previous errors\n\n"}
[00:44:03] {"me-lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "3.9.1\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[00:44:03] expected success, got: exit code: 101
[00:44:03]
[00:44:03]
[00:44:03] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[00:44:03] Build completed unsuccessfully in 0:02:16
[00:44:03] make: *** [check] Error 1
[00:44:03] Makefile:58: recipe for target 'check' failed
---
$ dmesg | grep -i kill
[   10.453064] init: failsafe main process (1094) killed by TERM signal

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)

@Zoxc
Copy link
Contributor

Zoxc commented Apr 15, 2018

This looks correct to me. We model generators as a struct of their upvars with a destructor which may access these upvars. The ui/generator/dropck.rs needs to be updated, and it would also like to see which errors it produces in this PR with NLL enabled.

I'd like someone who knows how dropck works to glance over it though. I'm just going to assume Niko is such a person.

r? @nikomatsakis

@rust-highfive rust-highfive assigned nikomatsakis and unassigned Zoxc Apr 15, 2018
ty::TyGenerator(def_id, substs, _) => {
// Note that the interior types are ignored here.
// Any type reachable inside the interior must also be reachable
// through the upvars.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment should be kept in some form. It serves as justification for why we can get away with only reporting the upvars instead of actually calculating all the types which may get dropped inside.

Copy link
Member Author

Choose a reason for hiding this comment

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

(okay, addressed this in followup commit)

@pnkfelix
Copy link
Member Author

I think the request to see what the output looks like under NLL will be satisfied by the eventual (hopefully soon) landing of PR #49900, so I won't put that change into this PR.

// because any side-effects from dropping `_interior` can
// only take place through references with lifetimes
// derived from lifetimes attached to the upvars, and we
// *do* traverse the uvpars here.
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo, uv-pars. Looks good otherwise.

@Zoxc
Copy link
Contributor

Zoxc commented Apr 16, 2018

@pnkfelix I'd just like you to run the test locally with NLL and post the errors in a comment here.

@pnkfelix
Copy link
Member Author

@Zoxc oh okay I can certainly do that.

@pnkfelix
Copy link
Member Author

@Zoxc here is the current behavior on ui/generator/dropck.rs with this PR under both AST-borrowck and NLL-borrowck:

AST-borrowck:

% ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/generator/dropck.rs
error[E0597]: `*cell` does not live long enough
  --> ../src/test/ui/generator/dropck.rs:19:40
   |
19 |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
   |                                        ^^^^ borrowed value does not live long enough
...
29 | }
   | - `*cell` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error[E0597]: `ref_` does not live long enough
  --> ../src/test/ui/generator/dropck.rs:24:18
   |
22 |     gen = || {
   |           -- capture occurs here
23 |         // but the generator can use it to drop a `Ref<'a, i32>`.
24 |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
   |                  ^^^^ borrowed value does not live long enough
...
29 | }
   | - borrowed value dropped before borrower
   |
   = note: values in a scope are dropped in the opposite order they are created

error: aborting due to 2 previous errors

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

NLL (-Z borrowck=mir):

% ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/generator/dropck.rs -Z borrowck=mir

error[E0597]: `ref_` does not live long enough
  --> ../src/test/ui/generator/dropck.rs:22:11
   |
22 |       gen = || {
   |  ___________^
23 | |         // but the generator can use it to drop a `Ref<'a, i32>`.
24 | |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
25 | |         yield;
26 | |     };
   | |_____^ borrowed value does not live long enough
...
29 |   }
   |   -
   |   |
   |   borrowed value only lives until here
   |   borrow later used here, when `gen` is dropped

error: aborting due to previous error

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

@arielb1
Copy link
Contributor

arielb1 commented Apr 21, 2018

There's already a test for this at https://github.com/rust-lang/rust/blob/master/src/test/ui/generator/dropck.rs, that was commented out for some reason. With this PR, that test should give an error.

let new_constraints: Vec<ty::subst::Kind<'tcx>> =
substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect();

let mut constraint = substs
Copy link
Contributor

@arielb1 arielb1 Apr 21, 2018

Choose a reason for hiding this comment

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

https://github.com/rust-lang/rust/pull/45337/files#r145093242
It might be a better idea to treat generators like trait object and have them always be dtorck. If generators are "supposed to be" captured by an impl Trait or trait object, this shouldn't be a problem in practice..

There's no reason to have both outlives and dtorck constraints together, the outlives constraint is always stricter than the is-destruction-safe constraint.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you saying @arielb1 that we only need to invoke constraint.outlives.extend(new_contraints), and not also include dtorck_constraint_for_ty?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure just return new_constraints as outlives constrains, same as trait objects.

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.

@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 Apr 25, 2018
@shepmaster
Copy link
Member

Ping from triage, @pnkfelix ! Will you have time to address the review feedback in the near future?

@pnkfelix
Copy link
Member Author

@shepmaster yep, I'll do it either today or tomorrow. (I was out on PTO last week.)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 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] ..............................i.....................................................................
[00:46:37] ....................................................................................................
[00:46:41] ....................................................................................................
[00:46:46] ....................................................................................................
[00:46:51] .................................................................................F.F.....F..........
[00:47:04] ....................................................................................................
[00:47:10] ....................................................................................................
[00:47:17] ....................................i...............................................................
[00:47:23] ............i.......................................................................................
---
[00:47:47]  diff of stderr:
[00:47:47] 
[00:47:47] - error: compilation successful
[00:47:47] -   --> $DIR/borrowing.rs:15:1
[00:47:47] + error[E0597]: `a` does not live long enough
[00:47:47] +   --> $DIR/borrowing.rs:18:18
[00:47:47] 3    |
[00:47:47] - LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
[00:47:47] - LL | |     let _b = {
[00:47:47] - LL | |         let a = 3;
[00:47:47] - LL | |         unsafe { (|| yield &a).resume() }
[00:47:47] - ...  |
[00:47:47] - LL | |     };
[00:47:47] - LL | | }
[00:47:47] -    | |_^
[00:47:47] + LL |         unsafe { (|| yield &a).resume() }
[00:47:47] +    |                  |
[00:47:47] +    |                  |
[00:47:47] +    |                  borrowed value does not live long enough
[00:47:47] +    |                  borrow may end up in a temporary, created here
[00:47:47] + LL |         //~^ ERROR: `a` does not live long enough
[00:47:47] + LL |     };
[00:47:47] +    |     -- temporary later dropped here, potentially using the reference
[00:47:47] +    |     |
[00:47:47] +    |     borrowed value only lives until here
[00:47:47] - error: aborting due to previous error
[00:47:47] - error: aborting due to previous error
[00:47:47] + error[E0597]: `a` does not live long enough
[00:47:47] +   --> $DIR/borrowing.rs:24:9
[00:47:47] +    |
[00:47:47] + LL | /         || {
[00:47:47] + LL | |             yield &a
[00:47:47] + LL | |             //~^ ERROR: `a` does not live long enough
[00:47:47] + LL | |         }
[00:47:47] +    | |_________^ borrowed value does not live long enough
[00:47:47] + LL |       };
[00:47:47] +    |       - borrowed value only lives until here
[00:47:47] + LL |   }
[00:47:47] +    |   - borrow later used here, when `_b` is dropped
[00:47:47] + error: aborting due to 2 previous errors
[00:47:47] + 
[00:47:47] + For more information about this error, try `rustc --explain E0597`.
[00:47:47] 15 
[00:47:47] 15 
[00:47:47] 
[00:47:47] 
[00:47:47] The actual stderr differed from the expected stderr.
[00:47:47] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/generator/borron here, `x` is created before `y` and therefore has a greater lifetime. Always\nkeep in mind that values in a scope are dropped in the opposite order they are\ncreated. So to fix the previous example, just make the `y` lifetime greater than\nthe `x`'s one:\n\n```\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet y = 0;\nlet mut x = Foo { x: None };\nx.x = Some(&y);\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":651,"byte_end":664,"line_start":18,"line_end":18,"column_start":18,"column_end":31,"is_primary":true,"text":[{"text":"        unsafe { (|| yield &a).resume() }","highlight_start":18,"highlight_end":31}],"label":"borrowed value does not live long enough","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":730,"byte_end":731,"line_start":20,"line_end":20,"column_start":5,"column_end":6,"is_primary":false,"text":[{"text":"    };","highlight_start":5,"highlight_end":6}],"label":"borrowed value only lives until here","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":651,"byte_end":664,"line_start":18,"line_end":18,"column_start":18,"column_end":31,"is_primary":true,"text":[{"text":"        unsafe { (|| yield &a).resume() }","highlight_start":18,"highlight_end":31}],"label":"borrow may end up in a temporary, created here","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":731,"byte_end":732,"line_start":20,"line_end":20,"column_start":6,"column_end":7,"is_primary":false,"text":[{"text":"    };","highlight_start":6,"highlight_end":7}],"label":"temporary later dropped here, potentially using the reference","suggested_replacement":null,"expansion":null}],"children":[],"rendered":"error[E0597]: `a` does not live long enough\n  --> /checkout/src/test/ui/generator/borrowing.rs:18:18\n   |\nLL |         unsafe { (|| yield &a).resume() }\n   |                  ^^^^^^^^^^^^^\n   |                  |\n   |                  borrowed value does not live long enough\n   |                  borrow may end up in a temporary, created here\nLL |         //~^ ERROR: `a` does not live long enough\nLL |     };\n   |     -- temporary later dropped here, potentially using the reference\n   |     |\n   |     borrowed value only lives until here\n\n"}
[00:47:47] {"message":"`a` does not live long enough","code":{"code":"E0597","explanation":"\nThis error occurs because a borrow was made inside a variable which has a\ngreater lifetime than the borrowed one.\n\nExample of erroneous code:\n\n```compile_fail,E0597\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet mut x = Foo { x: None };\nlet y = 0;\nx.x = Some(&y); // error: `y` does not live long enough\n```\n\nIn here, `x` is created before `y` and therefore has a greater lifetime. Always\nkeep in mind that values in a scope are dropped in the opposite order they are\ncreated. So to fix the previous example, just make the `y` lifetime greater than\nthe `x`'s one:\n\n```\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet y = 0;\nlet mut x = Foo { x: None };\nx.x = Some(&y);\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":776,"byte_end":865,"line_start":24,"line_end":27,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":"        || {","highlight_start":9,"highlight_end":13},{"text":"            yield &a","highlight_start":1,"highlight_end":21},{"text":"            //~^ ERROR: `a` does not live long enough","highlight_start":1,"highlight_end":54},{"text":"        }","highlight_start":1,"highlight_end":10}],"label":"borrowed value does not live long enough","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":870,"byte_end":871,"line_start":28,"line_end":28,"column_start":5,"column_end":6,"is_primary":false,"text":[{"text":"    };","highlight_start":5,"highlight_end":6}],"label":"borrowed value only lives until here","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/borrowing.rs","byte_start":873,"byte_end":874,"line_start":29,"line_end":29,"column_start":1,"column_end":2,"is_primary":false,"text":[{"text":"}","highlight_start":1,"highlight_end":2}],"label":"borrow later used here, when `_b` is dropped","suggested_replacement":null,"expansion":null}],"children":[],"rendered":"error[E0597]: `a` does not live long enough\n  --> /checkout/src/test/ui/generator/borrowing.rs:24:9\n   |\nLL | /         || {\nLL | |             yield &a\nLL | |             //~^ ERROR: `a` does not live long enough\nLL | |         }\n   | |_________^ borrowed value does not live long enough\nLL |       };\n   |       - borrowed value only lives until here\nLL |   }\n   |   - borrow later used here, when `_b` is dropped\n\n"}
[00:47:47] {"message":"aborting due to 2 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 2 previous errors\n\n"}
[00:47:47] {"message":"For more information about this error, try `rustc --explain E0597`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0597`.\n"}
[00:47:47] ------------------------------------------
[00:47:47] 
[00:47:47] thread '[ui (nll)] ui/generator/borrowing.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:2965:9
[00:47:47] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:47:47] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:47:47] 
[00:47:47] ---- [ui (nll)] ui/generator/dropck.rs stdout ----
[00:47:47]  diff of stderr:
[00:47:47] 
[00:47:47] - error: compilation successful
[00:47:47] -   --> $DIR/dropck.rs:16:1
[00:47:47] + error[E0597]: `ref_` does not live long enough
[00:47:47] +   --> $DIR/dropck.rs:22:11
[00:47:47] 3    |
[00:47:47] - LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
[00:47:47] - LL | |     let (cell, mut gen);
[00:47:47] - LL | |     cell = Box::new(RefCell::new(0));
[00:47:47] - LL | |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
[00:47:47] - ...  |
[00:47:47] - LL | |     // drops the RefCell and then the Ref, leading to use-after-free
[00:47:47] - LL | | }
[00:47:47] -    | |_^
[00:47:47] + LL |       gen = || {
[00:47:47] +    |  ___________^
[00:47:47] + LL | |         // but the generator can use it to drop a `Ref<'a, i32>`.
[00:47:47] + LL | |         let _d = ref_.take(); //~ ERROR `ref_` does not livestc --explain E0597`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0597`.\n"}
[00:47:47] ------------------------------------------
[00:47:47] 
[00:47:47] thread '[ui (nll)] ui/generator/dropck.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:2965:9
[00:47:47] 
[00:47:47] 
[00:47:47] ---- [ui (nll)] ui/generator/ref-escapes-but-not-over-yield.rs stdout ----
[00:47:47]  diff of stderr:
[00:47:47] 
[00:47:47] 1 error[E0597]: `b` does not live long enough
[00:47:47] 3    |
[00:47:47] 3    |
[00:47:47] - LL |         a = &b;
[00:47:47] -    |             ^^ borrowed value does not live long enough
[00:47:47] - LL |         //~^ ERROR `b` does not live long enough
[00:47:47] - LL |     };
[00:47:47] -    |     - borrowed value only lives until here
[00:47:47] + LL |       let mut b = move || {
[00:47:47] +    |  _________________-
[00:47:47] + LL | |         yield();
[00:47:47] + LL | |         let b = 5;
[00:47:47] + LL | |         a = &b;
[00:47:47] +    | |             ^^ borrowed value does not live long enough
[00:47:47] + LL | |         //~^ ERROR `b` does not live long enough
[00:47:47] + LL | |     };
[00:47:47] +    | |     |
[00:47:47] +    | |     |
[00:47:47] +    | |     borrowed value only lives until here
[00:47:47] +    | |_____temporary later dropped here, potentially using the reference
[00:47:47] +    |       borrow may end up in a temporary, created here
[00:47:47] 10 error: aborting due to previous error
[00:47:47] 11 
[00:47:47] 
[00:47:47] 
[00:47:47] 
[00:47:47] The actual stderr differed from the expected stderr.
[00:47:47] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
[00:47:47] /checkout/src/test/ui/update-references.sh '/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui' 'generator/ref-escapes-but-not-over-yield.rs'
[00:47:47] 
[00:47:47] error: 1 errors occurred comparing output.
[00:47:47] status: exit code: 101
[00:47:47] status: exit code: 101
[00:47:47] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/generator/ref-escapes-but-not-over-yield.rs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--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/generator/ref-escapes-but-not-over-yield.stage2-x86_64-unknown-linux-gnu" "-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/generator/ref-escapes-but-not-over-yield.stage2-x86_64-unknown-linux-gnu.aux" "-A" "unused"
[00:47:47] ------------------------------------------
[00:47:47] 
[00:47:47] ------------------------------------------
[00:47:47] stderr:
[00:47:47] stderr:
[00:47:47] ------------------------------------------
[00:47:47] {"message":"`b` does not live long enough","code":{"code":"E0597","explanation":"\nThis error occurs because a borrow was made inside a variable which has a\ngreater lifetime than the borrowed one.\n\nExample of erroneous code:\n\n```compile_fail,E0597\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet mut x = Foo { x: None };\nlet y = 0;\nx.x = Some(&y); // error: `y` does not live long enough\n```\n\nIn here, `x` is created before `y` and therefore has a greater lifetime. Always\nkeep in mind that values in a scope are dropped in the opposite order they are\ncreated. So to fix the previous example, just make the `y` lifetime greater than\nthe `x`'s one:\n\n```\nstruct Foo<'a> {\n    x: Option<&'a u32>,\n}\n\nlet y = 0;\nlet mut x = Foo { x: None };\nx.x = Some(&y);\n```\n"},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/generator/ref-escapes-but-not-over-yield.rs","byte_start":882,"byte_end":884,"line_start":24,"line_end":24,"column_start":13,"column_end":15,"is_primary":true,"text":[{"text":"        a = &b;","highlight_start":13,"highlight_end":15}],"label":"borrowed value does not live long enough","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/ref-escapes-but-not-over-yield.rs","byte_start":939,"byte_end":940,"line_start":26,"line_end":26,"column_start":5,"column_end":6,"is_primary":false,"text":[{"text":"    };","highlight_start":5,"highlight_end":6}],"label":"borrowed value only lives until here","suggested_replacement":null,"expansion":null},{"file_name":"/checkout/src/test/ui/generator/ref-escapes-but-not-over-yield.rs","byte_start":824,"byte_end":940,"line_start":21,"line_end":26,"column_start":17,"column_end":6,"is_primary":false,"text":[{"text":"    let mut b = move |ror: aborting due to previous error\n\n"}
[00:47:47] {"message":"For more information about this error, try `rustc --explain E0597`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0597`.\n"}
[00:47:47] ------------------------------------------
[00:47:47] 
[00:47:47] thread '[ui (nll)] ui/generator/ref-escapes-but-not-over-yield.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:2965:9
[00:47:47] 
---
[00:47:47] test result: FAILED. 1370 passed; 3 failed; 7 ignored; 0 measured; 0 filtered out
[00:47:47] 
[00:47:47] 
[00:47:47] 
[00:47:47] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-3.9/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Zunstable-options " "--target-rustcflags" "-Crpath4G  4.0K  7.4G   1% /dev
/dev/sda1        30G  9.8G   19G  35% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none            7.4G     0  7.4G   0% /run/shm
---
60840 ./src/llvm-emscripten/lib
56092 ./obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/bin
55348 ./obj/build/x86_64-unknown-linux-gnu/stage0-rustc/release
53752 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/incremental/syntax-284je5yviillk
53748 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/incremental/syntax-284je5yviillk/s-f0lq29bbi9-erx9ij-yefbrhq8bkke
48604 ./obj/build/x86_64-unknown-linux-gnu/stage0/bin
47832 ./obj/build/x86_64-unknown-linux-gnu/stage0-std
46868 ./src/test
46820 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps

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)

pnkfelix added 2 commits May 1, 2018 22:28
…cals' dtors.

This is meant to address rust-lang#49918.

Review feedback: put back comment justifying skipping interior traversal.

Review feedback: dropck generators like trait objects: all their upvars must
outlive the generator itself, so just create a DtorckConstraint saying so.
@pnkfelix pnkfelix force-pushed the fix-issue-49918 branch from d71cb04 to f12d7a5 Compare May 1, 2018 21:03
@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 1, 2018
@kennytm kennytm removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 1, 2018
@pnkfelix
Copy link
Member Author

pnkfelix commented May 2, 2018

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented May 2, 2018

📌 Commit f12d7a5 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-review Status: Awaiting review from the assignee but also interested parties. labels May 2, 2018
@bors
Copy link
Contributor

bors commented May 2, 2018

⌛ Testing commit f12d7a5 with merge d40a0b3...

bors added a commit that referenced this pull request May 2, 2018
Treat generators as if they have an arbitrary destructor

Conservatively assume dropping a generator touches its upvars, via locals' destructors.

Fix #49918
@bors
Copy link
Contributor

bors commented May 2, 2018

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

@bors bors merged commit f12d7a5 into rust-lang:master May 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

9 participants