Skip to content

Commit 3f07cda

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 fa6e2ba commit 3f07cda

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
@@ -1862,13 +1862,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18621862
// ignore `do_not_recommend` items
18631863
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
18641864
// Ignore automatically derived impls and `!Trait` impls.
1865-
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
1866-
.filter_map(|header| {
1865+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id).map(|h| (h, def_id)))
1866+
.filter_map(|(header, def_id)| {
18671867
(header.polarity != ty::ImplPolarity::Negative
18681868
|| self.tcx.is_automatically_derived(def_id))
1869-
.then(|| header.trait_ref.instantiate_identity())
1869+
.then(|| (header.trait_ref.instantiate_identity(), def_id))
18701870
})
1871-
.filter(|trait_ref| {
1871+
.filter(|(trait_ref, _)| {
18721872
let self_ty = trait_ref.self_ty();
18731873
// Avoid mentioning type parameters.
18741874
if let ty::Param(_) = self_ty.kind() {
@@ -1886,7 +1886,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18861886
})
18871887
.collect();
18881888

1889-
impl_candidates.sort_by_key(|tr| tr.to_string());
1889+
impl_candidates.sort_by_key(|(tr, _)| tr.to_string());
18901890
impl_candidates.dedup();
18911891
impl_candidates
18921892
};
@@ -1914,7 +1914,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19141914
let candidates = if impl_candidates.is_empty() {
19151915
alternative_candidates(trait_def_id)
19161916
} else {
1917-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
1917+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect()
19181918
};
19191919
let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
19201920
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
@@ -1946,7 +1946,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19461946
self.tcx.def_span(found_type),
19471947
"this type doesn't implement the required trait",
19481948
);
1949-
for trait_ref in candidates {
1949+
for (trait_ref, _) in candidates {
19501950
if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
19511951
&& let candidate_def_id = def.did()
19521952
&& let Some(name) = self.tcx.opt_item_name(candidate_def_id)
@@ -2159,12 +2159,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
21592159
}
21602160

21612161
let other = if other { "other " } else { "" };
2162-
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diag<'_>| {
2163-
candidates.retain(|tr| !tr.references_error());
2162+
let report = |mut candidates: Vec<(TraitRef<'tcx>, DefId)>, err: &mut Diag<'_>| {
2163+
candidates.retain(|(tr, _)| !tr.references_error());
21642164
if candidates.is_empty() {
21652165
return false;
21662166
}
2167-
if let &[cand] = &candidates[..] {
2167+
if let &[(cand, def_id)] = &candidates[..] {
21682168
if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
21692169
&& !self.tcx.features().enabled(sym::try_trait_v2)
21702170
{
@@ -2180,56 +2180,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
21802180
};
21812181
let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
21822182
let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
2183-
err.highlighted_help(vec![
2184-
StringPart::normal(format!("the trait `{trait_}` ",)),
2185-
StringPart::highlighted("is"),
2186-
StringPart::normal(desc),
2187-
StringPart::highlighted(self_ty),
2188-
StringPart::normal("`"),
2189-
StringPart::normal(mention_castable),
2190-
]);
2183+
err.highlighted_span_help(
2184+
self.tcx.def_span(def_id),
2185+
vec![
2186+
StringPart::normal(format!("the trait `{trait_}` ",)),
2187+
StringPart::highlighted("is"),
2188+
StringPart::normal(desc),
2189+
StringPart::highlighted(self_ty),
2190+
StringPart::normal("`"),
2191+
StringPart::normal(mention_castable),
2192+
],
2193+
);
21912194
return true;
21922195
}
2193-
let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
2196+
let trait_ref = TraitRef::identity(self.tcx, candidates[0].0.def_id);
21942197
// Check if the trait is the same in all cases. If so, we'll only show the type.
21952198
let mut traits: Vec<_> =
2196-
candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
2199+
candidates.iter().map(|(c, _)| c.print_only_trait_path().to_string()).collect();
21972200
traits.sort();
21982201
traits.dedup();
21992202
// FIXME: this could use a better heuristic, like just checking
22002203
// that args[1..] is the same.
22012204
let all_traits_equal = traits.len() == 1;
22022205

2203-
let candidates: Vec<String> = candidates
2204-
.into_iter()
2205-
.map(|c| {
2206-
if all_traits_equal {
2207-
format!("\n {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2208-
} else {
2209-
format!(
2210-
"\n `{}` implements `{}`",
2211-
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2212-
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2213-
)
2214-
}
2215-
})
2216-
.collect();
2217-
22182206
let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
22192207
candidates.len()
22202208
} else {
22212209
8
22222210
};
2223-
err.help(format!(
2224-
"the following {other}types implement trait `{}`:{}{}",
2225-
trait_ref.print_trait_sugared(),
2226-
candidates[..end].join(""),
2227-
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2228-
format!("\nand {} others", candidates.len() - 8)
2229-
} else {
2230-
String::new()
2211+
if candidates.len() < 5 {
2212+
let spans: Vec<_> =
2213+
candidates.iter().map(|(_, def_id)| self.tcx.def_span(def_id)).collect();
2214+
let mut span: MultiSpan = spans.into();
2215+
for (c, def_id) in &candidates {
2216+
let msg = if all_traits_equal {
2217+
format!("`{}`", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2218+
} else {
2219+
format!(
2220+
"`{}` implements `{}`",
2221+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2222+
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2223+
)
2224+
};
2225+
span.push_span_label(self.tcx.def_span(def_id), msg);
22312226
}
2232-
));
2227+
err.span_help(
2228+
span,
2229+
format!(
2230+
"the following {other}types implement trait `{}`",
2231+
trait_ref.print_trait_sugared(),
2232+
),
2233+
);
2234+
} else {
2235+
let candidate_names: Vec<String> = candidates
2236+
.iter()
2237+
.map(|(c, _)| {
2238+
if all_traits_equal {
2239+
format!(
2240+
"\n {}",
2241+
self.tcx.short_string(c.self_ty(), err.long_ty_path())
2242+
)
2243+
} else {
2244+
format!(
2245+
"\n `{}` implements `{}`",
2246+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2247+
self.tcx
2248+
.short_string(c.print_only_trait_path(), err.long_ty_path()),
2249+
)
2250+
}
2251+
})
2252+
.collect();
2253+
err.help(format!(
2254+
"the following {other}types implement trait `{}`:{}{}",
2255+
trait_ref.print_trait_sugared(),
2256+
candidate_names[..end].join(""),
2257+
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2258+
format!("\nand {} others", candidates.len() - 8)
2259+
} else {
2260+
String::new()
2261+
}
2262+
));
2263+
}
22332264
true
22342265
};
22352266

@@ -2279,7 +2310,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22792310
.collect();
22802311
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref.to_string()));
22812312
let mut impl_candidates: Vec<_> =
2282-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
2313+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect();
22832314
impl_candidates.dedup();
22842315

22852316
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
@@ -9,9 +9,13 @@ help: the trait `VisitorResult` is not implemented for `NotAValidResultType`
99
|
1010
LL | struct NotAValidResultType;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
= help: the following other types implement trait `VisitorResult`:
13-
()
14-
ControlFlow<T>
12+
help: the following other types implement trait `VisitorResult`
13+
--> /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
14+
|
15+
= note: `()`
16+
::: /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
17+
|
18+
= note: `ControlFlow<T>`
1519
note: required by a bound in `rustc_ast::visit::Visitor::Result`
1620
--> /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL
1721
= 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
@@ -9,9 +9,14 @@ help: the trait `VisitorResult` is not implemented for `NotAValidResultType`
99
|
1010
LL | struct NotAValidResultType;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
= help: the following other types implement trait `VisitorResult`:
13-
()
14-
ControlFlow<T>
12+
help: the following other types implement trait `VisitorResult`
13+
--> $COMPILER_DIR_REAL/rustc_ast_ir/src/visit.rs:LL:COL
14+
|
15+
LL | impl VisitorResult for () {
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `()`
17+
...
18+
LL | impl<T> VisitorResult for ControlFlow<T> {
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ControlFlow<T>`
1520
note: required by a bound in `rustc_ast::visit::Visitor::Result`
1621
--> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL
1722
|

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)