suggest dereferencing index when trying to use a reference of usize as index

This commit is contained in:
Takayuki Maeda 2022-07-24 22:26:44 +09:00
parent b4151a41a0
commit 1d4ddab1bf
12 changed files with 104 additions and 32 deletions

View file

@ -534,6 +534,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);

View file

@ -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) {
@ -2927,6 +2934,26 @@ 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::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.

View file

@ -2648,6 +2648,19 @@ 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| {
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 => {

View file

@ -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`

View file

@ -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`

View file

@ -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`

View file

@ -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>`:

View file

@ -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`

View file

@ -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`

View file

@ -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`
}

View file

@ -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`
}

View file

@ -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`.