diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 2ae06375af13c..28baaadb15cc9 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -13,7 +13,7 @@ use rustc::middle::region::ScopeTree; use rustc::mir::VarBindingForm; use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; -use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind}; use rustc::ty; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -21,7 +21,7 @@ use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; use super::borrow_set::BorrowData; -use super::{Context, MirBorrowckCtxt}; +use super::{Context, ContextKind, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; use dataflow::move_paths::MovePathIndex; @@ -372,6 +372,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.explain_why_borrow_contains_point(context, issued_borrow, None, &mut err); + let bb = &self.mir[context.loc.block]; + if let (&TerminatorKind::Call { ref args, .. }, ContextKind::AssignRhs) = + (&bb.terminator().kind, context.kind) + { + let stmt = &bb.statements[context.loc.statement_index]; + let assigned_place = match stmt.kind { + StatementKind::Assign(ref place, _) => place, + _ => unreachable!(), + }; + + for arg in args { + match arg { + Operand::Copy(ref operand) | Operand::Move(ref operand) => { + if assigned_place == operand { + err.span_note( + bb.terminator().source_info.span, + &format!("consider extracting this into a `let`-binding") + ); + } + } + Operand::Constant(..) => {} + } + } + } + err.buffer(&mut self.errors_buffer); } diff --git a/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.nll.stderr b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.nll.stderr new file mode 100644 index 0000000000000..2a79505528848 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.nll.stderr @@ -0,0 +1,19 @@ +error[E0502]: cannot borrow `buckets` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70 + | +LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22; + | -----------------------------------------------------------------^^^^^^^---------- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + | +note: consider extracting this into a `let`-binding + --> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70 + | +LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.rs b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.rs new file mode 100644 index 0000000000000..eff72adbda5b7 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.rs @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Sweep { + fn sweep(&self) -> usize; +} + +trait SliceWrapper { + fn slice(&self) -> &[T]; +} + +trait SliceWrapperMut { + fn slice_mut(&mut self) -> &mut [T]; +} + +fn foo + SliceWrapperMut + Sweep>(mut buckets: B) { + let key = 0u32; + buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22; + //~^ ERROR cannot borrow `buckets` as immutable +} + +fn main() { } diff --git a/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.stderr b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.stderr new file mode 100644 index 0000000000000..80827f041a038 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-suggest-extraction-of-subcomputation.stderr @@ -0,0 +1,11 @@ +error[E0502]: cannot borrow `buckets` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-suggest-extraction-of-subcomputation.rs:25:70 + | +LL | buckets.slice_mut()[(key as usize).wrapping_add(22).wrapping_rem(buckets.sweep())] = 22; + | ------- ^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`.