Skip to content

Commit

Permalink
Unrolled build for rust-lang#115726
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#115726 - compiler-errors:better-error-ref, r=estebank

For a single impl candidate, try to unify it with error trait ref

This allows us to point out an exact type mismatch when there's only one applicable impl.

cc `@asquared31415`
r? `@estebank`
  • Loading branch information
rust-timer authored Oct 3, 2023
2 parents 4f75af9 + 0785167 commit c020467
Show file tree
Hide file tree
Showing 22 changed files with 157 additions and 34 deletions.
91 changes: 88 additions & 3 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore-tidy-filelength :(

mod ambiguity;
pub mod on_unimplemented;
pub mod suggestions;
Expand Down Expand Up @@ -67,6 +69,7 @@ pub enum CandidateSimilarity {
pub struct ImplCandidate<'tcx> {
pub trait_ref: ty::TraitRef<'tcx>,
pub similarity: CandidateSimilarity,
impl_def_id: DefId,
}

enum GetSafeTransmuteErrorAndReason {
Expand Down Expand Up @@ -1331,6 +1334,7 @@ trait InferCtxtPrivExt<'tcx> {
body_def_id: LocalDefId,
err: &mut Diagnostic,
other: bool,
param_env: ty::ParamEnv<'tcx>,
) -> bool;

fn report_similar_impl_candidates_for_root_obligation(
Expand Down Expand Up @@ -1918,8 +1922,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {

let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();

self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
|similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
)
})
.collect();
if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
Expand All @@ -1938,7 +1943,82 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
body_def_id: LocalDefId,
err: &mut Diagnostic,
other: bool,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
// If we have a single implementation, try to unify it with the trait ref
// that failed. This should uncover a better hint for what *is* implemented.
if let [single] = &impl_candidates {
if self.probe(|_| {
let ocx = ObligationCtxt::new(self);
let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
let impl_trait_ref = ocx.normalize(
&ObligationCause::dummy(),
param_env,
ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
);

ocx.register_obligations(
self.tcx
.predicates_of(single.impl_def_id)
.instantiate(self.tcx, impl_args)
.into_iter()
.map(|(clause, _)| {
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
}),
);
if !ocx.select_where_possible().is_empty() {
return false;
}

let mut terrs = vec![];
for (obligation_arg, impl_arg) in
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
{
if let Err(terr) =
ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
{
terrs.push(terr);
}
if !ocx.select_where_possible().is_empty() {
return false;
}
}

// Literally nothing unified, just give up.
if terrs.len() == impl_trait_ref.args.len() {
return false;
}

let cand =
self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
tcx: self.tcx,
ty_op: |ty| ty,
lt_op: |lt| lt,
ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
});
err.highlighted_help(vec![
(format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
("is".to_string(), Style::Highlight),
(" implemented for `".to_string(), Style::NoStyle),
(cand.self_ty().to_string(), Style::Highlight),
("`".to_string(), Style::NoStyle),
]);

if let [TypeError::Sorts(exp_found)] = &terrs[..] {
let exp_found = self.resolve_vars_if_possible(*exp_found);
err.help(format!(
"for that trait implementation, expected `{}`, found `{}`",
exp_found.expected, exp_found.found
));
}

true
}) {
return true;
}
}

let other = if other { "other " } else { "" };
let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
if candidates.is_empty() {
Expand Down Expand Up @@ -2062,9 +2142,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
})
.collect();
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
let mut impl_candidates: Vec<_> =
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
impl_candidates.dedup();

report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err)
report(impl_candidates, err)
}

