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 65e589d336500..51527991b073b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5147,6 +5147,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind() && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind() { + // If the index is written as `&i`, suggest removing the borrow instead of + // dereferencing it, i.e. `v[&i]` -> `v[i]` rather than `v[*&i]`. + let span = obligation.cause.span; + if !span.from_expansion() + && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) + && let Some(expr) = { + let mut finder = FindExprBySpan::new(span, self.tcx); + finder.visit_expr(body.value); + finder.result + } + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, borrowed) = + expr.kind + && let Some(amp_span) = borrowed + .span + .find_ancestor_inside_same_ctxt(expr.span) + .map(|borrowed_span| expr.span.until(borrowed_span)) + && self + .tcx + .sess + .source_map() + .span_to_snippet(amp_span) + .is_ok_and(|snippet| snippet.starts_with('&')) + { + err.span_suggestion_verbose( + amp_span, + "remove this reference", + "", + Applicability::MachineApplicable, + ); + return; + } + err.span_suggestion_verbose( obligation.cause.span.shrink_to_lo(), "dereference this index", diff --git a/tests/ui/suggestions/suggest-remove-reference-index.fixed b/tests/ui/suggestions/suggest-remove-reference-index.fixed new file mode 100644 index 0000000000000..646c650de4584 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.fixed @@ -0,0 +1,10 @@ +//@ run-rustfix + +fn main() { + let arr = [false]; + let i = 0usize; + + println!("{}", arr[i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[(i + 0)]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-remove-reference-index.rs b/tests/ui/suggestions/suggest-remove-reference-index.rs new file mode 100644 index 0000000000000..db0a33a89eff3 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.rs @@ -0,0 +1,10 @@ +//@ run-rustfix + +fn main() { + let arr = [false]; + let i = 0usize; + + println!("{}", arr[&i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[&(i + 0)]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[& i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-remove-reference-index.stderr b/tests/ui/suggestions/suggest-remove-reference-index.stderr new file mode 100644 index 0000000000000..4f396fe529508 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.stderr @@ -0,0 +1,66 @@ +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:7:24 + | +LL | println!("{}", arr[&i]); + | ^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[&i]); +LL + println!("{}", arr[i]); + | + +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:8:24 + | +LL | println!("{}", arr[&(i + 0)]); + | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[&(i + 0)]); +LL + println!("{}", arr[(i + 0)]); + | + +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:9:24 + | +LL | println!("{}", arr[& i]); + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[& i]); +LL + println!("{}", arr[i]); + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`.