Skip to content

Commit ab7d8f0

Browse files
committed
Deduplicate some code and apply review comments
1 parent bc744bc commit ab7d8f0

14 files changed

+117
-125
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 93 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -984,84 +984,66 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
984984
}
985985
};
986986

987+
let mut suggest_restriction = |generics: &hir::Generics, msg| {
988+
err.span_suggestion(
989+
generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
990+
&format!("consider further restricting {}", msg),
991+
format!(
992+
"{} {} ",
993+
if !generics.where_clause.predicates.is_empty() {
994+
","
995+
} else {
996+
" where"
997+
},
998+
trait_ref.to_predicate(),
999+
),
1000+
Applicability::MachineApplicable,
1001+
);
1002+
};
1003+
1004+
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
1005+
// don't suggest `T: Sized + ?Sized`.
9871006
let mut hir_id = body_id;
9881007
while let Some(node) = self.tcx.hir().find(hir_id) {
989-
debug!("suggest_restricting_param_bound node={:?}", node);
9901008
match node {
9911009
hir::Node::Item(hir::Item {
992-
kind: hir::ItemKind::Fn(decl, _, generics, _), ..
1010+
kind: hir::ItemKind::Fn(_, _, generics, _), ..
9931011
}) |
9941012
hir::Node::TraitItem(hir::TraitItem {
9951013
generics,
996-
kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1014+
kind: hir::TraitItemKind::Method(..), ..
9971015
}) |
9981016
hir::Node::ImplItem(hir::ImplItem {
9991017
generics,
1000-
kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1001-
}) if param_ty.map(|p| p.name.as_str() == "Self").unwrap_or(false) => {
1002-
if !generics.where_clause.predicates.is_empty() {
1003-
err.span_suggestion(
1004-
generics.where_clause.span().unwrap().shrink_to_hi(),
1005-
"consider further restricting `Self`",
1006-
format!(", {}", trait_ref.to_predicate()),
1007-
Applicability::MachineApplicable,
1008-
);
1009-
} else {
1010-
err.span_suggestion(
1011-
decl.output.span().shrink_to_hi(),
1012-
"consider further restricting `Self`",
1013-
format!(" where {}", trait_ref.to_predicate()),
1014-
Applicability::MachineApplicable,
1015-
);
1016-
}
1018+
kind: hir::ImplItemKind::Method(..), ..
1019+
}) if param_ty.map_or(false, |p| p.name.as_str() == "Self") => {
1020+
// Restricting `Self` for a single method.
1021+
suggest_restriction(&generics, "`Self`");
10171022
return;
10181023
}
1024+
10191025
hir::Node::Item(hir::Item {
1020-
kind: hir::ItemKind::Fn(decl, _, generics, _), ..
1026+
kind: hir::ItemKind::Fn(_, _, generics, _), ..
10211027
}) |
10221028
hir::Node::TraitItem(hir::TraitItem {
10231029
generics,
1024-
kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1030+
kind: hir::TraitItemKind::Method(..), ..
10251031
}) |
10261032
hir::Node::ImplItem(hir::ImplItem {
10271033
generics,
1028-
kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), ..
1029-
}) if projection.is_some() => {
1030-
if !generics.where_clause.predicates.is_empty() {
1031-
err.span_suggestion(
1032-
generics.where_clause.span().unwrap().shrink_to_hi(),
1033-
"consider further restricting the associated type",
1034-
format!(", {}", trait_ref.to_predicate()),
1035-
Applicability::MachineApplicable,
1036-
);
1037-
} else {
1038-
err.span_suggestion(
1039-
decl.output.span().shrink_to_hi(),
1040-
"consider further restricting the associated type",
1041-
format!(" where {}", trait_ref.to_predicate()),
1042-
Applicability::MachineApplicable,
1043-
);
1044-
}
1045-
return;
1046-
}
1034+
kind: hir::ImplItemKind::Method(..), ..
1035+
}) |
1036+
hir::Node::Item(hir::Item {
1037+
kind: hir::ItemKind::Trait(_, _, generics, _, _), ..
1038+
}) |
10471039
hir::Node::Item(hir::Item {
10481040
kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
10491041
}) 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-
);
1042+
// Missing associated type bound.
1043+
suggest_restriction(&generics, "the associated type");
10631044
return;
10641045
}
1046+
10651047
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
10661048
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
10671049
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
@@ -1086,73 +1068,82 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10861068
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
10871069
hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
10881070
if param_ty.is_some() => {
1071+
// Missing generic type parameter bound.
10891072
let restrict_msg = "consider further restricting this bound";
10901073
let param_name = param_ty.unwrap().name.as_str();
1091-
for param in &generics.params {
1092-
if param_name == param.name.ident().as_str() {
1093-
if param_name.starts_with("impl ") {
1074+
for param in generics.params.iter().filter(|p| {
1075+
param_name == p.name.ident().as_str()
1076+
}) {
1077+
if param_name.starts_with("impl ") {
1078+
// `impl Trait` in argument:
1079+
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
1080+
err.span_suggestion(
1081+
param.span,
1082+
restrict_msg,
1083+
// `impl CurrentTrait + MissingTrait`
1084+
format!("{} + {}", param.name.ident(), trait_ref),
1085+
Applicability::MachineApplicable,
1086+
);
1087+
} else {
1088+
if generics.where_clause.predicates.is_empty() &&
1089+
param.bounds.is_empty()
1090+
{
1091+
// If there are no bounds whatsoever, suggest adding a constraint
1092+
// to the type parameter:
1093+
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
10941094
err.span_suggestion(
10951095
param.span,
1096-
restrict_msg,
1097-
// `impl CurrentTrait + MissingTrait`
1098-
format!("{} + {}", param.name.ident(), trait_ref),
1096+
"consider restricting this bound",
1097+
format!("{}", trait_ref.to_predicate()),
1098+
Applicability::MachineApplicable,
1099+
);
1100+
} else if !generics.where_clause.predicates.is_empty() {
1101+
// There is a `where` clause, so suggest expanding it:
1102+
// `fn foo<T>(t: T) where T: Debug {}` →
1103+
// `fn foo<T(t: T) where T: Debug, Trait {}`
1104+
err.span_suggestion(
1105+
generics.where_clause.span().unwrap().shrink_to_hi(),
1106+
&format!(
1107+
"consider further restricting type parameter `{}`",
1108+
param_name,
1109+
),
1110+
format!(", {}", trait_ref.to_predicate()),
10991111
Applicability::MachineApplicable,
11001112
);
11011113
} else {
1102-
if generics.where_clause.predicates.is_empty() &&
1103-
param.bounds.is_empty()
1104-
{
1105-
err.span_suggestion(
1106-
param.span,
1107-
"consider restricting this bound",
1108-
format!("{}", trait_ref.to_predicate()),
1109-
Applicability::MachineApplicable,
1110-
);
1111-
} else if !generics.where_clause.predicates.is_empty() {
1112-
err.span_suggestion(
1113-
generics.where_clause.span().unwrap().shrink_to_hi(),
1114-
&format!(
1115-
"consider further restricting type parameter `{}`",
1116-
param_name,
1117-
),
1118-
format!(", {}", trait_ref.to_predicate()),
1119-
Applicability::MachineApplicable,
1120-
);
1114+
// If there is no `where` clause lean towards constraining to the
1115+
// type parameter:
1116+
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
1117+
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
1118+
let sp = param.span.with_hi(span.hi());
1119+
let span = self.tcx.sess.source_map()
1120+
.span_through_char(sp, ':');
1121+
if sp != param.span && sp != span {
1122+
// Only suggest if we have high certainty that the span
1123+
// covers the colon in `foo<T: Trait>`.
1124+
err.span_suggestion(span, restrict_msg, format!(
1125+
"{} + ",
1126+
trait_ref.to_predicate(),
1127+
), Applicability::MachineApplicable);
11211128
} else {
1122-
let sp = param.span.with_hi(span.hi());
1123-
let span = self.tcx.sess.source_map()
1124-
.span_through_char(sp, ':');
1125-
if sp != param.span && sp != span {
1126-
// Only suggest if we have high certainty that the span
1127-
// covers the colon in `foo<T: Trait>`.
1128-
err.span_suggestion(span, restrict_msg, format!(
1129-
"{} + ",
1130-
trait_ref.to_predicate(),
1131-
), Applicability::MachineApplicable);
1132-
} else {
1133-
err.span_label(param.span, &format!(
1134-
"consider adding a `where {}` bound",
1135-
trait_ref.to_predicate(),
1136-
));
1137-
}
1129+
err.span_label(param.span, &format!(
1130+
"consider adding a `where {}` bound",
1131+
trait_ref.to_predicate(),
1132+
));
11381133
}
11391134
}
1140-
return;
11411135
}
1136+
return;
11421137
}
11431138
}
1139+
11441140
hir::Node::Crate => return,
1141+
11451142
_ => {}
11461143
}
11471144

11481145
hir_id = self.tcx.hir().get_parent_item(hir_id);
11491146
}
1150-
// FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`.
1151-
1152-
// Fallback in case we didn't find the type argument. Can happen on associated types
1153-
// bounds and when `Self` needs to be restricted, like in the ui test
1154-
// `associated-types-projection-to-unrelated-trait-in-method-without-default.rs`.
1155-
err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate()));
11561147
}
11571148

