Rollup merge of #116990 - estebank:issue-68445, r=cjgillot

Mention `into_iter` on borrow errors suggestions when appropriate

If we encounter a borrow error on `vec![1, 2, 3].iter()`, suggest `into_iter`.

Fix #68445.
This commit is contained in:
Matthias Krüger 2023-10-21 10:08:18 +02:00 committed by GitHub
commit dd66bc86be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 0 deletions

View File

@ -2263,6 +2263,7 @@ struct NestedStatementVisitor<'tcx> {
current: usize,
found: usize,
prop_expr: Option<&'tcx hir::Expr<'tcx>>,
call: Option<&'tcx hir::Expr<'tcx>>,
}
impl<'tcx> Visitor<'tcx> for NestedStatementVisitor<'tcx> {
@ -2272,6 +2273,11 @@ fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
self.current -= 1;
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::MethodCall(_, rcvr, _, _) = expr.kind {
if self.span == rcvr.span.source_callsite() {
self.call = Some(expr);
}
}
if self.span == expr.span.source_callsite() {
self.found = self.current;
if self.prop_expr.is_none() {
@ -2295,6 +2301,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
current: 0,
found: 0,
prop_expr: None,
call: None,
};
visitor.visit_stmt(stmt);
@ -2316,6 +2323,21 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
&& let Some(p) = sm.span_to_margin(stmt.span)
&& let Ok(s) = sm.span_to_snippet(proper_span)
{
if let Some(call) = visitor.call
&& let hir::ExprKind::MethodCall(path, _, [], _) = call.kind
&& path.ident.name == sym::iter
&& let Some(ty) = expr_ty
{
err.span_suggestion_verbose(
path.ident.span,
format!(
"consider consuming the `{ty}` when turning it into an \
`Iterator`",
),
"into_iter".to_string(),
Applicability::MaybeIncorrect,
);
}
if !is_format_arguments_item {
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
err.multipart_suggestion_verbose(

View File

@ -10,6 +10,10 @@ LL | x.use_mut();
| - borrow later used here
|
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider consuming the `Vec<i32>` when turning it into an `Iterator`
|
LL | let mut x = vec![1].into_iter();
| ~~~~~~~~~
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = vec![1];