Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ symbols! {
Into,
IntoFuture,
IntoIterator,
IntoIteratorItem,
IoBufRead,
IoLines,
IoRead,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4390,6 +4390,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
path_segment: &hir::PathSegment<'_>,
args: &[hir::Expr<'_>],
prev_ty: Ty<'_>,
err: &mut Diag<'_, G>,
) {
let tcx = self.tcx;
Expand All @@ -4403,6 +4404,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let TypeError::Sorts(expected_found) = diff else {
continue;
};
if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
&& path_segment.ident.name == sym::iter
&& self.can_eq(
param_env,
Ty::new_ref(
tcx,
tcx.lifetimes.re_erased,
expected_found.found,
ty::Mutability::Not,
),
*ty,
)
&& let [] = args
{
// Used `.iter()` when `.into_iter()` was likely meant.
err.span_suggestion_verbose(
path_segment.ident.span,
format!("consider consuming the `{prev_ty}` to construct the `Iterator`"),
"into_iter".to_string(),
Applicability::MachineApplicable,
);
}
if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
&& path_segment.ident.name == sym::into_iter
&& self.can_eq(
param_env,
expected_found.found,
Ty::new_ref(tcx, tcx.lifetimes.re_erased, *ty, ty::Mutability::Not),
)
&& let [] = args
{
// Used `.into_iter()` when `.iter()` was likely meant.
err.span_suggestion_verbose(
path_segment.ident.span,
format!(
"consider not consuming the `{prev_ty}` to construct the `Iterator`"
),
"iter".to_string(),
Applicability::MachineApplicable,
);
}
if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
&& path_segment.ident.name == sym::map
&& self.can_eq(param_env, expected_found.found, *ty)
Expand Down Expand Up @@ -4515,19 +4557,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
expr = rcvr_expr;
let assocs_in_this_method =
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
prev_ty = self.resolve_vars_if_possible(
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
);
self.look_for_iterator_item_mistakes(
&assocs_in_this_method,
typeck_results,
&type_diffs,
param_env,
path_segment,
args,
prev_ty,
err,
);
assocs.push(assocs_in_this_method);
prev_ty = self.resolve_vars_if_possible(
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
);

if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
&& let hir::Path { res: Res::Local(hir_id), .. } = path
Expand Down
1 change: 1 addition & 0 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ pub trait FromIterator<A>: Sized {
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
/// The type of the elements being iterated over.
#[rustc_diagnostic_item = "IntoIteratorItem"]
#[stable(feature = "rust1", since = "1.0.0")]
type Item;

Expand Down
10 changes: 10 additions & 0 deletions tests/ui/iterators/into_iter-when-iter-was-intended.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@ run-rustfix
//@ edition:2021
// Suggest using the right `IntoIterator` method. #68095
fn main() {
let _a = [0, 1, 2].iter().chain([3, 4, 5].iter()); //~ ERROR E0271
let _b = [0, 1, 2].into_iter().chain([3, 4, 5].into_iter()); //~ ERROR E0271
// These don't have appropriate suggestions yet.
// let c = [0, 1, 2].iter().chain([3, 4, 5]);
// let d = [0, 1, 2].iter().chain(vec![3, 4, 5]);
}
10 changes: 10 additions & 0 deletions tests/ui/iterators/into_iter-when-iter-was-intended.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@ run-rustfix
//@ edition:2021
// Suggest using the right `IntoIterator` method. #68095
fn main() {
let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter()); //~ ERROR E0271
let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter()); //~ ERROR E0271
// These don't have appropriate suggestions yet.
// let c = [0, 1, 2].iter().chain([3, 4, 5]);
// let d = [0, 1, 2].iter().chain(vec![3, 4, 5]);
}
48 changes: 48 additions & 0 deletions tests/ui/iterators/into_iter-when-iter-was-intended.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
error[E0271]: type mismatch resolving `<IntoIter<{integer}, 3> as IntoIterator>::Item == &{integer}`
--> $DIR/into_iter-when-iter-was-intended.rs:5:37
|
LL | let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
| ----- ^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
| |
| required by a bound introduced by this call
|
note: the method call chain might not have had the expected associated types
--> $DIR/into_iter-when-iter-was-intended.rs:5:47
|
LL | let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
| --------- ^^^^^^^^^^^ `IntoIterator::Item` is `{integer}` here
| |
| this expression has type `[{integer}; 3]`
note: required by a bound in `std::iter::Iterator::chain`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
help: consider not consuming the `[{integer}; 3]` to construct the `Iterator`
|
LL - let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
LL + let _a = [0, 1, 2].iter().chain([3, 4, 5].iter());
|

error[E0271]: type mismatch resolving `<Iter<'_, {integer}> as IntoIterator>::Item == {integer}`
--> $DIR/into_iter-when-iter-was-intended.rs:6:42
|
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter());
| ----- ^^^^^^^^^^^^^^^^ expected integer, found `&{integer}`
| |
| required by a bound introduced by this call
|
note: the method call chain might not have had the expected associated types
--> $DIR/into_iter-when-iter-was-intended.rs:6:52
|
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter());
| --------- ^^^^^^ `IntoIterator::Item` is `&{integer}` here
| |
| this expression has type `[{integer}; 3]`
note: required by a bound in `std::iter::Iterator::chain`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
help: consider consuming the `&[{integer}]` to construct the `Iterator`
|
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].into_iter());
| +++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
Loading