Skip to content

Commit bc744bc

Browse files
committed
Suggest associated bound restrictions in impls
1 parent 5cc99ee commit bc744bc

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

src/librustc/hir/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,12 @@ impl WhereClause {
669669
Some(self.span)
670670
}
671671
}
672+
673+
/// The `WhereClause` under normal circumstances points at either the predicates or the empty
674+
/// space where the `where` clause should be. Only of use for diagnostic suggestions.
675+
pub fn span_for_predicates_or_empty_place(&self) -> Span {
676+
self.span
677+
}
672678
}
673679

674680
/// A single predicate in a where-clause.

src/librustc/traits/error_reporting.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10441044
}
10451045
return;
10461046
}
1047+
hir::Node::Item(hir::Item {
1048+
kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
1049+
}) if projection.is_some() => {
1050+
err.span_suggestion(
1051+
generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
1052+
"consider further restricting the associated type",
1053+
format!(
1054+
"{} {}", if generics.where_clause.predicates.is_empty() {
1055+
" where"
1056+
} else {
1057+
" ,"
1058+
},
1059+
trait_ref.to_predicate(),
1060+
),
1061+
Applicability::MachineApplicable,
1062+
);
1063+
return;
1064+
}
10471065
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
10481066
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
10491067
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |

src/test/ui/issues/issue-38821.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
22
--> $DIR/issue-38821.rs:23:17
33
|
44
LL | #[derive(Debug, Copy, Clone)]
5-
| ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
5+
| ^^^^- help: consider further restricting the associated type: `, <Col as Expression>::SqlType: NotNull`
6+
| |
7+
| the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
68
|
7-
= help: consider adding a `where <Col as Expression>::SqlType: NotNull` bound
89
= note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType`
910

1011
error: aborting due to previous error
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Running rustfix would cause the same suggestion to be applied multiple times, which results in
2+
// invalid code.
3+
4+
trait Parent {
5+
type Ty;
6+
type Assoc: Child<Self::Ty>;
7+
}
8+
9+
trait Child<T> {}
10+
11+
struct ChildWrapper<T>(T);
12+
13+
impl<A, T> Child<A> for ChildWrapper<T> where T: Child<A> {}
14+
15+
struct ParentWrapper<T>(T);
16+
17+
impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
18+
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
19+
//~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
20+
type Ty = A;
21+
type Assoc = ChildWrapper<T::Assoc>;
22+
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
23+
}
24+
25+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
2+
--> $DIR/missing-assoc-type-bound-restriction.rs:17:1
3+
|
4+
LL | trait Parent {
5+
| ------------ required by `Parent`
6+
...
7+
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
8+
| ^ - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
9+
| _|
10+
| |
11+
LL | |
12+
LL | |
13+
LL | | type Ty = A;
14+
LL | | type Assoc = ChildWrapper<T::Assoc>;
15+
LL | |
16+
LL | | }
17+
| |_^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
18+
19+
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
20+
--> $DIR/missing-assoc-type-bound-restriction.rs:17:28
21+
|
22+
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
23+
| ^^^^^^ - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
24+
| |
25+
| the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
26+
|
27+
= note: required because of the requirements on the impl of `Child<A>` for `ChildWrapper<<T as Parent>::Assoc>`
28+
29+
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
30+
--> $DIR/missing-assoc-type-bound-restriction.rs:21:5
31+
|
32+
LL | trait Parent {
33+
| ------------ required by `Parent`
34+
...
35+
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
36+
| - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
37+
...
38+
LL | type Assoc = ChildWrapper<T::Assoc>;
39+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
40+
41+
error: aborting due to 3 previous errors
42+
43+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)