Skip to content

Commit 20887b7

Browse files
authored
Rollup merge of #81939 - kper:fixing-81584-allocate-in-iter, r=davidtwco
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`
2 parents 6013811 + a3db47a commit 20887b7

File tree

6 files changed

+62
-4
lines changed

6 files changed

+62
-4
lines changed

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

+29-4
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ use rustc_middle::mir::{
1010
FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
1111
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
1212
};
13-
use rustc_middle::ty::{self, suggest_constraining_type_param, Instance, Ty};
14-
use rustc_span::{source_map::DesugaringKind, symbol::sym, Span};
13+
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable};
14+
use rustc_span::source_map::DesugaringKind;
15+
use rustc_span::symbol::sym;
16+
use rustc_span::Span;
1517

1618
use crate::dataflow::drop_flag_effects;
1719
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
1820
use crate::util::borrowck_errors;
1921

2022
use crate::borrow_check::{
21-
borrow_set::BorrowData, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt,
22-
PrefixSet, WriteKind,
23+
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
24+
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
2325
};
2426

2527
use super::{
@@ -1267,6 +1269,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12671269

12681270
if return_span != borrow_span {
12691271
err.span_label(borrow_span, note);
1272+
1273+
let tcx = self.infcx.tcx;
1274+
let ty_params = ty::List::empty();
1275+
1276+
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
1277+
let return_ty = tcx.erase_regions(return_ty);
1278+
1279+
// to avoid panics
1280+
if !return_ty.has_infer_types() {
1281+
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
1282+
if tcx.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
1283+
{
1284+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
1285+
err.span_suggestion_hidden(
1286+
return_span,
1287+
"use `.collect()` to allocate the iterator",
1288+
format!("{}{}", snippet, ".collect::<Vec<_>>()"),
1289+
Applicability::MaybeIncorrect,
1290+
);
1291+
}
1292+
}
1293+
}
1294+
}
12701295
}
12711296

12721297
Some(err)

library/core/src/iter/traits/iterator.rs

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

src/test/ui/issues/issue-81584.fixed

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

src/test/ui/issues/issue-81584.rs

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

src/test/ui/issues/issue-81584.stderr

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

src/test/ui/static/static-reference-to-fn-2.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ LL | | statefn: &id(state1 as StateMachineFunc)
4040
| | ------------------------------ temporary value created here
4141
LL | | }
4242
| |_____^ returns a value referencing data owned by the current function
43+
|
44+
= help: use `.collect()` to allocate the iterator
4345

4446
error: aborting due to 4 previous errors
4547

0 commit comments

Comments
 (0)