Skip to content

Commit dbd75c8

Browse files
committed
Handle more cases involving impl and trait
1 parent 5b7ffd9 commit dbd75c8

File tree

6 files changed

+101
-78
lines changed

6 files changed

+101
-78
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 80 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -969,90 +969,103 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
969969
trait_ref: &ty::PolyTraitRef<'_>,
970970
body_id: hir::HirId,
971971
) {
972-
let node = self.tcx.hir()
973-
.find(self.tcx.hir().get_parent_item(body_id))
974-
.or_else(|| self.tcx.hir().find(body_id));
975972
debug!(
976-
"suggest_restricting_param_bound node={:?} - trait_ref={:?} ty={:?} ({:?})",
977-
node,
973+
"suggest_restricting_param_bound trait_ref={:?} ty={:?} ({:?})",
978974
trait_ref,
979975
trait_ref.self_ty(),
980976
trait_ref.self_ty().kind,
981977
);
982-
if let ty::Param(param_ty) = &trait_ref.self_ty().kind {
983-
let restrict_msg = "consider further restricting this bound";
984-
let param_name = param_ty.name.as_str();
985-
986-
if let Some(hir::Node::Item(hir::Item {
987-
kind: hir::ItemKind::Struct(_, generics), span, ..
988-
})) |
989-
Some(hir::Node::Item(hir::Item {
990-
kind: hir::ItemKind::Enum(_, generics), span, ..
991-
})) |
992-
Some(hir::Node::Item(hir::Item {
993-
kind: hir::ItemKind::Union(_, generics), span, ..
994-
})) |
995-
Some(hir::Node::Item(hir::Item {
996-
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
997-
})) |
998-
Some(hir::Node::Item(hir::Item {
999-
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
1000-
})) |
1001-
Some(hir::Node::Item(hir::Item {
1002-
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
1003-
})) = &node {
1004-
for param in &generics.params {
1005-
if param_name == param.name.ident().as_str() {
1006-
if param_name.starts_with("impl ") {
1007-
err.span_suggestion(
1008-
param.span,
1009-
restrict_msg,
1010-
// `impl CurrentTrait + MissingTrait`
1011-
format!("{} + {}", param.name.ident(), trait_ref),
1012-
Applicability::MachineApplicable,
1013-
);
1014-
} else {
1015-
if generics.where_clause.predicates.is_empty() &&
1016-
param.bounds.is_empty()
1017-
{
978+
let param_ty = if let ty::Param(param_ty) = &trait_ref.self_ty().kind {
979+
param_ty
980+
} else {
981+
err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate()));
982+
return;
983+
};
984+
985+
let mut hir_id = body_id;
986+
while let Some(node) = self.tcx.hir().find(hir_id) {
987+
debug!("suggest_restricting_param_bound node={:?}", node);
988+
match node {
989+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
990+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
991+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
992+
hir::Node::Item(hir::Item {
993+
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
994+
}) |
995+
hir::Node::Item(hir::Item {
996+
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
997+
}) |
998+
hir::Node::Item(hir::Item {
999+
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
1000+
}) |
1001+
hir::Node::Item(hir::Item {
1002+
kind: hir::ItemKind::TyAlias(_, generics), span, ..
1003+
}) |
1004+
hir::Node::Item(hir::Item {
1005+
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, ..
1006+
}) |
1007+
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
1008+
hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) => {
1009+
let restrict_msg = "consider further restricting this bound";
1010+
let param_name = param_ty.name.as_str();
1011+
for param in &generics.params {
1012+
if param_name == param.name.ident().as_str() {
1013+
if param_name.starts_with("impl ") {
10181014
err.span_suggestion(
10191015
param.span,
1020-
"consider restricting this bound",
1021-
format!("{}", trait_ref.to_predicate()),
1022-
Applicability::MachineApplicable,
1023-
);
1024-
} else if !generics.where_clause.predicates.is_empty() {
1025-
err.span_suggestion(
1026-
generics.where_clause.span().unwrap().shrink_to_hi(),
1027-
&format!(
1028-
"consider further restricting type parameter `{}`",
1029-
param_ty,
1030-
),
1031-
format!(", {}", trait_ref.to_predicate()),
1016+
restrict_msg,
1017+
// `impl CurrentTrait + MissingTrait`
1018+
format!("{} + {}", param.name.ident(), trait_ref),
10321019
Applicability::MachineApplicable,
10331020
);
10341021
} else {
1035-
let sp = param.span.with_hi(span.hi());
1036-
let span = self.tcx.sess.source_map().span_through_char(sp, ':');
1037-
if sp != param.span && sp != span {
1038-
// Only suggest if we have high certainty that the span covers
1039-
// the colon in `foo<T: Trait>`.
1040-
err.span_suggestion(span, restrict_msg, format!(
1041-
"{} + ",
1042-
trait_ref.to_predicate(),
1043-
), Applicability::MachineApplicable);
1022+
if generics.where_clause.predicates.is_empty() &&
1023+
param.bounds.is_empty()
1024+
{
1025+
err.span_suggestion(
1026+
param.span,
1027+
"consider restricting this bound",
1028+
format!("{}", trait_ref.to_predicate()),
1029+
Applicability::MachineApplicable,
1030+
);
1031+
} else if !generics.where_clause.predicates.is_empty() {
1032+
err.span_suggestion(
1033+
generics.where_clause.span().unwrap().shrink_to_hi(),
1034+
&format!(
1035+
"consider further restricting type parameter `{}`",
1036+
param_ty,
1037+
),
1038+
format!(", {}", trait_ref.to_predicate()),
1039+
Applicability::MachineApplicable,
1040+
);
10441041
} else {
1045-
err.span_label(param.span, &format!(
1046-
"consider adding a `where {}` bound",
1047-
trait_ref.to_predicate(),
1048-
));
1042+
let sp = param.span.with_hi(span.hi());
1043+
let span = self.tcx.sess.source_map()
1044+
.span_through_char(sp, ':');
1045+
if sp != param.span && sp != span {
1046+
// Only suggest if we have high certainty that the span
1047+
// covers the colon in `foo<T: Trait>`.
1048+
err.span_suggestion(span, restrict_msg, format!(
1049+
"{} + ",
1050+
trait_ref.to_predicate(),
1051+
), Applicability::MachineApplicable);
1052+
} else {
1053+
err.span_label(param.span, &format!(
1054+
"consider adding a `where {}` bound",
1055+
trait_ref.to_predicate(),
1056+
));
1057+
}
10491058
}
10501059
}
1060+
return;
10511061
}
1052-
return;
10531062
}
10541063
}
1064+
hir::Node::Crate => return,
1065+
_ => {}
10551066
}
1067+
1068+
hir_id = self.tcx.hir().get_parent_item(hir_id);
10561069
}
10571070
// FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`.
10581071

src/test/ui/associated-types/associated-types-no-suitable-bound.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `T: Get` is not satisfied
22
--> $DIR/associated-types-no-suitable-bound.rs:11:5
33
|
44
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
6-
|
7-
= help: consider adding a `where T: Get` bound
5+
| ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
| | |
7+
| | help: consider restricting this bound: `T: Get`
8+
| the trait `Get` is not implemented for `T`
89

910
error: aborting due to previous error
1011

src/test/ui/consts/too_generic_eval_ice.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,30 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
1616
|
1717
LL | pub struct Foo<A, B>(A, B);
1818
| --------------------------- required by `Foo`
19+
LL |
20+
LL | impl<A, B> Foo<A, B> {
21+
| - help: consider restricting this bound: `A: std::marker::Sized`
1922
...
2023
LL | [5; Self::HOST_SIZE] == [6; 0]
2124
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
2225
|
2326
= help: the trait `std::marker::Sized` is not implemented for `A`
2427
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
25-
= help: consider adding a `where A: std::marker::Sized` bound
2628

2729
error[E0277]: the size for values of type `B` cannot be known at compilation time
2830
--> $DIR/too_generic_eval_ice.rs:7:13
2931
|
3032
LL | pub struct Foo<A, B>(A, B);
3133
| --------------------------- required by `Foo`
34+
LL |
35+
LL | impl<A, B> Foo<A, B> {
36+
| - help: consider restricting this bound: `B: std::marker::Sized`
3237
...
3338
LL | [5; Self::HOST_SIZE] == [6; 0]
3439
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
3540
|
3641
= help: the trait `std::marker::Sized` is not implemented for `B`
3742
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
38-
= help: consider adding a `where B: std::marker::Sized` bound
3943

4044
error: aborting due to 3 previous errors
4145

src/test/ui/impl-trait/issue-55872-1.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)`
22
--> $DIR/issue-55872-1.rs:12:5
33
|
4+
LL | impl<S: Default> Bar for S {
5+
| -- help: consider further restricting this bound: `S: std::marker::Copy +`
46
LL | type E = impl Copy;
57
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
68
|
7-
= help: consider adding a `where S: std::marker::Copy` bound
89
= note: required because it appears within the type `(S, T)`
910
= note: the return type of a function must have a statically known size
1011

@@ -13,8 +14,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T)
1314
|
1415
LL | type E = impl Copy;
1516
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
17+
...
18+
LL | fn foo<T: Default>() -> Self::E {
19+
| -- help: consider further restricting this bound: `T: std::marker::Copy +`
1620
|
17-
= help: consider adding a `where T: std::marker::Copy` bound
1821
= note: required because it appears within the type `(S, T)`
1922
= note: the return type of a function must have a statically known size
2023

src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
44
LL | fn require_copy<T: Copy>(x: T) {}
55
| ------------ ---- required by this bound in `require_copy`
66
...
7+
LL | impl<T> Foo<T> {
8+
| - help: consider restricting this bound: `T: std::marker::Copy`
9+
...
710
LL | require_copy(self.x);
811
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
9-
|
10-
= help: consider adding a `where T: std::marker::Copy` bound
1112

1213
error: aborting due to previous error
1314

src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
44
LL | fn require_copy<T: Copy>(x: T) {}
55
| ------------ ---- required by this bound in `require_copy`
66
...
7+
LL | impl<T> Foo<T> for Bar<T> {
8+
| - help: consider restricting this bound: `T: std::marker::Copy`
9+
...
710
LL | require_copy(self.x);
811
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
9-
|
10-
= help: consider adding a `where T: std::marker::Copy` bound
1112

1213
error: aborting due to previous error
1314

0 commit comments

Comments
 (0)