Skip to content

Commit 44f13d9

Browse files
committed
NLL: Suggest extraction of subcomputation into a new binding
1 parent 0aa8d03 commit 44f13d9

4 files changed

+86
-2
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ use rustc::middle::region::ScopeTree;
1313
use rustc::mir::VarBindingForm;
1414
use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local};
1515
use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
16-
use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
16+
use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind};
1717
use rustc::ty;
1818
use rustc_data_structures::indexed_vec::Idx;
1919
use rustc_data_structures::sync::Lrc;
2020
use rustc_errors::DiagnosticBuilder;
2121
use syntax_pos::Span;
2222

2323
use super::borrow_set::BorrowData;
24-
use super::{Context, MirBorrowckCtxt};
24+
use super::{Context, ContextKind, MirBorrowckCtxt};
2525
use super::{InitializationRequiringAction, PrefixSet};
2626

2727
use dataflow::move_paths::MovePathIndex;
@@ -372,6 +372,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
372372

373373
self.explain_why_borrow_contains_point(context, issued_borrow, None, &mut err);
374374

375+
let bb = &self.mir[context.loc.block];
376+
if let (&TerminatorKind::Call { ref args, .. }, ContextKind::AssignRhs) =
377+
(&bb.terminator().kind, context.kind)
378+
{
379+
let stmt = &bb.statements[context.loc.statement_index];
380+
let assigned_place = match stmt.kind {
381+
StatementKind::Assign(ref place, _) => place,
382+
_ => unreachable!(),
383+
};
384+
385+
for arg in args {
386+
match arg {
387+
Operand::Copy(ref operand) | Operand::Move(ref operand) => {
388+
if assigned_place == operand {
389+
err.span_note(
390+
bb.terminator().source_info.span,
391+
&format!("consider extracting this into a `let`-binding")
392+
);
393+
}
394+
}
395+
Operand::Constant(..) => {}
396+
}
397+
}
398+
}
399+
375400
err.buffer(&mut self.errors_buffer);
376401
}
377402

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0502]: cannot borrow `buckets` as immutable because it is also borrowed as mutable
2+
--> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70
3+
|
4+
LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22;
5+
| -----------------------------------------------------------------^^^^^^^----------
6+
| | |
7+
| | immutable borrow occurs here
8+
| mutable borrow occurs here
9+
| borrow later used here
10+
|
11+
note: consider extracting this into a `let`-binding
12+
--> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70
13+
|
14+
LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22;
15+
| ^^^^^^^^^^^^^^^
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0502`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Sweep {
12+
fn sweep(&self) -> usize;
13+
}
14+
15+
trait SliceWrapper<T> {
16+
fn slice(&self) -> &[T];
17+
}
18+
19+
trait SliceWrapperMut<T> {
20+
fn slice_mut(&mut self) -> &mut [T];
21+
}
22+
23+
fn foo<B: SliceWrapper<u32> + SliceWrapperMut<u32> + Sweep>(mut buckets: B) {
24+
let key = 0u32;
25+
buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22;
26+
//~^ ERROR cannot borrow `buckets` as immutable
27+
}
28+
29+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0502]: cannot borrow `buckets` as immutable because it is also borrowed as mutable
2+
--> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70
3+
|
4+
LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22;
5+
| ------- ^^^^^^^ - mutable borrow ends here
6+
| | |
7+
| mutable borrow occurs here immutable borrow occurs here
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0502`.

0 commit comments

Comments
 (0)