Add suggestion for iterators in iterators

This commit is contained in:
Kevin Per 2021-02-09 17:18:28 +00:00
parent fe1bf8e05c
commit a3db47ab6c
6 changed files with 62 additions and 4 deletions

View File

@ -10,16 +10,18 @@ use rustc_middle::mir::{
FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_param, Instance, Ty};
use rustc_span::{source_map::DesugaringKind, symbol::sym, Span};
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::Span;
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
use crate::util::borrowck_errors;
use crate::borrow_check::{
borrow_set::BorrowData, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt,
PrefixSet, WriteKind,
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
};
use super::{
@ -1267,6 +1269,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if return_span != borrow_span {
err.span_label(borrow_span, note);
let tcx = self.infcx.tcx;
let ty_params = ty::List::empty();
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
let return_ty = tcx.erase_regions(return_ty);
// to avoid panics
if !return_ty.has_infer_types() {
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
if tcx.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
{
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
err.span_suggestion_hidden(
return_span,
"use `.collect()` to allocate the iterator",
format!("{}{}", snippet, ".collect::<Vec<_>>()"),
Applicability::MaybeIncorrect,
);
}
}
}
}
}
Some(err)

View File

@ -93,6 +93,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
message = "`{Self}` is not an iterator"
)]
#[doc(spotlight)]
#[rustc_diagnostic_item = "Iterator"]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait Iterator {
/// The type of the elements being iterated over.

View File

@ -0,0 +1,8 @@
// run-rustfix
fn main() {
let _ = vec![vec![0, 1], vec![2]]
.into_iter()
.map(|y| y.iter().map(|x| x + 1).collect::<Vec<_>>())
//~^ ERROR cannot return value referencing function parameter `y`
.collect::<Vec<_>>();
}

View File

@ -0,0 +1,8 @@
// run-rustfix
fn main() {
let _ = vec![vec![0, 1], vec![2]]
.into_iter()
.map(|y| y.iter().map(|x| x + 1))
//~^ ERROR cannot return value referencing function parameter `y`
.collect::<Vec<_>>();
}

View File

@ -0,0 +1,14 @@
error[E0515]: cannot return value referencing function parameter `y`
--> $DIR/issue-81584.rs:5:22
|
LL | .map(|y| y.iter().map(|x| x + 1))
| -^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `y` is borrowed here
|
= help: use `.collect()` to allocate the iterator
error: aborting due to previous error
For more information about this error, try `rustc --explain E0515`.

View File

@ -40,6 +40,8 @@ LL | | statefn: &id(state1 as StateMachineFunc)
| | ------------------------------ temporary value created here
LL | | }
| |_____^ returns a value referencing data owned by the current function
|
= help: use `.collect()` to allocate the iterator
error: aborting due to 4 previous errors