Skip to content

Commit 7285b56

Browse files
committed
Make migrate mode work at item level granularity
1 parent 913ad6d commit 7285b56

File tree

7 files changed

+129
-25
lines changed

7 files changed

+129
-25
lines changed

src/librustc/middle/expr_use_visitor.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ pub trait Delegate<'tcx> {
8282
assignment_span: Span,
8383
assignee_cmt: &mc::cmt_<'tcx>,
8484
mode: MutateMode);
85+
86+
// A nested closure or generator - only one layer deep.
87+
fn nested_body(&mut self, _body_id: hir::BodyId) {}
8588
}
8689

8790
#[derive(Copy, Clone, PartialEq, Debug)]
@@ -531,8 +534,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
531534
self.consume_expr(&base);
532535
}
533536

534-
hir::ExprKind::Closure(.., fn_decl_span, _) => {
535-
self.walk_captures(expr, fn_decl_span)
537+
hir::ExprKind::Closure(_, _, body_id, fn_decl_span, _) => {
538+
self.delegate.nested_body(body_id);
539+
self.walk_captures(expr, fn_decl_span);
536540
}
537541

538542
hir::ExprKind::Box(ref base) => {

src/librustc_borrowck/borrowck/gather_loans/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
153153
.node_type(id);
154154
gather_moves::gather_decl(self.bccx, &self.move_data, id, ty);
155155
}
156+
157+
fn nested_body(&mut self, body_id: hir::BodyId) {
158+
debug!("nested_body(body_id={:?})", body_id);
159+
// rust-lang/rust#58776: MIR and AST borrow check disagree on where
160+
// certain closure errors are reported. As such migrate borrowck has to
161+
// operate at the level of items, rather than bodies. Check if the
162+
// contained closure had any errors and set `signalled_any_error` if it
163+
// has.
164+
let bccx = self.bccx;
165+
if bccx.tcx.migrate_borrowck() {
166+
if let SignalledError::NoErrorsSeen = bccx.signalled_any_error.get() {
167+
let closure_def_id = bccx.tcx.hir().body_owner_def_id(body_id);
168+
debug!("checking closure: {:?}", closure_def_id);
169+
170+
bccx.signalled_any_error.set(bccx.tcx.borrowck(closure_def_id).signalled_any_error);
171+
}
172+
}
173+
}
156174
}
157175

158176
/// Implements the A-* rules in README.md.

src/librustc_mir/borrow_check/mod.rs

+5-23
Original file line numberDiff line numberDiff line change
@@ -329,30 +329,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
329329
// When borrowck=migrate, check if AST-borrowck would
330330
// error on the given code.
331331

332-
// rust-lang/rust#55492: loop over parents to ensure that
333-
// errors that AST-borrowck only detects in some parent of
334-
// a closure still allows NLL to signal an error.
335-
let mut curr_def_id = def_id;
336-
let signalled_any_error = loop {
337-
match tcx.borrowck(curr_def_id).signalled_any_error {
338-
SignalledError::NoErrorsSeen => {
339-
// keep traversing (and borrow-checking) parents
340-
}
341-
SignalledError::SawSomeError => {
342-
// stop search here
343-
break SignalledError::SawSomeError;
344-
}
345-
}
346-
347-
if tcx.is_closure(curr_def_id) {
348-
curr_def_id = tcx.parent_def_id(curr_def_id)
349-
.expect("a closure must have a parent_def_id");
350-
} else {
351-
break SignalledError::NoErrorsSeen;
352-
}
353-
};
332+
// rust-lang/rust#55492, rust-lang/rust#58776 check the base def id
333+
// for errors. AST borrowck is responsible for aggregating
334+
// `signalled_any_error` from all of the nested closures here.
335+
let base_def_id = tcx.closure_base_def_id(def_id);
354336

