Skip to content

Commit

Permalink
Rollup merge of #99671 - TaKO8Ki:suggest-dereferencing-index, r=compi…
Browse files Browse the repository at this point in the history
…ler-errors

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

fixes #96678
  • Loading branch information
JohnTitor authored Jul 29, 2022
2 parents 955091b + 3ae669d commit 4a44efa
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,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 @@ -2895,6 +2902,27 @@ 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::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.
Expand Down
19 changes: 19 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,9 @@ 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| {
self.point_at_index_if_possible(errors, idx.span)
});
element_ty
}
None => {
Expand Down Expand Up @@ -2691,6 +2694,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn point_at_index_if_possible(
&self,
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
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>,
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: 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`.

0 comments on commit 4a44efa

Please sign in to comment.