Skip to content

Commit

Permalink
Rollup merge of #81939 - kper:fixing-81584-allocate-in-iter, r=davidtwco
Browse files Browse the repository at this point in the history
Add suggestion `.collect()` for iterators in iterators

Closes #81584

```
error[E0515]: cannot return value referencing function parameter `y`
 --> main3.rs:4:38
  |
4 | ...                   .map(|y| y.iter().map(|x| x + 1))
  |                                -^^^^^^^^^^^^^^^^^^^^^^
  |                                |
  |                                returns a value referencing data owned by the current function
  |                                `y` is borrowed here
  |                                help: Maybe use `.collect()` to allocate the iterator
```

Added the suggestion: `help: Maybe use `.collect()` to allocate the iterator`
  • Loading branch information
m-ou-se committed Mar 5, 2021
2 parents 6013811 + a3db47a commit 20887b7
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 4 deletions.
33 changes: 29 additions & 4 deletions compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/issues/issue-81584.fixed
Original file line number Diff line number Diff line change
@@ -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<_>>();
}
8 changes: 8 additions & 0 deletions src/test/ui/issues/issue-81584.rs
Original file line number Diff line number Diff line change
@@ -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<_>>();
}
14 changes: 14 additions & 0 deletions src/test/ui/issues/issue-81584.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 2 additions & 0 deletions src/test/ui/static/static-reference-to-fn-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 20887b7

Please sign in to comment.