Skip to content

Commit 9f2d7b1

Browse files
committed
fix(traits): clarify conditional impl diagnostics
1 parent d13ea3c commit 9f2d7b1

8 files changed

Lines changed: 78 additions & 13 deletions

File tree

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

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,18 +2326,71 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
23262326
{
23272327
return false;
23282328
}
2329+
let mut failing_obligations = Vec::new();
23292330
let (desc, mention_castable) =
23302331
match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) {
23312332
(ty::FnPtr(..), ty::FnDef(..)) => {
23322333
(" implemented for fn pointer `", ", cast using `as`")
23332334
}
23342335
(ty::FnPtr(..), _) => (" implemented for fn pointer `", ""),
2335-
_ => (" implemented for `", ""),
2336+
_ => {
2337+
if !self.tcx.predicates_of(def_id).predicates.is_empty() {
2338+
failing_obligations = self.probe(|_| {
2339+
let ocx = ObligationCtxt::new_with_diagnostics(self);
2340+
self.enter_forall(trait_pred, |obligation_trait_ref| {
2341+
let impl_args = self.fresh_args_for_item(DUMMY_SP, def_id);
2342+
let impl_trait_ref = ocx.normalize(
2343+
&ObligationCause::dummy(),
2344+
param_env,
2345+
ty::EarlyBinder::bind(self.tcx, cand)
2346+
.instantiate(self.tcx, impl_args),
2347+
);
2348+
if ocx
2349+
.eq(
2350+
&ObligationCause::dummy(),
2351+
param_env,
2352+
obligation_trait_ref.trait_ref,
2353+
impl_trait_ref,
2354+
)
2355+
.is_err()
2356+
{
2357+
return Vec::new();
2358+
}
2359+
ocx.register_obligations(
2360+
self.tcx
2361+
.predicates_of(def_id)
2362+
.instantiate(self.tcx, impl_args)
2363+
.into_iter()
2364+
.map(|(clause, span)| {
2365+
Obligation::new(
2366+
self.tcx,
2367+
ObligationCause::dummy_with_span(span),
2368+
param_env,
2369+
clause.skip_norm_wip(),
2370+
)
2371+
}),
2372+
);
2373+
ocx.try_evaluate_obligations()
2374+
})
2375+
});
2376+
}
2377+
2378+
if !failing_obligations.is_empty() {
2379+
(" conditionally implemented for `", "")
2380+
} else {
2381+
(" implemented for `", "")
2382+
}
2383+
}
23362384
};
23372385
let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
23382386
let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
2387+
let mut multi_span = MultiSpan::from_span(self.tcx.def_span(def_id));
2388+
for error in failing_obligations {
2389+
multi_span
2390+
.push_span_label(error.obligation.cause.span, "unsatisfied trait bound");
2391+
}
23392392
err.highlighted_span_help(
2340-
self.tcx.def_span(def_id),
2393+
multi_span,
23412394
vec![
23422395
StringPart::normal(format!("the trait `{trait_}` ")),
23432396
StringPart::highlighted("is"),

tests/ui/derives/redundant-derive-note-on-unimplemented.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ LL | println!("{:?}", S(X));
77
| required by this formatting parameter
88
|
99
= help: the trait `Debug` is not implemented for `X`
10-
help: the trait `Debug` is implemented for `S<T>`
10+
help: the trait `Debug` is conditionally implemented for `S<T>`
1111
--> $DIR/redundant-derive-note-on-unimplemented.rs:8:10
1212
|
1313
LL | #[derive(Debug)]
1414
| ^^^^^
15+
LL | struct S<T>(T);
16+
| - unsatisfied trait bound
1517
note: required for `S<X>` to implement `Debug`
1618
--> $DIR/redundant-derive-note-on-unimplemented.rs:9:8
1719
|

tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ LL | want(Some(()));
3939
| required by a bound introduced by this call
4040
|
4141
= help: the trait `Iterator` is not implemented for `()`
42-
help: the trait `T1` is implemented for `Option<It>`
42+
help: the trait `T1` is conditionally implemented for `Option<It>`
4343
--> $DIR/blame-trait-error.rs:21:1
4444
|
4545
LL | impl<It: Iterator> T1 for Option<It> {}
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
| ^^^^^^^^^--------^^^^^^^^^^^^^^^^^^^
47+
| |
48+
| unsatisfied trait bound
4749
note: required for `Option<()>` to implement `T1`
4850
--> $DIR/blame-trait-error.rs:21:20
4951
|

tests/ui/impl-trait/nested_impl_trait.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
5050
| |
5151
| the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
5252
|
53-
help: the trait `Into<U>` is implemented for `T`
53+
help: the trait `Into<U>` is conditionally implemented for `T`
5454
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
55+
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
56+
|
57+
= note: unsatisfied trait bound
5558
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
5659

5760
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
@@ -62,8 +65,11 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
6265
| |
6366
| the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
6467
|
65-
help: the trait `Into<U>` is implemented for `T`
68+
help: the trait `Into<U>` is conditionally implemented for `T`
6669
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
70+
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
71+
|
72+
= note: unsatisfied trait bound
6773
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
6874

6975
error: aborting due to 7 previous errors

tests/ui/traits/copy-bounds-impl-type-params.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
8080
LL | let a = t as Box<dyn Gettable<String>>;
8181
| ^ the trait `Copy` is not implemented for `String`
8282
|
83-
help: the trait `Gettable<T>` is implemented for `S<T>`
83+
help: the trait `Gettable<T>` is conditionally implemented for `S<T>`
8484
--> $DIR/copy-bounds-impl-type-params.rs:14:1
8585
|
8686
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -100,7 +100,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied
100100
LL | let a: Box<dyn Gettable<Foo>> = t;
101101
| ^ the trait `Copy` is not implemented for `Foo`
102102
|
103-
help: the trait `Gettable<T>` is implemented for `S<T>`
103+
help: the trait `Gettable<T>` is conditionally implemented for `S<T>`
104104
--> $DIR/copy-bounds-impl-type-params.rs:14:1
105105
|
106106
LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}

tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ help: the trait `Foo<'_>` is not implemented for `Test`
1111
|
1212
LL | struct Test(i32, i64);
1313
| ^^^^^^^^^^^
14-
help: the trait `Foo<'_>` is implemented for `Test`
14+
help: the trait `Foo<'_>` is conditionally implemented for `Test`
1515
--> $DIR/conditionally-implemented-trait-158423.rs:20:1
1616
|
1717
LL | impl<'a> Foo<'a> for Test where i32: Foo<'a, Assoc = i32>, i64: Foo<'a, Assoc = i64> {
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^
19+
| |
20+
| unsatisfied trait bound
1921
note: required by a bound in `process`
2022
--> $DIR/conditionally-implemented-trait-158423.rs:24:19
2123
|

tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ help: the trait `Trait<_, _, _>` is not implemented for `A<X>`
99
|
1010
LL | struct A<T>(*const T);
1111
| ^^^^^^^^^^^
12-
help: the trait `Trait<U, V, D>` is implemented for `A<T>`
12+
help: the trait `Trait<U, V, D>` is conditionally implemented for `A<T>`
1313
--> $DIR/incompleteness-unstable-result.rs:34:1
1414
|
1515
LL | / impl<T, U, V, D> Trait<U, V, D> for A<T>

tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ help: the trait `Trait<_, _, _>` is not implemented for `A<X>`
99
|
1010
LL | struct A<T>(*const T);
1111
| ^^^^^^^^^^^
12-
help: the trait `Trait<U, V, D>` is implemented for `A<T>`
12+
help: the trait `Trait<U, V, D>` is conditionally implemented for `A<T>`
1313
--> $DIR/incompleteness-unstable-result.rs:34:1
1414
|
1515
LL | / impl<T, U, V, D> Trait<U, V, D> for A<T>

0 commit comments

Comments
 (0)