Rollup merge of #105476 - estebank:moves-n-borrows, r=compiler-errors
Change pattern borrowing suggestions to be verbose and remove invalid suggestion Synthesize a more accurate span and use verbose suggestion output to make the message clearer. Do not suggest borrowing binding in pattern in let else. Fix #104838.
This commit is contained in:
commit
dcdbbd0471
73 changed files with 1842 additions and 816 deletions
|
|
@ -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",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
remainder_span,
|
||||
pattern,
|
||||
None,
|
||||
Some((None, initializer_span)),
|
||||
Some((Some(&destination), initializer_span)),
|
||||
);
|
||||
this.visit_primary_bindings(
|
||||
pattern,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue