Suggest constraining fn type params when appropriate
This commit is contained in:
parent
9fa165d11b
commit
cecbd7657a
7 changed files with 85 additions and 28 deletions
|
|
@ -704,27 +704,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
|
||||
(self_ty.kind(), parent_pred.kind().skip_binder())
|
||||
{
|
||||
if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
|
||||
let node = def.did.as_local().map(|def_id| {
|
||||
let node = match p.trait_ref.self_ty().kind() {
|
||||
ty::Param(_) => {
|
||||
// Account for `fn` items like in `issue-35677.rs` to
|
||||
// suggest restricting its type params.
|
||||
let did = self.tcx.hir().body_owner_def_id(hir::BodyId {
|
||||
hir_id: self.body_id,
|
||||
});
|
||||
Some(
|
||||
self.tcx
|
||||
.hir()
|
||||
.get(self.tcx.hir().local_def_id_to_hir_id(did)),
|
||||
)
|
||||
}
|
||||
ty::Adt(def, _) => def.did.as_local().map(|def_id| {
|
||||
self.tcx
|
||||
.hir()
|
||||
.get(self.tcx.hir().local_def_id_to_hir_id(def_id))
|
||||
});
|
||||
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
|
||||
if let Some(g) = kind.generics() {
|
||||
let key = match g.where_clause.predicates {
|
||||
[.., pred] => (pred.span().shrink_to_hi(), false),
|
||||
[] => (
|
||||
g.where_clause
|
||||
.span_for_predicates_or_empty_place(),
|
||||
true,
|
||||
),
|
||||
};
|
||||
type_params
|
||||
.entry(key)
|
||||
.or_insert_with(FxHashSet::default)
|
||||
.insert(obligation.to_owned());
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
|
||||
if let Some(g) = kind.generics() {
|
||||
let key = match g.where_clause.predicates {
|
||||
[.., pred] => (pred.span().shrink_to_hi(), false),
|
||||
[] => (
|
||||
g.where_clause.span_for_predicates_or_empty_place(),
|
||||
true,
|
||||
),
|
||||
};
|
||||
type_params
|
||||
.entry(key)
|
||||
.or_insert_with(FxHashSet::default)
|
||||
.insert(obligation.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -875,19 +887,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.iter()
|
||||
.filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred))
|
||||
.filter_map(|(pred, parent_pred, _cause)| {
|
||||
format_pred(*pred).map(|(p, self_ty)| match parent_pred {
|
||||
None => format!("`{}`", &p),
|
||||
Some(parent_pred) => match format_pred(*parent_pred) {
|
||||
format_pred(*pred).map(|(p, self_ty)| {
|
||||
collect_type_param_suggestions(self_ty, pred, &p);
|
||||
match parent_pred {
|
||||
None => format!("`{}`", &p),
|
||||
Some((parent_p, _)) => {
|
||||
collect_type_param_suggestions(self_ty, parent_pred, &p);
|
||||
format!("`{}`\nwhich is required by `{}`", p, parent_p)
|
||||
}
|
||||
},
|
||||
Some(parent_pred) => match format_pred(*parent_pred) {
|
||||
None => format!("`{}`", &p),
|
||||
Some((parent_p, _)) => {
|
||||
collect_type_param_suggestions(
|
||||
self_ty,
|
||||
parent_pred,
|
||||
&p,
|
||||
);
|
||||
format!("`{}`\nwhich is required by `{}`", p, parent_p)
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
.enumerate()
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
for ((span, empty_where), obligations) in type_params.into_iter() {
|
||||
restrict_type_params = true;
|
||||
// #74886: Sort here so that the output is always the same.
|
||||
|
|
|
|||
11
src/test/ui/issues/issue-35677.fixed
Normal file
11
src/test/ui/issues/issue-35677.fixed
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code)]
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
|
||||
this.is_subset(other)
|
||||
//~^ ERROR the method
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code)]
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool {
|
||||
this.is_subset(other)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0599]: the method `is_subset` exists for reference `&HashSet<T>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-35677.rs:4:10
|
||||
--> $DIR/issue-35677.rs:7:10
|
||||
|
|
||||
LL | this.is_subset(other)
|
||||
| ^^^^^^^^^ method cannot be called on `&HashSet<T>` due to unsatisfied trait bounds
|
||||
|
|
@ -7,6 +7,10 @@ LL | this.is_subset(other)
|
|||
= note: the following trait bounds were not satisfied:
|
||||
`T: Eq`
|
||||
`T: Hash`
|
||||
help: consider restricting the type parameters to satisfy the trait bounds
|
||||
|
|
||||
LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
13
src/test/ui/issues/issue-69725.fixed
Normal file
13
src/test/ui/issues/issue-69725.fixed
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// run-rustfix
|
||||
// aux-build:issue-69725.rs
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate issue_69725;
|
||||
use issue_69725::Struct;
|
||||
|
||||
fn crash<A>() where A: Clone {
|
||||
let _ = Struct::<A>::new().clone();
|
||||
//~^ ERROR: the method
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
// run-rustfix
|
||||
// aux-build:issue-69725.rs
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate issue_69725;
|
||||
use issue_69725::Struct;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0599]: the method `clone` exists for struct `Struct<A>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-69725.rs:7:32
|
||||
--> $DIR/issue-69725.rs:9:32
|
||||
|
|
||||
LL | let _ = Struct::<A>::new().clone();
|
||||
| ^^^^^ method cannot be called on `Struct<A>` due to unsatisfied trait bounds
|
||||
|
|
@ -12,6 +12,10 @@ LL | pub struct Struct<A>(A);
|
|||
= note: the following trait bounds were not satisfied:
|
||||
`A: Clone`
|
||||
which is required by `Struct<A>: Clone`
|
||||
help: consider restricting the type parameter to satisfy the trait bound
|
||||
|
|
||||
LL | fn crash<A>() where A: Clone {
|
||||
| ++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue