Skip to content

Commit eeadffd

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 1d86090 commit eeadffd

File tree

133 files changed

+1567
-551
lines changed

Some content is hidden

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

133 files changed

+1567
-551
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
@@ -1906,13 +1906,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19061906
// ignore `do_not_recommend` items
19071907
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
19081908
// Ignore automatically derived impls and `!Trait` impls.
1909-
.map(|def_id| self.tcx.impl_trait_header(def_id))
1910-
.filter_map(|header| {
1909+
.map(|def_id| (self.tcx.impl_trait_header(def_id), def_id))
1910+
.filter_map(|(header, def_id)| {
19111911
(header.polarity != ty::ImplPolarity::Negative
19121912
|| self.tcx.is_automatically_derived(def_id))
1913-
.then(|| header.trait_ref.instantiate_identity())
1913+
.then(|| (header.trait_ref.instantiate_identity(), def_id))
19141914
})
1915-
.filter(|trait_ref| {
1915+
.filter(|(trait_ref, _)| {
19161916
let self_ty = trait_ref.self_ty();
19171917
// Avoid mentioning type parameters.
19181918
if let ty::Param(_) = self_ty.kind() {
@@ -1944,7 +1944,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19441944
})
19451945
.collect();
19461946

1947-
impl_candidates.sort_by_key(|tr| tr.to_string());
1947+
impl_candidates.sort_by_key(|(tr, _)| tr.to_string());
19481948
impl_candidates.dedup();
19491949
impl_candidates
19501950
};
@@ -1972,7 +1972,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19721972
let candidates = if impl_candidates.is_empty() {
19731973
alternative_candidates(trait_def_id)
19741974
} else {
1975-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
1975+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect()
19761976
};
19771977
let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
19781978
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
@@ -2004,7 +2004,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
20042004
self.tcx.def_span(found_type),
20052005
"this type doesn't implement the required trait",
20062006
);
2007-
for trait_ref in candidates {
2007+
for (trait_ref, _) in candidates {
20082008
if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
20092009
&& let candidate_def_id = def.did()
20102010
&& let Some(name) = self.tcx.opt_item_name(candidate_def_id)
@@ -2217,12 +2217,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22172217
}
22182218

22192219
let other = if other { "other " } else { "" };
2220-
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diag<'_>| {
2221-
candidates.retain(|tr| !tr.references_error());
2220+
let report = |mut candidates: Vec<(TraitRef<'tcx>, DefId)>, err: &mut Diag<'_>| {
2221+
candidates.retain(|(tr, _)| !tr.references_error());
22222222
if candidates.is_empty() {
22232223
return false;
22242224
}
2225-
if let &[cand] = &candidates[..] {
2225+
if let &[(cand, def_id)] = &candidates[..] {
22262226
if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
22272227
&& !self.tcx.features().enabled(sym::try_trait_v2)
22282228
{
@@ -2238,56 +2238,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22382238
};
22392239
let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
22402240
let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
2241-
err.highlighted_help(vec![
2242-
StringPart::normal(format!("the trait `{trait_}` ",)),
2243-
StringPart::highlighted("is"),
2244-
StringPart::normal(desc),
2245-
StringPart::highlighted(self_ty),
2246-
StringPart::normal("`"),
2247-
StringPart::normal(mention_castable),
2248-
]);
2241+
err.highlighted_span_help(
2242+
self.tcx.def_span(def_id),
2243+
vec![
2244+
StringPart::normal(format!("the trait `{trait_}` ",)),
2245+
StringPart::highlighted("is"),
2246+
StringPart::normal(desc),
2247+
StringPart::highlighted(self_ty),
2248+
StringPart::normal("`"),
2249+
StringPart::normal(mention_castable),
2250+
],
2251+
);
22492252
return true;
22502253
}
2251-
let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
2254+
let trait_ref = TraitRef::identity(self.tcx, candidates[0].0.def_id);
22522255
// Check if the trait is the same in all cases. If so, we'll only show the type.
22532256
let mut traits: Vec<_> =
2254-
candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
2257+
candidates.iter().map(|(c, _)| c.print_only_trait_path().to_string()).collect();
22552258
traits.sort();
22562259
traits.dedup();
22572260
// FIXME: this could use a better heuristic, like just checking
22582261
// that args[1..] is the same.
22592262
let all_traits_equal = traits.len() == 1;
22602263

2261-
let candidates: Vec<String> = candidates
2262-
.into_iter()
2263-
.map(|c| {
2264-
if all_traits_equal {
2265-
format!("\n {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2266-
} else {
2267-
format!(
2268-
"\n `{}` implements `{}`",
2269-
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2270-
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2271-
)
2272-
}
2273-
})
2274-
.collect();
2275-
22762264
let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
22772265
candidates.len()
22782266
} else {
22792267
8
22802268
};
2281-
err.help(format!(
2282-
"the following {other}types implement trait `{}`:{}{}",
2283-
trait_ref.print_trait_sugared(),
2284-
candidates[..end].join(""),
2285-
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2286-
format!("\nand {} others", candidates.len() - 8)
2287-
} else {
2288-
String::new()
2269+
if candidates.len() < 5 {
2270+
let spans: Vec<_> =
2271+
candidates.iter().map(|(_, def_id)| self.tcx.def_span(def_id)).collect();
2272+
let mut span: MultiSpan = spans.into();
2273+
for (c, def_id) in &candidates {
2274+
let msg = if all_traits_equal {
2275+
format!("`{}`", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2276+
} else {
2277+
format!(
2278+
"`{}` implements `{}`",
2279+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2280+
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2281+
)
2282+
};
2283+
span.push_span_label(self.tcx.def_span(def_id), msg);
22892284
}
2290-
));
2285+
err.span_help(
2286+
span,
2287+
format!(
2288+
"the following {other}types implement trait `{}`",
2289+
trait_ref.print_trait_sugared(),
2290+
),
2291+
);
2292+
} else {
2293+
let candidate_names: Vec<String> = candidates
2294+
.iter()
2295+
.map(|(c, _)| {
2296+
if all_traits_equal {
2297+
format!(
2298+
"\n {}",
2299+
self.tcx.short_string(c.self_ty(), err.long_ty_path())
2300+
)
2301+
} else {
2302+
format!(
2303+
"\n `{}` implements `{}`",
2304+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2305+
self.tcx
2306+
.short_string(c.print_only_trait_path(), err.long_ty_path()),
2307+
)
2308+
}
2309+
})
2310+
.collect();
2311+
err.help(format!(
2312+
"the following {other}types implement trait `{}`:{}{}",
2313+
trait_ref.print_trait_sugared(),
2314+
candidate_names[..end].join(""),
2315+
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2316+
format!("\nand {} others", candidates.len() - 8)
2317+
} else {
2318+
String::new()
2319+
}
2320+
));
2321+
}
22912322
true
22922323
};
22932324

@@ -2349,7 +2380,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
23492380
(cand.similarity, len, cand.trait_ref.to_string())
23502381
});
23512382
let mut impl_candidates: Vec<_> =
2352-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
2383+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect();
23532384
impl_candidates.dedup();
23542385

23552386
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.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ revisions: u w
2+
//@[u] only-unix
3+
//@[w] only-windows
14
#[global_allocator]
25
static A: usize = 0;
36
//~^ ERROR E0277

tests/ui/allocator/not-an-allocator.stderr renamed to tests/ui/allocator/not-an-allocator.u.stderr

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,48 @@
11
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
2-
--> $DIR/not-an-allocator.rs:2:11
2+
--> $DIR/not-an-allocator.rs:5:11
33
|
44
LL | #[global_allocator]
55
| ------------------- in this attribute macro expansion
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
12-
--> $DIR/not-an-allocator.rs:2:11
13+
--> $DIR/not-an-allocator.rs:5:11
1314
|
1415
LL | #[global_allocator]
1516
| ------------------- in this attribute macro expansion
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
23-
--> $DIR/not-an-allocator.rs:2:11
25+
--> $DIR/not-an-allocator.rs:5:11
2426
|
2527
LL | #[global_allocator]
2628
| ------------------- in this attribute macro expansion
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
34-
--> $DIR/not-an-allocator.rs:2:11
37+
--> $DIR/not-an-allocator.rs:5:11
3538
|
3639
LL | #[global_allocator]
3740
| ------------------- in this attribute macro expansion
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
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
2+
--> $DIR/not-an-allocator.rs:5:11
3+
|
4+
LL | #[global_allocator]
5+
| ------------------- in this attribute macro expansion
6+
LL | static A: usize = 0;
7+
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
8+
|
9+
help: the trait `GlobalAlloc` is implemented for `System`
10+
--> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL
11+
12+
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
13+
--> $DIR/not-an-allocator.rs:5:11
14+
|
15+
LL | #[global_allocator]
16+
| ------------------- in this attribute macro expansion
17+
LL | static A: usize = 0;
18+
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
19+
|
20+
help: the trait `GlobalAlloc` is implemented for `System`
21+
--> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL
22+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
23+
24+
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
25+
--> $DIR/not-an-allocator.rs:5:11
26+
|
27+
LL | #[global_allocator]
28+
| ------------------- in this attribute macro expansion
29+
LL | static A: usize = 0;
30+
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
31+
|
32+
help: the trait `GlobalAlloc` is implemented for `System`
33+
--> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL
34+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
35+
36+
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
37+
--> $DIR/not-an-allocator.rs:5:11
38+
|
39+
LL | #[global_allocator]
40+
| ------------------- in this attribute macro expansion
41+
LL | static A: usize = 0;
42+
| ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
43+
|
44+
help: the trait `GlobalAlloc` is implemented for `System`
45+
--> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL
46+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
47+
48+
error: aborting due to 4 previous errors
49+
50+
For more information about this error, try `rustc --explain E0277`.

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

0 commit comments

Comments
 (0)