Skip to content

Commit 8be12f4

Browse files
For a single impl candidate, try to unify it with error trait ref
1 parent 5333b87 commit 8be12f4

16 files changed

+106
-34
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+75-3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub enum CandidateSimilarity {
6767
pub struct ImplCandidate<'tcx> {
6868
pub trait_ref: ty::TraitRef<'tcx>,
6969
pub similarity: CandidateSimilarity,
70+
impl_def_id: DefId,
7071
}
7172

7273
enum GetSafeTransmuteErrorAndReason {
@@ -1331,6 +1332,7 @@ trait InferCtxtPrivExt<'tcx> {
13311332
body_def_id: LocalDefId,
13321333
err: &mut Diagnostic,
13331334
other: bool,
1335+
param_env: ty::ParamEnv<'tcx>,
13341336
) -> bool;
13351337

13361338
fn report_similar_impl_candidates_for_root_obligation(
@@ -1918,8 +1920,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19181920

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

1921-
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
1922-
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
1923+
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
1924+
|similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
1925+
)
19231926
})
19241927
.collect();
19251928
if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
@@ -1938,7 +1941,71 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19381941
body_def_id: LocalDefId,
19391942
err: &mut Diagnostic,
19401943
other: bool,
1944+
param_env: ty::ParamEnv<'tcx>,
19411945
) -> bool {
1946+
if let [single] = &impl_candidates {
1947+
if self.probe(|_| {
1948+
let ocx = ObligationCtxt::new(self);
1949+
let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
1950+
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
1951+
let impl_trait_ref = ocx.normalize(
1952+
&ObligationCause::dummy(),
1953+
param_env,
1954+
ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
1955+
);
1956+
1957+
ocx.register_obligations(
1958+
self.tcx
1959+
.predicates_of(single.impl_def_id)
1960+
.instantiate(self.tcx, impl_args)
1961+
.into_iter()
1962+
.map(|(clause, _)| {
1963+
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
1964+
}),
1965+
);
1966+
if !ocx.select_where_possible().is_empty() {
1967+
return false;
1968+
}
1969+
1970+
let mut terrs = vec![];
1971+
for (obligation_arg, impl_arg) in
1972+
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
1973+
{
1974+
if let Err(terr) =
1975+
ocx.eq(&ObligationCause::dummy(), param_env, obligation_arg, impl_arg)
1976+
{
1977+
terrs.push(terr);
1978+
}
1979+
if !ocx.select_where_possible().is_empty() {
1980+
return false;
1981+
}
1982+
}
1983+
1984+
// Literally nothing unified, just give up.
1985+
if terrs.len() == impl_trait_ref.args.len() {
1986+
return false;
1987+
}
1988+
1989+
let cand =
1990+
self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
1991+
tcx: self.tcx,
1992+
ty_op: |ty| ty,
1993+
lt_op: |lt| lt,
1994+
ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
1995+
});
1996+
err.highlighted_help(vec![
1997+
(format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
1998+
("is".to_string(), Style::Highlight),
1999+
(" implemented for `".to_string(), Style::NoStyle),
2000+
(cand.self_ty().to_string(), Style::Highlight),
2001+
("`".to_string(), Style::NoStyle),
2002+
]);
2003+
true
2004+
}) {
2005+
return true;
2006+
}
2007+
}
2008+
19422009
let other = if other { "other " } else { "" };
19432010
let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
19442011
if candidates.is_empty() {
@@ -2062,9 +2129,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
20622129
})
20632130
.collect();
20642131
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
2132+
let mut impl_candidates: Vec<_> =
2133+
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
20652134
impl_candidates.dedup();
20662135

2067-
report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err)
2136+
report(impl_candidates, err)
20682137
}
20692138

