diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 25ba520ace2..7ee3fe844b5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -531,6 +531,7 @@ fn report_selection_error( } self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); + self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); let mut suggested = self.suggest_dereferences(&obligation, &mut err, trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); 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 6c8faed0df4..1f72c96406d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -320,6 +320,13 @@ fn suggest_derive( err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ); + + fn suggest_dereferencing_index( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ); } fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { @@ -2895,6 +2902,27 @@ fn suggest_derive( ); } } + + fn suggest_dereferencing_index( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) { + if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code() + && self.tcx.is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id) + && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.substs.type_at(1).kind() + && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind() + && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind() + { + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_lo(), + "dereference this index", + '*', + Applicability::MachineApplicable, + ); + } + } } /// Collect all the returned expressions within the input expression. diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index ba5ef5edc86..65a562060eb 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2648,6 +2648,9 @@ fn check_expr_index( Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); + self.select_obligations_where_possible(false, |errors| { + self.point_at_index_if_possible(errors, idx.span) + }); element_ty } None => { @@ -2691,6 +2694,22 @@ fn check_expr_index( } } + fn point_at_index_if_possible( + &self, + errors: &mut Vec>, + span: Span, + ) { + for error in errors { + match error.obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(predicate) + if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => { + } + _ => continue, + } + error.obligation.cause.span = span; + } + } + fn check_expr_yield( &self, value: &'tcx hir::Expr<'tcx>, diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index 7f51a48111b..b36f4dab829 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -1,8 +1,8 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `i32` - --> $DIR/index-help.rs:3:5 + --> $DIR/index-help.rs:3:7 | LL | x[0i32]; - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr index 0a24855a6a7..fbff20f8dee 100644 --- a/src/test/ui/indexing-requires-a-uint.stderr +++ b/src/test/ui/indexing-requires-a-uint.stderr @@ -1,8 +1,8 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `u8` - --> $DIR/indexing-requires-a-uint.rs:6:5 + --> $DIR/indexing-requires-a-uint.rs:6:9 | LL | [0][0u8]; - | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` = help: the trait `SliceIndex<[T]>` is implemented for `usize` diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr index be3398552dc..3f9094d124e 100644 --- a/src/test/ui/integral-indexing.stderr +++ b/src/test/ui/integral-indexing.stderr @@ -1,78 +1,78 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:6:5 + --> $DIR/integral-indexing.rs:6:7 | LL | v[3u8]; - | ^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:7:5 + --> $DIR/integral-indexing.rs:7:7 | LL | v[3i8]; - | ^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:8:5 + --> $DIR/integral-indexing.rs:8:7 | LL | v[3u32]; - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[isize]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:9:5 + --> $DIR/integral-indexing.rs:9:7 | LL | v[3i32]; - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `Vec` error[E0277]: the type `[u8]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:12:5 + --> $DIR/integral-indexing.rs:12:18 | LL | s.as_bytes()[3u8]; - | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:13:5 + --> $DIR/integral-indexing.rs:13:18 | LL | s.as_bytes()[3i8]; - | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:14:5 + --> $DIR/integral-indexing.rs:14:18 | LL | s.as_bytes()[3u32]; - | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:15:5 + --> $DIR/integral-indexing.rs:15:18 | LL | s.as_bytes()[3i32]; - | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index ae7d2e1d823..72f67a68515 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -1,18 +1,18 @@ error[E0277]: the type `[i32]` cannot be indexed by `i32` - --> $DIR/slice-index.rs:8:5 + --> $DIR/slice-index.rs:8:7 | LL | x[1i32]; - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index` for `[i32]` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` - --> $DIR/slice-index.rs:9:5 + --> $DIR/slice-index.rs:9:7 | LL | x[..1i32]; - | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` = help: the following other types implement trait `SliceIndex`: diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 45450788b9c..9079a18d6a6 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -1,8 +1,8 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-idx.rs:3:17 + --> $DIR/str-idx.rs:3:19 | LL | let _: u8 = s[4]; - | ^^^^ string indices are ranges of `usize` + | ^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` @@ -47,10 +47,10 @@ LL | pub const unsafe fn get_unchecked>(&self, i: | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked` error[E0277]: the type `str` cannot be indexed by `char` - --> $DIR/str-idx.rs:6:17 + --> $DIR/str-idx.rs:6:19 | LL | let _: u8 = s['c']; - | ^^^^^^ string indices are ranges of `usize` + | ^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `char` = note: required because of the requirements on the impl of `Index` for `str` diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 9ae08563027..2d062e56a9b 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -25,10 +25,10 @@ LL | s[1..2] = bot(); = note: the left-hand-side of an assignment must have a statically known size error[E0277]: the type `str` cannot be indexed by `usize` - --> $DIR/str-mut-idx.rs:7:5 + --> $DIR/str-mut-idx.rs:7:7 | LL | s[1usize] = bot(); - | ^^^^^^^^^ string indices are ranges of `usize` + | ^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` = help: the trait `SliceIndex<[T]>` is implemented for `usize` @@ -71,10 +71,10 @@ LL | pub const unsafe fn get_unchecked_mut>( | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked_mut` error[E0277]: the type `str` cannot be indexed by `char` - --> $DIR/str-mut-idx.rs:13:5 + --> $DIR/str-mut-idx.rs:13:7 | LL | s['c']; - | ^^^^^^ string indices are ranges of `usize` + | ^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `char` = note: required because of the requirements on the impl of `Index` for `str` diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.fixed b/src/test/ui/suggestions/suggest-dereferencing-index.fixed new file mode 100644 index 00000000000..dd4ae4eb14c --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][*i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.rs b/src/test/ui/suggestions/suggest-dereferencing-index.rs new file mode 100644 index 00000000000..82ebacc49f2 --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.stderr b/src/test/ui/suggestions/suggest-dereferencing-index.stderr new file mode 100644 index 00000000000..c8b87af7bd8 --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.stderr @@ -0,0 +1,17 @@ +error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` + --> $DIR/suggest-dereferencing-index.rs:6:42 + | +LL | let one_item_please: i32 = [1, 2, 3][i]; + | ^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required because of the requirements on the impl of `Index<&usize>` for `[{integer}]` +help: dereference this index + | +LL | let one_item_please: i32 = [1, 2, 3][*i]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.