From 733bdd079a3c09aa3baa47ad65ae134f07b9dbcd Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 1 Sep 2021 20:07:56 -0700 Subject: [PATCH 1/3] fix(rustc): suggest `items` be borrowed in `for i in items[x..]` Fixes #87994 --- .../src/traits/error_reporting/suggestions.rs | 17 +++++++-- src/test/ui/suggestions/slice-issue-87994.rs | 7 ++++ .../ui/suggestions/slice-issue-87994.stderr | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/suggestions/slice-issue-87994.rs create mode 100644 src/test/ui/suggestions/slice-issue-87994.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index db3432b01422f..608add1d91c9f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::{ use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::fmt; @@ -680,7 +680,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { points_at_arg: bool, has_custom_message: bool, ) -> bool { - if !points_at_arg { + let span = obligation.cause.span; + let points_at_for_iter = matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) + ); + + if !points_at_arg && !points_at_for_iter { return false; } @@ -695,7 +701,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap()); - let span = obligation.cause.span; let param_env = obligation.param_env; let trait_ref = trait_ref.skip_binder(); @@ -754,7 +759,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); // This if is to prevent a special edge-case - if !span.from_expansion() { + if matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Root + | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) + ) { // We don't want a borrowing suggestion on the fields in structs, // ``` // struct Foo { diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs new file mode 100644 index 0000000000000..98a936ab2fdd5 --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.rs @@ -0,0 +1,7 @@ +fn main() { + let v = vec![1i32, 2, 3]; + for _ in v[1..] { + //~^ ERROR [i32]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + } +} diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr new file mode 100644 index 0000000000000..0c69bec22109b --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -0,0 +1,37 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ + | | + | expected an implementor of trait `IntoIterator` + | help: consider borrowing here: `&v[1..]` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `[i32]` is not an iterator + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ + | | + | expected an implementor of trait `IntoIterator` + | help: consider borrowing here: `&v[1..]` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From f23003dff12fdb6c3ba09a55b1323cd2692e50d1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 1 Sep 2021 20:39:11 -0700 Subject: [PATCH 2/3] fix(test): update with `&mut` suggestion --- src/test/ui/issues/issue-20605.stderr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index 25a90df45613b..ce3ab6b599864 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -2,9 +2,12 @@ error[E0277]: the size for values of type `dyn Iterator` cann --> $DIR/issue-20605.rs:2:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^ + | | + | expected an implementor of trait `IntoIterator` + | help: consider mutably borrowing here: `&mut *things` | - = help: the trait `Sized` is not implemented for `dyn Iterator` + = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator` note: required by `into_iter` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL From d6ff916c2fe6a47f52fc14e4f6d85e92d07e5e76 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Sep 2021 00:49:43 -0700 Subject: [PATCH 3/3] test: add case for mutating iterator Note that this incorrectly suggests a shared borrow, but at least we know it's happening. --- src/test/ui/suggestions/slice-issue-87994.rs | 9 +++++ .../ui/suggestions/slice-issue-87994.stderr | 36 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs index 98a936ab2fdd5..ecb7f54ea250a 100644 --- a/src/test/ui/suggestions/slice-issue-87994.rs +++ b/src/test/ui/suggestions/slice-issue-87994.rs @@ -4,4 +4,13 @@ fn main() { //~^ ERROR [i32]` is not an iterator [E0277] //~^^ ERROR known at compilation time } + struct K { + n: i32, + } + let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; + for i2 in v2[1..] { + //~^ ERROR [K]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + i2.n = 2; + } } diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr index 0c69bec22109b..018f62e783daf 100644 --- a/src/test/ui/suggestions/slice-issue-87994.stderr +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -32,6 +32,40 @@ note: required by `into_iter` LL | fn into_iter(self) -> Self::IntoIter; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0277]: the size for values of type `[K]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ + | | + | expected an implementor of trait `IntoIterator` + | help: consider borrowing here: `&v2[1..]` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[K]` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `[K]` is not an iterator + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ + | | + | expected an implementor of trait `IntoIterator` + | help: consider borrowing here: `&v2[1..]` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[K]` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`.