Rollup merge of #81466 - sasurau4:fix/enhance-sugget-mut-method-for-loop, r=oli-obk
Add suggest mut method for loop Part of #49839 This PR focus on [the comment case](https://github.com/rust-lang/rust/issues/49839#issuecomment-761930746)
This commit is contained in:
commit
3f09418cbe
@ -376,15 +376,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
|
||||
match opt_desugaring_kind {
|
||||
// on for loops, RHS points to the iterator part
|
||||
Some(DesugaringKind::ForLoop(_)) => Some((
|
||||
false,
|
||||
opt_assignment_rhs_span.unwrap(),
|
||||
format!(
|
||||
"this iterator yields `{SIGIL}` {DESC}s",
|
||||
SIGIL = pointer_sigil,
|
||||
DESC = pointer_desc
|
||||
),
|
||||
)),
|
||||
Some(DesugaringKind::ForLoop(_)) => {
|
||||
self.suggest_similar_mut_method_for_for_loop(&mut err);
|
||||
Some((
|
||||
false,
|
||||
opt_assignment_rhs_span.unwrap(),
|
||||
format!(
|
||||
"this iterator yields `{SIGIL}` {DESC}s",
|
||||
SIGIL = pointer_sigil,
|
||||
DESC = pointer_desc
|
||||
),
|
||||
))
|
||||
}
|
||||
// don't create labels for compiler-generated spans
|
||||
Some(_) => None,
|
||||
None => {
|
||||
@ -537,6 +540,79 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
// Attempt to search similar mutable assosiated items for suggestion.
|
||||
// In the future, attempt in all path but initially for RHS of for_loop
|
||||
fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||
let hir = self.infcx.tcx.hir();
|
||||
let node = hir.item(self.mir_hir_id());
|
||||
use hir::{
|
||||
Expr,
|
||||
ExprKind::{Block, Call, DropTemps, Match, MethodCall},
|
||||
};
|
||||
if let hir::ItemKind::Fn(_, _, body_id) = node.kind {
|
||||
if let Block(
|
||||
hir::Block {
|
||||
expr:
|
||||
Some(Expr {
|
||||
kind:
|
||||
DropTemps(Expr {
|
||||
kind:
|
||||
Match(
|
||||
Expr {
|
||||
kind:
|
||||
Call(
|
||||
_,
|
||||
[Expr {
|
||||
kind: MethodCall(path_segment, ..),
|
||||
hir_id,
|
||||
..
|
||||
}, ..],
|
||||
),
|
||||
..
|
||||
},
|
||||
..,
|
||||
),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}),
|
||||
..
|
||||
},
|
||||
_,
|
||||
) = hir.body(body_id).value.kind
|
||||
{
|
||||
let opt_suggestions = path_segment
|
||||
.hir_id
|
||||
.map(|path_hir_id| self.infcx.tcx.typeck(path_hir_id.owner))
|
||||
.and_then(|typeck| typeck.type_dependent_def_id(*hir_id))
|
||||
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
|
||||
.map(|def_id| self.infcx.tcx.associated_items(def_id))
|
||||
.map(|assoc_items| {
|
||||
assoc_items
|
||||
.in_definition_order()
|
||||
.map(|assoc_item_def| assoc_item_def.ident)
|
||||
.filter(|&ident| {
|
||||
let original_method_ident = path_segment.ident;
|
||||
original_method_ident != ident
|
||||
&& ident
|
||||
.as_str()
|
||||
.starts_with(&original_method_ident.name.to_string())
|
||||
})
|
||||
.map(|ident| format!("{}()", ident))
|
||||
});
|
||||
|
||||
if let Some(suggestions) = opt_suggestions {
|
||||
err.span_suggestions(
|
||||
path_segment.ident.span,
|
||||
&format!("use mutable method"),
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
|
||||
fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
|
||||
err.span_label(sp, format!("cannot {}", act));
|
||||
|
17
src/test/ui/suggestions/suggest-mut-method-for-loop.rs
Normal file
17
src/test/ui/suggestions/suggest-mut-method-for-loop.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use std::collections::HashMap;
|
||||
struct X(usize);
|
||||
struct Y {
|
||||
v: u32
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut buzz = HashMap::new();
|
||||
buzz.insert("a", Y { v: 0 });
|
||||
|
||||
for mut t in buzz.values() {
|
||||
//~^ HELP
|
||||
//~| SUGGESTION values_mut()
|
||||
t.v += 1;
|
||||
//~^ ERROR cannot assign
|
||||
}
|
||||
}
|
15
src/test/ui/suggestions/suggest-mut-method-for-loop.stderr
Normal file
15
src/test/ui/suggestions/suggest-mut-method-for-loop.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0594]: cannot assign to `t.v` which is behind a `&` reference
|
||||
--> $DIR/suggest-mut-method-for-loop.rs:14:9
|
||||
|
|
||||
LL | for mut t in buzz.values() {
|
||||
| -------------
|
||||
| | |
|
||||
| | help: use mutable method: `values_mut()`
|
||||
| this iterator yields `&` references
|
||||
...
|
||||
LL | t.v += 1;
|
||||
| ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0594`.
|
Loading…
Reference in New Issue
Block a user