20702139
fn report_similar_impl_candidates_for_root_obligation(
@@ -2108,6 +2177,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
21082177
body_def_id,
21092178
err,
21102179
true,
2180+
obligation.param_env,
21112181
);
21122182
}
21132183
}
@@ -2316,6 +2386,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23162386
obligation.cause.body_id,
23172387
&mut err,
23182388
false,
2389+
obligation.param_env,
23192390
);
23202391
}
23212392
}
@@ -3051,6 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30513122
body_def_id,
30523123
err,
30533124
true,
3125+
obligation.param_env,
30543126
) {
30553127
self.report_similar_impl_candidates_for_root_obligation(
30563128
&obligation,

tests/ui/const-generics/occurs-check/unused-substs-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
44
LL | let _ = A;
55
| ^ the trait `Bar<_>` is not implemented for `A<_>`
66
|
7-
= help: the trait `Bar<N>` is implemented for `A<7>`
7+
= help: the trait `Bar<_>` is implemented for `A<7>`
88
note: required by a bound in `A`
99
--> $DIR/unused-substs-1.rs:9:11
1010
|

tests/ui/impl-trait/issues/issue-62742.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
44
LL | WrongImpl::foo(0i32);
55
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
66
|
7-
= help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
7+
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
88
note: required by a bound in `SafeImpl`
99
--> $DIR/issue-62742.rs:26:35
1010
|
@@ -42,7 +42,7 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
4242
LL | WrongImpl::<()>::foo(0i32);
4343
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
4444
|
45-
= help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
45+
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
4646
note: required by a bound in `SafeImpl`
4747
--> $DIR/issue-62742.rs:26:35
4848
|

tests/ui/indexing/index-help.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | x[0i32];
55
| ^^^^ slice indices are of type `usize` or ranges of `usize`
66
|
77
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
8-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
8+
= help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
99
= note: required for `Vec<{integer}>` to implement `Index<i32>`
1010

1111
error: aborting due to previous error

tests/ui/indexing/indexing-requires-a-uint.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | [0][0u8];
55
| ^^^ slice indices are of type `usize` or ranges of `usize`
66
|
77
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
8-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
8+
= help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
99
= note: required for `[{integer}]` to implement `Index<u8>`
1010

1111
error[E0308]: mismatched types

tests/ui/integral-indexing.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | v[3u8];
55
| ^^^ slice indices are of type `usize` or ranges of `usize`
66
|
77
= help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
8-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
8+
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
99
= note: required for `Vec<isize>` to implement `Index<u8>`
1010

1111
error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -15,7 +15,7 @@ LL | v[3i8];
1515
| ^^^ slice indices are of type `usize` or ranges of `usize`
1616
|
1717
= help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
18-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
18+
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
1919
= note: required for `Vec<isize>` to implement `Index<i8>`
2020

2121
error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -25,7 +25,7 @@ LL | v[3u32];
2525
| ^^^^ slice indices are of type `usize` or ranges of `usize`
2626
|
2727
= help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
28-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
28+
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
2929
= note: required for `Vec<isize>` to implement `Index<u32>`
3030

3131
error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -35,7 +35,7 @@ LL | v[3i32];
3535
| ^^^^ slice indices are of type `usize` or ranges of `usize`
3636
|
3737
= help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
38-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
38+
= help: the trait `SliceIndex<[isize]>` is implemented for `usize`
3939
= note: required for `Vec<isize>` to implement `Index<i32>`
4040

4141
error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -45,7 +45,7 @@ LL | s.as_bytes()[3u8];
4545
| ^^^ slice indices are of type `usize` or ranges of `usize`
4646
|
4747
= help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
48-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
48+
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
4949
= note: required for `[u8]` to implement `Index<u8>`
5050

5151
error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -55,7 +55,7 @@ LL | s.as_bytes()[3i8];
5555
| ^^^ slice indices are of type `usize` or ranges of `usize`
5656
|
5757
= help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
58-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
58+
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
5959
= note: required for `[u8]` to implement `Index<i8>`
6060

6161
error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -65,7 +65,7 @@ LL | s.as_bytes()[3u32];
6565
| ^^^^ slice indices are of type `usize` or ranges of `usize`
6666
|
6767
= help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
68-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
68+
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
6969
= note: required for `[u8]` to implement `Index<u32>`
7070

7171
error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -75,7 +75,7 @@ LL | s.as_bytes()[3i32];
7575
| ^^^^ slice indices are of type `usize` or ranges of `usize`
7676
|
7777
= help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
78-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
78+
= help: the trait `SliceIndex<[u8]>` is implemented for `usize`
7979
= note: required for `[u8]` to implement `Index<i32>`
8080

8181
error: aborting due to 8 previous errors

tests/ui/issues/issue-34334.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
1919
| ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
2020
|
2121
= help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
22-
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
22+
= help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
2323
note: the method call chain might not have had the expected associated types
2424
--> $DIR/issue-34334.rs:5:43
2525
|

tests/ui/issues/issue-66923-show-error-for-correct-call.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let x2: Vec<f64> = x1.into_iter().collect();
55
| ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
66
|
77
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
8-
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
8+
= help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
99
note: the method call chain might not have had the expected associated types
1010
--> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
1111
|
@@ -25,7 +25,7 @@ LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
2525
| required by a bound introduced by this call
2626
|
2727
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
28-
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
28+
= help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
2929
note: the method call chain might not have had the expected associated types
3030
--> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
3131
|

tests/ui/iterators/invalid-iterator-chain.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | i.collect()
55
| ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
66
|
77
= help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
8-
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
8+
= help: the trait `FromIterator<X>` is implemented for `Vec<X>`
99
note: the method call chain might not have had the expected associated types
1010
--> $DIR/invalid-iterator-chain.rs:4:26
1111
|
@@ -159,7 +159,7 @@ LL | let g: Vec<i32> = f.collect();
159159
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
160160
|
161161
= help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
162-
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
162+
= help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
163163
note: the method call chain might not have had the expected associated types
164164
--> $DIR/invalid-iterator-chain.rs:44:15
165165
|

tests/ui/on-unimplemented/impl-substs.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | Foo::<usize>::foo((1i32, 1i32, 1i32));
77
| required by a bound introduced by this call
88
|
99
= help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
10-
= help: the trait `Foo<A>` is implemented for `(A, B, C)`
10+
= help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
1111

1212
error: aborting due to previous error
1313

tests/ui/on-unimplemented/slice-index.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | x[1i32];
55
| ^^^^ slice indices are of type `usize` or ranges of `usize`
66
|
77
= help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
8-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
8+
= help: the trait `SliceIndex<[i32]>` is implemented for `usize`
99
= note: required for `[i32]` to implement `Index<i32>`
1010

1111
error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`

tests/ui/str/str-idx.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let _: u8 = s[4];
77
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
88
= note: you can use `.chars().nth()` or `.bytes().nth()`
99
for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
10-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
10+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
1111
= note: required for `str` to implement `Index<{integer}>`
1212

1313
error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -21,7 +21,7 @@ LL | let _ = s.get(4);
2121
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
2222
= note: you can use `.chars().nth()` or `.bytes().nth()`
2323
for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
24-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
24+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
2525
note: required by a bound in `core::str::<impl str>::get`
2626
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
2727

@@ -36,7 +36,7 @@ LL | let _ = s.get_unchecked(4);
3636
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
3737
= note: you can use `.chars().nth()` or `.bytes().nth()`
3838
for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
39-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
39+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
4040
note: required by a bound in `core::str::<impl str>::get_unchecked`
4141
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
4242

tests/ui/str/str-mut-idx.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ LL | s[1usize] = bot();
3131
| ^^^^^^ string indices are ranges of `usize`
3232
|
3333
= help: the trait `SliceIndex<str>` is not implemented for `usize`
34-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
34+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
3535
= note: required for `str` to implement `Index<usize>`
3636

3737
error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -45,7 +45,7 @@ LL | s.get_mut(1);
4545
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
4646
= note: you can use `.chars().nth()` or `.bytes().nth()`
4747
for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
48-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
48+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
4949
note: required by a bound in `core::str::<impl str>::get_mut`
5050
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
5151

@@ -60,7 +60,7 @@ LL | s.get_unchecked_mut(1);
6060
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
6161
= note: you can use `.chars().nth()` or `.bytes().nth()`
6262
for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
63-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
63+
= help: the trait `SliceIndex<[_]>` is implemented for `usize`
6464
note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
6565
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
6666

tests/ui/suggestions/issue-101623.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | Trait::do_stuff({ fun(&mut *inner) });
77
| | the trait `Trait<'_>` is not implemented for `*mut ()`
88
| required by a bound introduced by this call
99
|
10-
= help: the trait `Trait<'a>` is implemented for `()`
10+
= help: the trait `Trait<'_>` is implemented for `()`
1111

1212
error: aborting due to previous error
1313

tests/ui/suggestions/suggest-dereferencing-index.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let one_item_please: i32 = [1, 2, 3][i];
55
| ^ slice indices are of type `usize` or ranges of `usize`
66
|
77
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
8-
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
8+
= help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
99
= note: required for `[{integer}]` to implement `Index<&usize>`
1010
help: dereference this index
1111
|

0 commit comments

Comments
 (0)