11581149
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a

src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` is not an iterato
1010
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
1111
|
1212
LL | fn assume_case1<T: Case1>() {
13-
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator`
13+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator`
1414
| _|
1515
| |
1616
LL | |
@@ -30,7 +30,7 @@ LL | trait Case1 {
3030
| ----------- required by `Case1`
3131
...
3232
LL | fn assume_case1<T: Case1>() {
33-
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send`
33+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send`
3434
| _|
3535
| |
3636
LL | |
@@ -50,7 +50,7 @@ LL | trait Case1 {
5050
| ----------- required by `Case1`
5151
...
5252
LL | fn assume_case1<T: Case1>() {
53-
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync`
53+
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync`
5454
| _|
5555
| |
5656
LL | |

src/test/ui/associated-types/associated-types-bound-failure.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub trait GetToInt
1414
}
1515

1616
fn foo<G>(g: G) -> isize
17-
where G : GetToInt, <G as GetToInt>::R: ToInt
17+
where G : GetToInt, <G as GetToInt>::R: ToInt
1818
{
1919
ToInt::to_int(&g.get()) //~ ERROR E0277
2020
}

src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Get {
77
}
88

99
trait Other {
10-
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get{}
10+
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {}
1111
//~^ ERROR the trait bound `Self: Get` is not satisfied
1212
}
1313

src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
22
--> $DIR/associated-types-for-unimpl-trait.rs:10:5
33
|
44
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
6-
| | |
7-
| | help: consider further restricting `Self`: `where Self: Get`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
6+
| | |
7+
| | help: consider further restricting `Self`: `where Self: Get`
88
| the trait `Get` is not implemented for `Self`
99

1010
error: aborting due to previous error

src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
22
--> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
33
|
44
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
6-
| | |
7-
| | help: consider further restricting `Self`: `where Self: Get`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
6+
| | |
7+
| | help: consider further restricting `Self`: `where Self: Get`
88
| the trait `Get` is not implemented for `Self`
99

1010
error: aborting due to previous error

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
22
--> $DIR/associated-types-no-suitable-supertrait.rs:17:5
33
|
44
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
6-
| | |
7-
| | help: consider further restricting `Self`: `where Self: Get`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
6+
| | |
7+
| | help: consider further restricting `Self`: `where Self: Get`
88
| the trait `Get` is not implemented for `Self`
99

1010
error[E0277]: the trait bound `(T, U): Get` is not satisfied

src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Get {
77
}
88

99
trait Other {
10-
fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get;
10+
fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get ;
1111
//~^ ERROR E0277
1212
}
1313

src/test/ui/associated-types/associated-types-unsized.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ trait Get {
66
fn get(&self) -> <Self as Get>::Value;
77
}
88

9-
fn foo<T:Get>(t: T) where <T as Get>::Value: std::marker::Sized{
9+
fn foo<T:Get>(t: T) where <T as Get>::Value: std::marker::Sized {
1010
let x = t.get(); //~ ERROR the size for values of type
1111
}
1212

src/test/ui/associated-types/associated-types-unsized.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: the size for values of type `<T as Get>::Value` cannot be known at
22
--> $DIR/associated-types-unsized.rs:10:9
33
|
44
LL | fn foo<T:Get>(t: T) {
5-
| - help: consider further restricting the associated type: `where <T as Get>::Value: std::marker::Sized`
5+
| - help: consider further restricting the associated type: `where <T as Get>::Value: std::marker::Sized`
66
LL | let x = t.get();
77
| ^ doesn't have a size known at compile-time
88
|

src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Trait {
77
type AssocType;
88
fn dummy(&self) { }
99
}
10-
fn bar<T:Trait+Send>() where <T as Trait>::AssocType: std::marker::Send{
10+
fn bar<T:Trait+Send>() where <T as Trait>::AssocType: std::marker::Send {
1111
is_send::<T::AssocType>(); //~ ERROR E0277
1212
}
1313

0 commit comments

Comments
 (0)