Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest dereferencing index when trying to use a reference of usize as index #99671

Merged
merged 3 commits into from
Jul 30, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
TaKO8Ki marked this conversation as resolved.
Show resolved Hide resolved
&& 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.
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
TaKO8Ki marked this conversation as resolved.
Show resolved Hide resolved
});
element_ty
}
None => {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/index-help.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/indexing-requires-a-uint.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
32 changes: 16 additions & 16 deletions src/test/ui/integral-indexing.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/on-unimplemented/slice-index.stderr
Original file line number Diff line number Diff line change
@@ -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>`:
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/str/str-idx.stderr
Original file line number Diff line number Diff line change
@@ -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()`
Expand Down Expand Up @@ -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`
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/str/str-mut-idx.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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`
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/suggestions/suggest-dereferencing-index.fixed
Original file line number Diff line number Diff line change
@@ -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`
}
7 changes: 7 additions & 0 deletions src/test/ui/suggestions/suggest-dereferencing-index.rs
Original file line number Diff line number Diff line change
@@ -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`
}
17 changes: 17 additions & 0 deletions src/test/ui/suggestions/suggest-dereferencing-index.stderr
Original file line number Diff line number Diff line change
@@ -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`.