355-
match signalled_any_error {
337+
match tcx.borrowck(base_def_id).signalled_any_error {
356338
SignalledError::NoErrorsSeen => {
357339
// if AST-borrowck signalled no errors, then
358340
// downgrade all the buffered MIR-borrowck errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0597]: `**greeting` does not live long enough
2+
--> $DIR/issue-58776-borrowck-scans-children.rs:10:24
3+
|
4+
LL | let res = (|| (|| &greeting)())();
5+
| -- ^^^^^^^^ - borrowed value only lives until here
6+
| | |
7+
| | borrowed value does not live long enough
8+
| capture occurs here
9+
...
10+
LL | }
11+
| - borrowed value needs to live until here
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0506]: cannot assign to `greeting` because it is borrowed
2+
--> $DIR/issue-58776-borrowck-scans-children.rs:13:5
3+
|
4+
LL | let res = (|| (|| &greeting)())();
5+
| -- -------- borrow occurs due to use in closure
6+
| |
7+
| borrow of `greeting` occurs here
8+
...
9+
LL | greeting = "DEALLOCATED".to_string();
10+
| ^^^^^^^^ assignment to borrowed `greeting` occurs here
11+
...
12+
LL | println!("thread result: {:?}", res);
13+
| --- borrow later used here
14+
15+
error[E0505]: cannot move out of `greeting` because it is borrowed
16+
--> $DIR/issue-58776-borrowck-scans-children.rs:16:10
17+
|
18+
LL | let res = (|| (|| &greeting)())();
19+
| -- -------- borrow occurs due to use in closure
20+
| |
21+
| borrow of `greeting` occurs here
22+
...
23+
LL | drop(greeting);
24+
| ^^^^^^^^ move out of `greeting` occurs here
25+
...
26+
LL | println!("thread result: {:?}", res);
27+
| --- borrow later used here
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors occurred: E0505, E0506.
32+
For more information about an error, try `rustc --explain E0505`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0506]: cannot assign to `greeting` because it is borrowed
2+
--> $DIR/issue-58776-borrowck-scans-children.rs:13:5
3+
|
4+
LL | let res = (|| (|| &greeting)())();
5+
| -- -------- borrow occurs due to use in closure
6+
| |
7+
| borrow of `greeting` occurs here
8+
...
9+
LL | greeting = "DEALLOCATED".to_string();
10+
| ^^^^^^^^ assignment to borrowed `greeting` occurs here
11+
...
12+
LL | println!("thread result: {:?}", res);
13+
| --- borrow later used here
14+
15+
error[E0505]: cannot move out of `greeting` because it is borrowed
16+
--> $DIR/issue-58776-borrowck-scans-children.rs:16:10
17+
|
18+
LL | let res = (|| (|| &greeting)())();
19+
| -- -------- borrow occurs due to use in closure
20+
| |
21+
| borrow of `greeting` occurs here
22+
...
23+
LL | drop(greeting);
24+
| ^^^^^^^^ move out of `greeting` occurs here
25+
...
26+
LL | println!("thread result: {:?}", res);
27+
| --- borrow later used here
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors occurred: E0505, E0506.
32+
For more information about an error, try `rustc --explain E0505`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// ignore-compare-mode-nll
2+
3+
// revisions: ast migrate nll
4+
5+
//[migrate]compile-flags: -Z borrowck=migrate
6+
#![cfg_attr(nll, feature(nll))]
7+
8+
fn main() {
9+
let mut greeting = "Hello world!".to_string();
10+
let res = (|| (|| &greeting)())();
11+
//[ast]~^ ERROR does not live long enough
12+
13+
greeting = "DEALLOCATED".to_string();
14+
//[migrate]~^ ERROR cannot assign
15+
//[nll]~^^ ERROR cannot assign
16+
drop(greeting);
17+
//[migrate]~^ ERROR cannot move
18+
//[nll]~^^ ERROR cannot move
19+
20+
println!("thread result: {:?}", res);
21+
}

0 commit comments

Comments
 (0)