Factor out suggest_ref_mut; use it in rustc_borrowck

Also teach rustc_borrowck not to show useless help messages like
"use a mutable reference instead: `x`".
This commit is contained in:
ashtneoi 2018-07-12 15:39:36 -07:00
parent 323df7b504
commit 531a68cea7
5 changed files with 27 additions and 39 deletions

View File

@ -39,6 +39,7 @@ use rustc::middle::free_region::RegionRelations;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::query::Providers;
use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
use rustc_mir::util::suggest_ref_mut;
use rustc::util::nodemap::FxHashSet;
use std::cell::RefCell;
@ -1206,21 +1207,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
self.note_immutable_local(db, error_node_id, node_id)
}
Some(ImmutabilityBlame::LocalDeref(node_id)) => {
let let_span = self.tcx.hir.span(node_id);
match self.local_binding_mode(node_id) {
ty::BindByReference(..) => {
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
let replace_str = if snippet.starts_with("ref ") {
snippet.replacen("ref ", "ref mut ", 1)
} else {
snippet
};
let let_span = self.tcx.hir.span(node_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
if let Some((let_span, replace_str)) = suggestion {
db.span_suggestion(
let_span,
"use a mutable reference instead",
replace_str,
);
};
}
}
ty::BindByValue(..) => {
if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) {

View File

@ -29,8 +29,6 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::small_vec::SmallVec;
use core::unicode::property::Pattern_White_Space;
use std::rc::Rc;
use syntax_pos::Span;
@ -46,6 +44,7 @@ use dataflow::{EverInitializedPlaces, MovingOutStatements};
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
use util::borrowck_errors::{BorrowckErrors, Origin};
use util::collect_writes::FindAssignments;
use util::suggest_ref_mut;
use self::borrow_set::{BorrowData, BorrowSet};
use self::flows::Flows;
@ -1861,7 +1860,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByReference(_),
..
})) => suggest_ref_mut(self.tcx, local_decl),
})) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
ClearCrossCrate::Clear => bug!("saw cleared local state"),
};
@ -1957,22 +1956,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
assert_eq!(ty_mut.mutbl, hir::MutImmutable);
(highlight_span, format!("&mut {}", ty_mut.ty))
}
fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
local_decl: &mir::LocalDecl<'tcx>,
) -> Option<(Span, String)> {
let hi_span = local_decl.source_info.span;
let hi_src = tcx.sess.codemap().span_to_snippet(hi_span).unwrap();
if hi_src.starts_with("ref")
&& hi_src["ref".len()..].starts_with(Pattern_White_Space)
{
let suggestion = format!("ref mut{}", &hi_src["ref".len()..]);
Some((hi_span, suggestion))
} else {
None
}
}
}
/// Adds the place into the used mutable variables set

View File

@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::unicode::property::Pattern_White_Space;
use rustc::ty;
use syntax_pos::Span;
pub mod borrowck_errors;
pub mod elaborate_drops;
pub mod def_use;
@ -23,3 +27,19 @@ pub use self::alignment::is_disaligned;
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
pub use self::graphviz::{write_mir_graphviz};
pub use self::graphviz::write_node_label as write_graphviz_node_label;
/// If possible, suggest replacing `ref` with `ref mut`.
pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>,
pattern_span: Span,
) -> Option<(Span, String)> {
let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap();
if hi_src.starts_with("ref")
&& hi_src["ref".len()..].starts_with(Pattern_White_Space)
{
let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
Some((pattern_span, replacement))
} else {
None
}
}

View File

@ -1,24 +1,18 @@
error[E0594]: cannot assign to immutable borrowed content `*x`
--> $DIR/enum.rs:19:5
|
LL | let Wrap(x) = &Wrap(3);
| - help: use a mutable reference instead: `x`
LL | *x += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable
error[E0594]: cannot assign to immutable borrowed content `*x`
--> $DIR/enum.rs:23:9
|
LL | if let Some(x) = &Some(3) {
| - help: use a mutable reference instead: `x`
LL | *x += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable
error[E0594]: cannot assign to immutable borrowed content `*x`
--> $DIR/enum.rs:29:9
|
LL | while let Some(x) = &Some(3) {
| - help: use a mutable reference instead: `x`
LL | *x += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable

View File

@ -1,24 +1,18 @@
error[E0594]: cannot assign to immutable borrowed content `*n`
--> $DIR/explicit-mut.rs:17:13
|
LL | Some(n) => {
| - help: use a mutable reference instead: `n`
LL | *n += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable
error[E0594]: cannot assign to immutable borrowed content `*n`
--> $DIR/explicit-mut.rs:25:13
|
LL | Some(n) => {
| - help: use a mutable reference instead: `n`
LL | *n += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable
error[E0594]: cannot assign to immutable borrowed content `*n`
--> $DIR/explicit-mut.rs:33:13
|
LL | Some(n) => {
| - help: use a mutable reference instead: `n`
LL | *n += 1; //~ ERROR cannot assign to immutable
| ^^^^^^^ cannot borrow as mutable