Skip to content

Commit cecbd76

Browse files
committed
Suggest constraining fn type params when appropriate
1 parent 9fa165d commit cecbd76

File tree

7 files changed

+85
-28
lines changed

7 files changed

+85
-28
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -704,27 +704,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
704704
if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
705705
(self_ty.kind(), parent_pred.kind().skip_binder())
706706
{
707-
if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
708-
let node = def.did.as_local().map(|def_id| {
707+
let node = match p.trait_ref.self_ty().kind() {
708+
ty::Param(_) => {
709+
// Account for `fn` items like in `issue-35677.rs` to
710+
// suggest restricting its type params.
711+
let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
712+
hir_id: self.body_id,
713+
});
714+
Some(
715+
self.tcx
716+
.hir()
717+
.get(self.tcx.hir().local_def_id_to_hir_id(did)),
718+
)
719+
}
720+
ty::Adt(def, _) => def.did.as_local().map(|def_id| {
709721
self.tcx
710722
.hir()
711723
.get(self.tcx.hir().local_def_id_to_hir_id(def_id))
712-
});
713-
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
714-
if let Some(g) = kind.generics() {
715-
let key = match g.where_clause.predicates {
716-
[.., pred] => (pred.span().shrink_to_hi(), false),
717-
[] => (
718-
g.where_clause
719-
.span_for_predicates_or_empty_place(),
720-
true,
721-
),
722-
};
723-
type_params
724-
.entry(key)
725-
.or_insert_with(FxHashSet::default)
726-
.insert(obligation.to_owned());
727-
}
724+
}),
725+
_ => None,
726+
};
727+
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
728+
if let Some(g) = kind.generics() {
729+
let key = match g.where_clause.predicates {
730+
[.., pred] => (pred.span().shrink_to_hi(), false),
731+
[] => (
732+
g.where_clause.span_for_predicates_or_empty_place(),
733+
true,
734+
),
735+
};
736+
type_params
737+
.entry(key)
738+
.or_insert_with(FxHashSet::default)
739+
.insert(obligation.to_owned());
728740
}
729741
}
730742
}
@@ -875,19 +887,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
875887
.iter()
876888
.filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred))
877889
.filter_map(|(pred, parent_pred, _cause)| {
878-
format_pred(*pred).map(|(p, self_ty)| match parent_pred {
879-
None => format!("`{}`", &p),
880-
Some(parent_pred) => match format_pred(*parent_pred) {
890+
format_pred(*pred).map(|(p, self_ty)| {
891+
collect_type_param_suggestions(self_ty, pred, &p);
892+
match parent_pred {
881893
None => format!("`{}`", &p),
882-
Some((parent_p, _)) => {
883-
collect_type_param_suggestions(self_ty, parent_pred, &p);
884-
format!("`{}`\nwhich is required by `{}`", p, parent_p)
885-
}
886-
},
894+
Some(parent_pred) => match format_pred(*parent_pred) {
895+
None => format!("`{}`", &p),
896+
Some((parent_p, _)) => {
897+
collect_type_param_suggestions(
898+
self_ty,
899+
parent_pred,
900+
&p,
901+
);
902+
format!("`{}`\nwhich is required by `{}`", p, parent_p)
903+
}
904+
},
905+
}
887906
})
888907
})
889908
.enumerate()
890909
.collect::<Vec<(usize, String)>>();
910+
891911
for ((span, empty_where), obligations) in type_params.into_iter() {
892912
restrict_type_params = true;
893913
// #74886: Sort here so that the output is always the same.

src/test/ui/issues/issue-35677.fixed

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
use std::collections::HashSet;
4+
use std::hash::Hash;
5+
6+
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
7+
this.is_subset(other)
8+
//~^ ERROR the method
9+
}
10+
11+
fn main() {}

src/test/ui/issues/issue-35677.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
13
use std::collections::HashSet;
4+
use std::hash::Hash;
25

36
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool {
47
this.is_subset(other)

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
error[E0599]: the method `is_subset` exists for reference `&HashSet<T>`, but its trait bounds were not satisfied
2-
--> $DIR/issue-35677.rs:4:10
2+
--> $DIR/issue-35677.rs:7:10
33
|
44
LL | this.is_subset(other)
55
| ^^^^^^^^^ method cannot be called on `&HashSet<T>` due to unsatisfied trait bounds
66
|
77
= note: the following trait bounds were not satisfied:
88
`T: Eq`
99
`T: Hash`
10+
help: consider restricting the type parameters to satisfy the trait bounds
11+
|
12+
LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
13+
| ++++++++++++++++++++
1014

1115
error: aborting due to previous error
1216

src/test/ui/issues/issue-69725.fixed

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// run-rustfix
2+
// aux-build:issue-69725.rs
3+
#![allow(dead_code)]
4+
5+
extern crate issue_69725;
6+
use issue_69725::Struct;
7+
8+
fn crash<A>() where A: Clone {
9+
let _ = Struct::<A>::new().clone();
10+
//~^ ERROR: the method
11+
}
12+
13+
fn main() {}

src/test/ui/issues/issue-69725.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
// run-rustfix
12
// aux-build:issue-69725.rs
3+
#![allow(dead_code)]
24

35
extern crate issue_69725;
46
use issue_69725::Struct;

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0599]: the method `clone` exists for struct `Struct<A>`, but its trait bounds were not satisfied
2-
--> $DIR/issue-69725.rs:7:32
2+
--> $DIR/issue-69725.rs:9:32
33
|
44
LL | let _ = Struct::<A>::new().clone();
55
| ^^^^^ method cannot be called on `Struct<A>` due to unsatisfied trait bounds
@@ -12,6 +12,10 @@ LL | pub struct Struct<A>(A);
1212
= note: the following trait bounds were not satisfied:
1313
`A: Clone`
1414
which is required by `Struct<A>: Clone`
15+
help: consider restricting the type parameter to satisfy the trait bound
16+
|
17+
LL | fn crash<A>() where A: Clone {
18+
| ++++++++++++++
1519

1620
error: aborting due to previous error
1721

0 commit comments

Comments
 (0)