Skip to content

Commit a05bf52

Browse files
committed
When more than a single impl and less than 4 could apply, point at them
``` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | help: the following other types implement trait `Bar` --> $DIR/issue-67185-2.rs:9:1 | LL | impl Bar for [u16; 4] {} | ^^^^^^^^^^^^^^^^^^^^^ `[u16; 4]` LL | impl Bar for [[u16; 3]; 3] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `[[u16; 3]; 3]` note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this trait LL | where LL | [<u8 as Baz>::Quaks; 2]: Bar, | ^^^ required by this bound in `Foo` ```
1 parent 776983a commit a05bf52

File tree

126 files changed

+1465
-534
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+1465
-534
lines changed

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

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,13 +1841,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18411841
// ignore `do_not_recommend` items
18421842
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
18431843
// Ignore automatically derived impls and `!Trait` impls.
1844-
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
1845-
.filter_map(|header| {
1844+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id).map(|h| (h, def_id)))
1845+
.filter_map(|(header, def_id)| {
18461846
(header.polarity != ty::ImplPolarity::Negative
18471847
|| self.tcx.is_automatically_derived(def_id))
1848-
.then(|| header.trait_ref.instantiate_identity())
1848+
.then(|| (header.trait_ref.instantiate_identity(), def_id))
18491849
})
1850-
.filter(|trait_ref| {
1850+
.filter(|(trait_ref, _)| {
18511851
let self_ty = trait_ref.self_ty();
18521852
// Avoid mentioning type parameters.
18531853
if let ty::Param(_) = self_ty.kind() {
@@ -1865,7 +1865,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18651865
})
18661866
.collect();
18671867

1868-
impl_candidates.sort_by_key(|tr| tr.to_string());
1868+
impl_candidates.sort_by_key(|(tr, _)| tr.to_string());
18691869
impl_candidates.dedup();
18701870
impl_candidates
18711871
};
@@ -1893,7 +1893,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18931893
let candidates = if impl_candidates.is_empty() {
18941894
alternative_candidates(trait_def_id)
18951895
} else {
1896-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
1896+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect()
18971897
};
18981898
let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
18991899
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
@@ -1925,7 +1925,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19251925
self.tcx.def_span(found_type),
19261926
"this type doesn't implement the required trait",
19271927
);
1928-
for trait_ref in candidates {
1928+
for (trait_ref, _) in candidates {
19291929
if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
19301930
&& let candidate_def_id = def.did()
19311931
&& let Some(name) = self.tcx.opt_item_name(candidate_def_id)
@@ -2138,12 +2138,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
21382138
}
21392139

21402140
let other = if other { "other " } else { "" };
2141-
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diag<'_>| {
2142-
candidates.retain(|tr| !tr.references_error());
2141+
let report = |mut candidates: Vec<(TraitRef<'tcx>, DefId)>, err: &mut Diag<'_>| {
2142+
candidates.retain(|(tr, _)| !tr.references_error());
21432143
if candidates.is_empty() {
21442144
return false;
21452145
}
2146-
if let &[cand] = &candidates[..] {
2146+
if let &[(cand, def_id)] = &candidates[..] {
21472147
if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
21482148
&& !self.tcx.features().enabled(sym::try_trait_v2)
21492149
{
@@ -2159,56 +2159,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
21592159
};
21602160
let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
21612161
let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
2162-
err.highlighted_help(vec![
2163-
StringPart::normal(format!("the trait `{trait_}` ",)),
2164-
StringPart::highlighted("is"),
2165-
StringPart::normal(desc),
2166-
StringPart::highlighted(self_ty),
2167-
StringPart::normal("`"),
2168-
StringPart::normal(mention_castable),
2169-
]);
2162+
err.highlighted_span_help(
2163+
self.tcx.def_span(def_id),
2164+
vec![
2165+
StringPart::normal(format!("the trait `{trait_}` ",)),
2166+
StringPart::highlighted("is"),
2167+
StringPart::normal(desc),
2168+
StringPart::highlighted(self_ty),
2169+
StringPart::normal("`"),
2170+
StringPart::normal(mention_castable),
2171+
],
2172+
);
21702173
return true;
21712174
}
2172-
let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
2175+
let trait_ref = TraitRef::identity(self.tcx, candidates[0].0.def_id);
21732176
// Check if the trait is the same in all cases. If so, we'll only show the type.
21742177
let mut traits: Vec<_> =
2175-
candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
2178+
candidates.iter().map(|(c, _)| c.print_only_trait_path().to_string()).collect();
21762179
traits.sort();
21772180
traits.dedup();
21782181
// FIXME: this could use a better heuristic, like just checking
21792182
// that args[1..] is the same.
21802183
let all_traits_equal = traits.len() == 1;
21812184

2182-
let candidates: Vec<String> = candidates
2183-
.into_iter()
2184-
.map(|c| {
2185-
if all_traits_equal {
2186-
format!("\n {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2187-
} else {
2188-
format!(
2189-
"\n `{}` implements `{}`",
2190-
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2191-
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2192-
)
2193-
}
2194-
})
2195-
.collect();
2196-
21972185
let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
21982186
candidates.len()
21992187
} else {
22002188
8
22012189
};
2202-
err.help(format!(
2203-
"the following {other}types implement trait `{}`:{}{}",
2204-
trait_ref.print_trait_sugared(),
2205-
candidates[..end].join(""),
2206-
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2207-
format!("\nand {} others", candidates.len() - 8)
2208-
} else {
2209-
String::new()
2190+
if candidates.len() < 5 {
2191+
let spans: Vec<_> =
2192+
candidates.iter().map(|(_, def_id)| self.tcx.def_span(def_id)).collect();
2193+
let mut span: MultiSpan = spans.into();
2194+
for (c, def_id) in &candidates {
2195+
let msg = if all_traits_equal {
2196+
format!("`{}`", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2197+
} else {
2198+
format!(
2199+
"`{}` implements `{}`",
2200+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2201+
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2202+
)
2203+
};
2204+
span.push_span_label(self.tcx.def_span(def_id), msg);
22102205
}
2211-
));
2206+
err.span_help(
2207+
span,
2208+
format!(
2209+
"the following {other}types implement trait `{}`",
2210+
trait_ref.print_trait_sugared(),
2211+
),
2212+
);
2213+
} else {
2214+
let candidate_names: Vec<String> = candidates
2215+
.iter()
2216+
.map(|(c, _)| {
2217+
if all_traits_equal {
2218+
format!(
2219+
"\n {}",
2220+
self.tcx.short_string(c.self_ty(), err.long_ty_path())
2221+
)
2222+
} else {
2223+
format!(
2224+
"\n `{}` implements `{}`",
2225+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2226+
self.tcx
2227+
.short_string(c.print_only_trait_path(), err.long_ty_path()),
2228+
)
2229+
}
2230+
})
2231+
.collect();
2232+
err.help(format!(
2233+
"the following {other}types implement trait `{}`:{}{}",
2234+
trait_ref.print_trait_sugared(),
2235+
candidate_names[..end].join(""),
2236+
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2237+
format!("\nand {} others", candidates.len() - 8)
2238+
} else {
2239+
String::new()
2240+
}
2241+
));
2242+
}
22122243
true
22132244
};
22142245

@@ -2258,7 +2289,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22582289
.collect();
22592290
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref.to_string()));
22602291
let mut impl_candidates: Vec<_> =
2261-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
2292+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect();
22622293
impl_candidates.dedup();
22632294

22642295
report(impl_candidates, err)

tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisf
44
LL | type Result = NotAValidResultType;
55
| ^^^^^^^^^^^^^^^^^^^ the trait `VisitorResult` is not implemented for `NotAValidResultType`
66
|
7-
= help: the following other types implement trait `VisitorResult`:
8-
()
9-
ControlFlow<T>
7+
help: the following other types implement trait `VisitorResult`
8+
--> /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
9+
|
10+
= note: `()`
11+
::: /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
12+
|
13+
= note: `ControlFlow<T>`
1014
note: required by a bound in `rustc_ast::visit::Visitor::Result`
1115
--> /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL
1216
= note: this error originates in the macro `common_visitor_and_walkers` (in Nightly builds, run with -Z macro-backtrace for more info)

tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisf
44
LL | type Result = NotAValidResultType;
55
| ^^^^^^^^^^^^^^^^^^^ the trait `VisitorResult` is not implemented for `NotAValidResultType`
66
|
7-
= help: the following other types implement trait `VisitorResult`:
8-
()
9-
ControlFlow<T>
7+
help: the following other types implement trait `VisitorResult`
8+
--> $COMPILER_DIR_REAL/rustc_ast_ir/src/visit.rs:LL:COL
9+
|
10+
LL | impl VisitorResult for () {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `()`
12+
...
13+
LL | impl<T> VisitorResult for ControlFlow<T> {
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ControlFlow<T>`
1015
note: required by a bound in `rustc_ast::visit::Visitor::Result`
1116
--> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL
1217
|

tests/ui/allocator/not-an-allocator.stderr

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ LL | #[global_allocator]
66
LL | static A: usize = 0;
77
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
88
|
9-
= help: the trait `GlobalAlloc` is implemented for `System`
9+
help: the trait `GlobalAlloc` is implemented for `System`
10+
--> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
1011

1112
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
1213
--> $DIR/not-an-allocator.rs:2:11
@@ -16,7 +17,8 @@ LL | #[global_allocator]
1617
LL | static A: usize = 0;
1718
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
1819
|
19-
= help: the trait `GlobalAlloc` is implemented for `System`
20+
help: the trait `GlobalAlloc` is implemented for `System`
21+
--> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
2022
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
2123

2224
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -27,7 +29,8 @@ LL | #[global_allocator]
2729
LL | static A: usize = 0;
2830
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
2931
|
30-
= help: the trait `GlobalAlloc` is implemented for `System`
32+
help: the trait `GlobalAlloc` is implemented for `System`
33+
--> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
3134
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3235

3336
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -38,7 +41,8 @@ LL | #[global_allocator]
3841
LL | static A: usize = 0;
3942
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
4043
|
41-
= help: the trait `GlobalAlloc` is implemented for `System`
44+
help: the trait `GlobalAlloc` is implemented for `System`
45+
--> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
4246
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4347

4448
error: aborting due to 4 previous errors

tests/ui/associated-types/associated-types-path-2.stderr

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ LL | f1(2u32, 4u32);
2525
| |
2626
| required by a bound introduced by this call
2727
|
28-
= help: the trait `Foo` is implemented for `i32`
28+
help: the trait `Foo` is implemented for `i32`
29+
--> $DIR/associated-types-path-2.rs:11:1
30+
|
31+
LL | impl Foo for i32 {
32+
| ^^^^^^^^^^^^^^^^
2933
note: required by a bound in `f1`
3034
--> $DIR/associated-types-path-2.rs:15:14
3135
|
@@ -38,7 +42,11 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
3842
LL | f1(2u32, 4u32);
3943
| ^^^^ the trait `Foo` is not implemented for `u32`
4044
|
41-
= help: the trait `Foo` is implemented for `i32`
45+
help: the trait `Foo` is implemented for `i32`
46+
--> $DIR/associated-types-path-2.rs:11:1
47+
|
48+
LL | impl Foo for i32 {
49+
| ^^^^^^^^^^^^^^^^
4250

4351
error[E0277]: the trait bound `u32: Foo` is not satisfied
4452
--> $DIR/associated-types-path-2.rs:37:8
@@ -48,7 +56,11 @@ LL | f1(2u32, 4i32);
4856
| |
4957
| required by a bound introduced by this call
5058
|
51-
= help: the trait `Foo` is implemented for `i32`
59+
help: the trait `Foo` is implemented for `i32`
60+
--> $DIR/associated-types-path-2.rs:11:1
61+
|
62+
LL | impl Foo for i32 {
63+
| ^^^^^^^^^^^^^^^^
5264
note: required by a bound in `f1`
5365
--> $DIR/associated-types-path-2.rs:15:14
5466
|
@@ -61,7 +73,11 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
6173
LL | f1(2u32, 4i32);
6274
| ^^^^ the trait `Foo` is not implemented for `u32`
6375
|
64-
= help: the trait `Foo` is implemented for `i32`
76+
help: the trait `Foo` is implemented for `i32`
77+
--> $DIR/associated-types-path-2.rs:11:1
78+
|
79+
LL | impl Foo for i32 {
80+
| ^^^^^^^^^^^^^^^^
6581

6682
error[E0308]: mismatched types
6783
--> $DIR/associated-types-path-2.rs:43:18

tests/ui/associated-types/hr-associated-type-bound-1.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type U = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7-
= help: the trait `Clone` is implemented for `String`
7+
help: the trait `Clone` is implemented for `String`
8+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
89
note: required by a bound in `X`
910
--> $DIR/hr-associated-type-bound-1.rs:3:33
1011
|
@@ -20,7 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
2021
LL | 1i32.f("abc");
2122
| ^ the trait `Clone` is not implemented for `str`
2223
|
23-
= help: the trait `Clone` is implemented for `String`
24+
help: the trait `Clone` is implemented for `String`
25+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
2426
note: required by a bound in `X::f`
2527
--> $DIR/hr-associated-type-bound-1.rs:3:33
2628
|

tests/ui/associated-types/hr-associated-type-bound-param-1.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type V = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7-
= help: the trait `Clone` is implemented for `String`
7+
help: the trait `Clone` is implemented for `String`
8+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
89
note: required by a bound in `Y`
910
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
1011
|
@@ -20,7 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
2021
LL | 1u8.g("abc");
2122
| ^ the trait `Clone` is not implemented for `str`
2223
|
23-
= help: the trait `Clone` is implemented for `String`
24+
help: the trait `Clone` is implemented for `String`
25+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
2426
note: required by a bound in `Y::g`
2527
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
2628
|

0 commit comments

Comments
 (0)