summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics/move_errors.rs')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs100
1 files changed, 64 insertions, 36 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 5a47f4567..6db3c858a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -4,7 +4,7 @@ use rustc_middle::ty;
use rustc_mir_dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
use crate::prefixes::PrefixSet;
@@ -148,7 +148,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
match_span: Span,
statement_span: Span,
) {
- debug!("append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span);
+ debug!(?match_place, ?match_span, "append_binding_error");
let from_simple_let = match_place.is_none();
let match_place = match_place.unwrap_or(move_from);
@@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
&& match_span == *span
{
- debug!("appending local({:?}) to list", bind_to);
+ debug!("appending local({bind_to:?}) to list");
if !binds_to.is_empty() {
binds_to.push(bind_to);
}
@@ -198,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} = ge
{
if match_span == *span && mpi == *other_mpi {
- debug!("appending local({:?}) to list", bind_to);
+ debug!("appending local({bind_to:?}) to list");
binds_to.push(bind_to);
return;
}
@@ -410,15 +410,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) {
match error {
GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
- if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
- err.span_suggestion(
- span,
- "consider borrowing here",
- format!("&{snippet}"),
- Applicability::Unspecified,
- );
- }
-
+ self.add_borrow_suggestions(err, span);
if binds_to.is_empty() {
let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
let place_desc = match self.describe_place(move_from.as_ref()) {
@@ -461,39 +453,75 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
+ fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) {
+ match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+ Ok(snippet) if snippet.starts_with('*') => {
+ err.span_suggestion_verbose(
+ span.with_hi(span.lo() + BytePos(1)),
+ "consider removing the dereference here",
+ String::new(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ err.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ "consider borrowing here",
+ "&".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+
fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) {
- let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+ let mut suggestions: Vec<(Span, String, String)> = Vec::new();
for local in binds_to {
let bind_to = &self.body.local_decls[*local];
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { pat_span, .. },
)))) = bind_to.local_info
{
- if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+ let Ok(pat_snippet) =
+ self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+ let Some(stripped) = pat_snippet.strip_prefix('&') else {
+ suggestions.push((
+ bind_to.source_info.span.shrink_to_lo(),
+ "consider borrowing the pattern binding".to_string(),
+ "ref ".to_string(),
+ ));
+ continue;
+ };
+ let inner_pat_snippet = stripped.trim_start();
+ let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut")
+ && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
{
- if let Some(stripped) = pat_snippet.strip_prefix('&') {
- let pat_snippet = stripped.trim_start();
- let (suggestion, to_remove) = if pat_snippet.starts_with("mut")
- && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
- {
- (pat_snippet["mut".len()..].trim_start(), "&mut")
- } else {
- (pat_snippet, "&")
- };
- suggestions.push((pat_span, to_remove, suggestion.to_owned()));
- }
- }
+ let inner_pat_snippet = inner_pat_snippet["mut".len()..].trim_start();
+ let pat_span = pat_span.with_hi(
+ pat_span.lo()
+ + BytePos((pat_snippet.len() - inner_pat_snippet.len()) as u32),
+ );
+ (pat_span, String::new(), "mutable borrow")
+ } else {
+ let pat_span = pat_span.with_hi(
+ pat_span.lo()
+ + BytePos(
+ (pat_snippet.len() - inner_pat_snippet.trim_start().len()) as u32,
+ ),
+ );
+ (pat_span, String::new(), "borrow")
+ };
+ suggestions.push((
+ pat_span,
+ format!("consider removing the {to_remove}"),
+ suggestion.to_string(),
+ ));
}
}
suggestions.sort_unstable_by_key(|&(span, _, _)| span);
suggestions.dedup_by_key(|&mut (span, _, _)| span);
- for (span, to_remove, suggestion) in suggestions {
- err.span_suggestion(
- span,
- &format!("consider removing the `{to_remove}`"),
- suggestion,
- Applicability::MachineApplicable,
- );
+ for (span, msg, suggestion) in suggestions {
+ err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable);
}
}
@@ -521,8 +549,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if binds_to.len() > 1 {
err.note(
- "move occurs because these variables have types that \
- don't implement the `Copy` trait",
+ "move occurs because these variables have types that don't implement the `Copy` \
+ trait",
);
}
}