fn report_similar_impl_candidates_for_root_obligation(
Expand Down Expand Up @@ -2108,6 +2190,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
body_def_id,
err,
true,
obligation.param_env,
);
}
}
Expand Down Expand Up @@ -2316,6 +2399,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.cause.body_id,
&mut err,
false,
obligation.param_env,
);
}
}
Expand Down Expand Up @@ -3051,6 +3135,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
body_def_id,
err,
true,
obligation.param_env,
) {
self.report_similar_impl_candidates_for_root_obligation(
&obligation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
LL | let _ = A;
| ^ the trait `Bar<_>` is not implemented for `A<_>`
|
= help: the trait `Bar<N>` is implemented for `A<7>`
= help: the trait `Bar<_>` is implemented for `A<7>`
note: required by a bound in `A`
--> $DIR/unused-substs-1.rs:9:11
|
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/generic-const-items/unsatisfied-bounds.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ LL | let () = K::<()>;
| ^^ the trait `From<()>` is not implemented for `Infallible`
|
= help: the trait `From<!>` is implemented for `Infallible`
= help: for that trait implementation, expected `!`, found `()`
note: required by a bound in `K`
--> $DIR/unsatisfied-bounds.rs:12:17
|
Expand Down Expand Up @@ -48,6 +49,7 @@ LL | let _ = <() as Trait<&'static str>>::B::<()>;
| ^^ the trait `From<()>` is not implemented for `Infallible`
|
= help: the trait `From<!>` is implemented for `Infallible`
= help: for that trait implementation, expected `!`, found `()`
note: required by a bound in `Trait::B`
--> $DIR/unsatisfied-bounds.rs:21:21
|
Expand Down
5 changes: 3 additions & 2 deletions tests/ui/impl-trait/issues/issue-62742.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
LL | WrongImpl::foo(0i32);
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
= help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:26:35
|
Expand Down Expand Up @@ -42,7 +42,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
LL | WrongImpl::<()>::foo(0i32);
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
= help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
= help: for that trait implementation, expected `[()]`, found `()`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:26:35
|
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/indexing/index-help.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ LL | x[0i32];
| ^^^^ 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`
= help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `i32`
= note: required for `Vec<{integer}>` to implement `Index<i32>`

error: aborting due to previous error
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/indexing/indexing-requires-a-uint.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ LL | [0][0u8];
| ^^^ 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`
= help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `u8`
= note: required for `[{integer}]` to implement `Index<u8>`

error[E0308]: mismatched types
Expand Down
24 changes: 16 additions & 8 deletions tests/ui/integral-indexing.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ LL | v[3u8];
| ^^^ 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`
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `u8`
= note: required for `Vec<isize>` to implement `Index<u8>`

error[E0277]: the type `[isize]` cannot be indexed by `i8`
Expand All @@ -15,7 +16,8 @@ LL | v[3i8];
| ^^^ 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`
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `i8`
= note: required for `Vec<isize>` to implement `Index<i8>`

error[E0277]: the type `[isize]` cannot be indexed by `u32`
Expand All @@ -25,7 +27,8 @@ LL | v[3u32];
| ^^^^ 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`
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `u32`
= note: required for `Vec<isize>` to implement `Index<u32>`

error[E0277]: the type `[isize]` cannot be indexed by `i32`
Expand All @@ -35,7 +38,8 @@ LL | v[3i32];
| ^^^^ 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`
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `i32`
= note: required for `Vec<isize>` to implement `Index<i32>`

error[E0277]: the type `[u8]` cannot be indexed by `u8`
Expand All @@ -45,7 +49,8 @@ LL | s.as_bytes()[3u8];
| ^^^ 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`
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `u8`
= note: required for `[u8]` to implement `Index<u8>`

error[E0277]: the type `[u8]` cannot be indexed by `i8`
Expand All @@ -55,7 +60,8 @@ LL | s.as_bytes()[3i8];
| ^^^ 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`
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `i8`
= note: required for `[u8]` to implement `Index<i8>`

error[E0277]: the type `[u8]` cannot be indexed by `u32`
Expand All @@ -65,7 +71,8 @@ LL | s.as_bytes()[3u32];
| ^^^^ 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`
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `u32`
= note: required for `[u8]` to implement `Index<u32>`

error[E0277]: the type `[u8]` cannot be indexed by `i32`
Expand All @@ -75,7 +82,8 @@ LL | s.as_bytes()[3i32];
| ^^^^ 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`
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
= help: for that trait implementation, expected `usize`, found `i32`
= note: required for `[u8]` to implement `Index<i32>`

error: aborting due to 8 previous errors
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/issues/issue-34334.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
| ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
|
= help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
= help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
= help: for that trait implementation, expected `(u32, _, _)`, found `()`
note: the method call chain might not have had the expected associated types
--> $DIR/issue-34334.rs:5:43
|
Expand Down
1 change: 1 addition & 0 deletions tests/ui/issues/issue-45801.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ LL | req.get_ref::<Params>();
| ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params`
|
= help: the trait `Plugin<Foo>` is implemented for `Params`
= help: for that trait implementation, expected `Foo`, found `i32`

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ LL | let x2: Vec<f64> = x1.into_iter().collect();
| ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
|
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
= help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
= help: for that trait implementation, expected `f64`, found `&f64`
note: the method call chain might not have had the expected associated types
--> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
|
Expand All @@ -25,7 +26,8 @@ LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
| required by a bound introduced by this call
|
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
= help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
= help: for that trait implementation, expected `f64`, found `&f64`
note: the method call chain might not have had the expected associated types
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
|
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/iterators/invalid-iterator-chain.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ LL | i.collect()
| ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
|
= help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
= help: the trait `FromIterator<X>` is implemented for `Vec<X>`
= help: for that trait implementation, expected `X`, found `&X`
note: the method call chain might not have had the expected associated types
--> $DIR/invalid-iterator-chain.rs:4:26
|
Expand Down Expand Up @@ -159,7 +160,8 @@ LL | let g: Vec<i32> = f.collect();
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
|
= help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
= help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
= help: for that trait implementation, expected `i32`, found `()`
note: the method call chain might not have had the expected associated types
--> $DIR/invalid-iterator-chain.rs:44:15
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ LL | <E as From<_>>::from(never);
| ^ the trait `From<()>` is not implemented for `E`
|
= help: the trait `From<!>` is implemented for `E`
= help: for that trait implementation, expected `!`, found `()`

error: aborting due to previous error

Expand Down
3 changes: 2 additions & 1 deletion tests/ui/on-unimplemented/impl-substs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ LL | Foo::<usize>::foo((1i32, 1i32, 1i32));
| required by a bound introduced by this call
|
= help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
= help: the trait `Foo<A>` is implemented for `(A, B, C)`
= help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
= help: for that trait implementation, expected `i32`, found `usize`

error: aborting due to previous error

Expand Down
3 changes: 3 additions & 0 deletions tests/ui/on-unimplemented/on-impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
= help: the trait `Index<usize>` is implemented for `[i32]`
= help: for that trait implementation, expected `usize`, found `u32`

error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
--> $DIR/on-impl.rs:22:5
Expand All @@ -17,6 +18,7 @@ LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
= help: the trait `Index<usize>` is implemented for `[i32]`
= help: for that trait implementation, expected `usize`, found `u32`

error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
--> $DIR/on-impl.rs:22:5
Expand All @@ -26,6 +28,7 @@ LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
= help: the trait `Index<usize>` is implemented for `[i32]`
= help: for that trait implementation, expected `usize`, found `u32`

error: aborting due to 3 previous errors

Expand Down
Loading

0 comments on commit c020467

Please sign in to comment.