From c8ed5c50edfd1b721c0541fa614864179251aaac Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 11 Jul 2024 10:14:07 +0800 Subject: [PATCH] Fix the issue of invalid suggestion for a reference of iterator --- .../src/diagnostics/conflict_errors.rs | 9 +++ .../src/error_reporting/traits/suggestions.rs | 4 +- .../invalid-suggest-deref-issue-127590.rs | 18 ++++++ .../invalid-suggest-deref-issue-127590.stderr | 61 +++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.rs create mode 100644 tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b1e302e5e27d3..8e4b385b29d50 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1284,6 +1284,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if self.in_move_closure(expr) { return false; } + // Try to find predicates on *generic params* that would allow copying `ty` let mut suggestion = if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { @@ -1312,6 +1313,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } } } + + // Don't suggest cloning the result of a `clone` call. + if let hir::ExprKind::MethodCall(segment, _, _, _) = inner_expr.kind + && segment.ident.name == sym::clone + { + return false; + }; + // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863) if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr { // Remove "(*" or "(&" diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 2cf808f962f08..a53cb4eea16e8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -466,7 +466,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr) { // Suggest dereferencing the argument to a function/method call if possible - let mut real_trait_pred = trait_pred; while let Some((parent_code, parent_trait_pred)) = code.parent() { code = parent_code; @@ -553,6 +552,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); if self.predicate_may_hold(&obligation) && self.predicate_must_hold_modulo_regions(&sized_obligation) + // Do not suggest * if it is already a reference, + // will suggest removing the borrow instead in that case. + && !matches!(expr.kind, hir::ExprKind::AddrOf(..)) { let call_node = self.tcx.hir_node(*call_hir_id); let msg = "consider dereferencing here"; diff --git a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.rs b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.rs new file mode 100644 index 0000000000000..a71657316ae60 --- /dev/null +++ b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.rs @@ -0,0 +1,18 @@ +fn main() { + let fields = vec![1]; + let variant = vec![2]; + + // should not suggest `*&variant.iter()` + for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { + //~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator + //~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator + eprintln!("{} {}", src, dest); + } + + // don't suggest add `variant.iter().clone().clone()` + for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { + //~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator + //~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator + eprintln!("{} {}", src, dest); + } +} diff --git a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr new file mode 100644 index 0000000000000..a3ed51ace0880 --- /dev/null +++ b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr @@ -0,0 +1,61 @@ +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:6:54 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { + | -------------- ^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator` + = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` +note: required by a bound in `std::iter::zip` + --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL +help: consider removing the leading `&`-reference + | +LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { +LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter()) { + | + +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:6:24 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip, &std::slice::Iter<'_, {integer}>>: IntoIterator` + = help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>` + = note: required for `Zip, &std::slice::Iter<'_, {integer}>>` to implement `Iterator` + = note: required for `Zip, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` + +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:13:54 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator` + = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` +note: required by a bound in `std::iter::zip` + --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL +help: consider removing the leading `&`-reference + | +LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { +LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter().clone()) { + | + +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:13:24 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip, &std::slice::Iter<'_, {integer}>>: IntoIterator` + = help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>` + = note: required for `Zip, &std::slice::Iter<'_, {integer}>>` to implement `Iterator` + = note: required for `Zip, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`.