Skip to content

Commit cbe7ba6

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 624e88b commit cbe7ba6

File tree

131 files changed

+1534
-541
lines changed

Some content is hidden

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

131 files changed

+1534
-541
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
@@ -1904,13 +1904,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19041904
// ignore `do_not_recommend` items
19051905
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
19061906
// Ignore automatically derived impls and `!Trait` impls.
1907-
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
1908-
.filter_map(|header| {
1907+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id).map(|h| (h, def_id)))
1908+
.filter_map(|(header, def_id)| {
19091909
(header.polarity != ty::ImplPolarity::Negative
19101910
|| self.tcx.is_automatically_derived(def_id))
1911-
.then(|| header.trait_ref.instantiate_identity())
1911+
.then(|| (header.trait_ref.instantiate_identity(), def_id))
19121912
})
1913-
.filter(|trait_ref| {
1913+
.filter(|(trait_ref, _)| {
19141914
let self_ty = trait_ref.self_ty();
19151915
// Avoid mentioning type parameters.
19161916
if let ty::Param(_) = self_ty.kind() {
@@ -1928,7 +1928,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19281928
})
19291929
.collect();
19301930

1931-
impl_candidates.sort_by_key(|tr| tr.to_string());
1931+
impl_candidates.sort_by_key(|(tr, _)| tr.to_string());
19321932
impl_candidates.dedup();
19331933
impl_candidates
19341934
};
@@ -1956,7 +1956,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19561956
let candidates = if impl_candidates.is_empty() {
19571957
alternative_candidates(trait_def_id)
19581958
} else {
1959-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
1959+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect()
19601960
};
19611961
let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
19621962
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
@@ -1988,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19881988
self.tcx.def_span(found_type),
19891989
"this type doesn't implement the required trait",
19901990
);
1991-
for trait_ref in candidates {
1991+
for (trait_ref, _) in candidates {
19921992
if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
19931993
&& let candidate_def_id = def.did()
19941994
&& let Some(name) = self.tcx.opt_item_name(candidate_def_id)
@@ -2201,12 +2201,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22012201
}
22022202

22032203
let other = if other { "other " } else { "" };
2204-
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diag<'_>| {
2205-
candidates.retain(|tr| !tr.references_error());
2204+
let report = |mut candidates: Vec<(TraitRef<'tcx>, DefId)>, err: &mut Diag<'_>| {
2205+
candidates.retain(|(tr, _)| !tr.references_error());
22062206
if candidates.is_empty() {
22072207
return false;
22082208
}
2209-
if let &[cand] = &candidates[..] {
2209+
if let &[(cand, def_id)] = &candidates[..] {
22102210
if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
22112211
&& !self.tcx.features().enabled(sym::try_trait_v2)
22122212
{
@@ -2222,56 +2222,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22222222
};
22232223
let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
22242224
let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
2225-
err.highlighted_help(vec![
2226-
StringPart::normal(format!("the trait `{trait_}` ",)),
2227-
StringPart::highlighted("is"),
2228-
StringPart::normal(desc),
2229-
StringPart::highlighted(self_ty),
2230-
StringPart::normal("`"),
2231-
StringPart::normal(mention_castable),
2232-
]);
2225+
err.highlighted_span_help(
2226+
self.tcx.def_span(def_id),
2227+
vec![
2228+
StringPart::normal(format!("the trait `{trait_}` ",)),
2229+
StringPart::highlighted("is"),
2230+
StringPart::normal(desc),
2231+
StringPart::highlighted(self_ty),
2232+
StringPart::normal("`"),
2233+
StringPart::normal(mention_castable),
2234+
],
2235+
);
22332236
return true;
22342237
}
2235-
let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
2238+
let trait_ref = TraitRef::identity(self.tcx, candidates[0].0.def_id);
22362239
// Check if the trait is the same in all cases. If so, we'll only show the type.
22372240
let mut traits: Vec<_> =
2238-
candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
2241+
candidates.iter().map(|(c, _)| c.print_only_trait_path().to_string()).collect();
22392242
traits.sort();
22402243
traits.dedup();
22412244
// FIXME: this could use a better heuristic, like just checking
22422245
// that args[1..] is the same.
22432246
let all_traits_equal = traits.len() == 1;
22442247

2245-
let candidates: Vec<String> = candidates
2246-
.into_iter()
2247-
.map(|c| {
2248-
if all_traits_equal {
2249-
format!("\n {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2250-
} else {
2251-
format!(
2252-
"\n `{}` implements `{}`",
2253-
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2254-
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2255-
)
2256-
}
2257-
})
2258-
.collect();
2259-
22602248
let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
22612249
candidates.len()
22622250
} else {
22632251
8
22642252
};
2265-
err.help(format!(
2266-
"the following {other}types implement trait `{}`:{}{}",
2267-
trait_ref.print_trait_sugared(),
2268-
candidates[..end].join(""),
2269-
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2270-
format!("\nand {} others", candidates.len() - 8)
2271-
} else {
2272-
String::new()
2253+
if candidates.len() < 5 {
2254+
let spans: Vec<_> =
2255+
candidates.iter().map(|(_, def_id)| self.tcx.def_span(def_id)).collect();
2256+
let mut span: MultiSpan = spans.into();
2257+
for (c, def_id) in &candidates {
2258+
let msg = if all_traits_equal {
2259+
format!("`{}`", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
2260+
} else {
2261+
format!(
2262+
"`{}` implements `{}`",
2263+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2264+
self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
2265+
)
2266+
};
2267+
span.push_span_label(self.tcx.def_span(def_id), msg);
22732268
}
2274-
));
2269+
err.span_help(
2270+
span,
2271+
format!(
2272+
"the following {other}types implement trait `{}`",
2273+
trait_ref.print_trait_sugared(),
2274+
),
2275+
);
2276+
} else {
2277+
let candidate_names: Vec<String> = candidates
2278+
.iter()
2279+
.map(|(c, _)| {
2280+
if all_traits_equal {
2281+
format!(
2282+
"\n {}",
2283+
self.tcx.short_string(c.self_ty(), err.long_ty_path())
2284+
)
2285+
} else {
2286+
format!(
2287+
"\n `{}` implements `{}`",
2288+
self.tcx.short_string(c.self_ty(), err.long_ty_path()),
2289+
self.tcx
2290+
.short_string(c.print_only_trait_path(), err.long_ty_path()),
2291+
)
2292+
}
2293+
})
2294+
.collect();
2295+
err.help(format!(
2296+
"the following {other}types implement trait `{}`:{}{}",
2297+
trait_ref.print_trait_sugared(),
2298+
candidate_names[..end].join(""),
2299+
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
2300+
format!("\nand {} others", candidates.len() - 8)
2301+
} else {
2302+
String::new()
2303+
}
2304+
));
2305+
}
22752306
true
22762307
};
22772308

@@ -2333,7 +2364,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
23332364
(cand.similarity, len, cand.trait_ref.to_string())
23342365
});
23352366
let mut impl_candidates: Vec<_> =
2336-
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
2367+
impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect();
23372368
impl_candidates.dedup();
23382369

23392370
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)