Skip to content

Commit d3c4dbd

Browse files
committed
Add suggest mu method for loop
1 parent 9e5d58f commit d3c4dbd

File tree

1 file changed

+85
-9
lines changed

1 file changed

+85
-9
lines changed

compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs

+85-9
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
376376
opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
377377
match opt_desugaring_kind {
378378
// on for loops, RHS points to the iterator part
379-
Some(DesugaringKind::ForLoop(_)) => Some((
380-
false,
381-
opt_assignment_rhs_span.unwrap(),
382-
format!(
383-
"this iterator yields `{SIGIL}` {DESC}s",
384-
SIGIL = pointer_sigil,
385-
DESC = pointer_desc
386-
),
387-
)),
379+
Some(DesugaringKind::ForLoop(_)) => {
380+
self.suggest_similar_mut_method_for_for_loop(&mut err);
381+
Some((
382+
false,
383+
opt_assignment_rhs_span.unwrap(),
384+
format!(
385+
"this iterator yields `{SIGIL}` {DESC}s",
386+
SIGIL = pointer_sigil,
387+
DESC = pointer_desc
388+
),
389+
))
390+
}
388391
// don't create labels for compiler-generated spans
389392
Some(_) => None,
390393
None => {
@@ -537,6 +540,79 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
537540
);
538541
}
539542

543+
// Attempt to search similar mutable assosiated items for suggestion.
544+
// In the future, attempt in all path but initially for RHS of for_loop
545+
fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>) {
546+
let hir = self.infcx.tcx.hir();
547+
let node = hir.item(self.mir_hir_id());
548+
use hir::{
549+
Expr,
550+
ExprKind::{Block, Call, DropTemps, Match, MethodCall},
551+
};
552+
if let hir::ItemKind::Fn(_, _, body_id) = node.kind {
553+
if let Block(
554+
hir::Block {
555+
expr:
556+
Some(Expr {
557+
kind:
558+
DropTemps(Expr {
559+
kind:
560+
Match(
561+
Expr {
562+
kind:
563+
Call(
564+
_,
565+
[Expr {
566+
kind: MethodCall(path_segment, ..),
567+
hir_id,
568+
..
569+
}, ..],
570+
),
571+
..
572+
},
573+
..,
574+
),
575+
..
576+
}),
577+
..
578+
}),
579+
..
580+
},
581+
_,
582+
) = hir.body(body_id).value.kind
583+
{
584+
let opt_suggestions = path_segment
585+
.hir_id
586+
.map(|path_hir_id| self.infcx.tcx.typeck(path_hir_id.owner))
587+
.and_then(|typeck| typeck.type_dependent_def_id(*hir_id))
588+
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
589+
.map(|def_id| self.infcx.tcx.associated_items(def_id))
590+
.map(|assoc_items| {
591+
assoc_items
592+
.in_definition_order()
593+
.map(|assoc_item_def| assoc_item_def.ident)
594+
.filter(|&ident| {
595+
let original_method_ident = path_segment.ident;
596+
original_method_ident != ident
597+
&& ident
598+
.as_str()
599+
.starts_with(&original_method_ident.name.to_string())
600+
})
601+
.map(|ident| format!("{}()", ident))
602+
});
603+
604+
if let Some(suggestions) = opt_suggestions {
605+
err.span_suggestions(
606+
path_segment.ident.span,
607+
&format!("use mutable method"),
608+
suggestions,
609+
Applicability::MaybeIncorrect,
610+
);
611+
}
612+
}
613+
};
614+
}
615+
540616
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
541617
fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
542618
err.span_label(sp, format!("cannot {}", act));

0 commit comments

Comments
 (0)