about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2022-07-24 22:26:44 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2022-07-24 22:26:44 +0900
commit1d4ddab1bf5c523bdf6e3b7e9cff3c3224c6ed04 (patch)
tree325b68e8067b679a961dc965de26528defd8443e
parentb4151a41a0b275dee59ffbbc115e7bfc5be8a8c3 (diff)
downloadrust-1d4ddab1bf5c523bdf6e3b7e9cff3c3224c6ed04.tar.gz
rust-1d4ddab1bf5c523bdf6e3b7e9cff3c3224c6ed04.zip
suggest dereferencing index when trying to use a reference of usize as index
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs27
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs13
-rw-r--r--src/test/ui/index-help.stderr4
-rw-r--r--src/test/ui/indexing-requires-a-uint.stderr4
-rw-r--r--src/test/ui/integral-indexing.stderr32
-rw-r--r--src/test/ui/on-unimplemented/slice-index.stderr8
-rw-r--r--src/test/ui/str/str-idx.stderr8
-rw-r--r--src/test/ui/str/str-mut-idx.stderr8
-rw-r--r--src/test/ui/suggestions/suggest-dereferencing-index.fixed7
-rw-r--r--src/test/ui/suggestions/suggest-dereferencing-index.rs7
-rw-r--r--src/test/ui/suggestions/suggest-dereferencing-index.stderr17
12 files changed, 104 insertions, 32 deletions
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 2f92a77a795..1b7928a10bd 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -534,6 +534,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         }
 
                         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 7ab85e7fa66..c51f3dacd54 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 @@ pub trait InferCtxtExt<'tcx> {
         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) {
@@ -2927,6 +2934,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             );
         }
     }
+
+    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::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(),
+            "consider dereferencing here",
+            '*',
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
 }
 
 /// 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 8e4cd2392e0..4c0a2bd9199 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -2648,6 +2648,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 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| {
+                        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 = idx.span;
+                        }
+                    });
                     element_ty
                 }
                 None => {
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<u8>` for `Vec<isize>`
 
 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<i8>` for `Vec<isize>`
 
 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<u32>` for `Vec<isize>`
 
 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<i32>` for `Vec<isize>`
 
 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<u8>` 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<i8>` 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<u32>` 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<i32>` for `[i32]`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
-  --> $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<i32>`
    = help: the following other types implement trait `SliceIndex<T>`:
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<str>` 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<I: ~const SliceIndex<str>>(&self, i:
    |                                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl 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<str>` is not implemented for `char`
    = note: required because of the requirements on the impl of `Index<char>` 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<str>` 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<I: ~const SliceIndex<str>>(
    |                                              ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl 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<str>` is not implemented for `char`
    = note: required because of the requirements on the impl of `Index<char>` 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..c0bb5044338
--- /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: consider dereferencing here
+   |
+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`.