diff options
| author | Esteban Kuber <esteban@kuber.com.ar> | 2021-10-13 16:07:22 +0000 |
|---|---|---|
| committer | Esteban Kuber <esteban@kuber.com.ar> | 2021-11-20 19:19:34 +0000 |
| commit | cecbd7657a80a824bdcf60fb43acc7af000ac2c1 (patch) | |
| tree | 5bf2d8aff434a406360d36494e14e8faea8673b9 | |
| parent | 9fa165d11b5eeedcf6e04f4812704d7fccf60ed6 (diff) | |
| download | rust-cecbd7657a80a824bdcf60fb43acc7af000ac2c1.tar.gz rust-cecbd7657a80a824bdcf60fb43acc7af000ac2c1.zip | |
Suggest constraining `fn` type params when appropriate
| -rw-r--r-- | compiler/rustc_typeck/src/check/method/suggest.rs | 72 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-35677.fixed | 11 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-35677.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-35677.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-69725.fixed | 13 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-69725.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-69725.stderr | 6 |
7 files changed, 85 insertions, 28 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b4508368e26..ca174ed5e84 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -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. diff --git a/src/test/ui/issues/issue-35677.fixed b/src/test/ui/issues/issue-35677.fixed new file mode 100644 index 00000000000..08174d8d8d5 --- /dev/null +++ b/src/test/ui/issues/issue-35677.fixed @@ -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() {} diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs index 15d13979062..2cb394386b8 100644 --- a/src/test/ui/issues/issue-35677.rs +++ b/src/test/ui/issues/issue-35677.rs @@ -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) diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index ab59e5d1acf..a2201b946a6 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -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 diff --git a/src/test/ui/issues/issue-69725.fixed b/src/test/ui/issues/issue-69725.fixed new file mode 100644 index 00000000000..d57badcfd8c --- /dev/null +++ b/src/test/ui/issues/issue-69725.fixed @@ -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() {} diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs index 7c77293945e..9c88969c5cf 100644 --- a/src/test/ui/issues/issue-69725.rs +++ b/src/test/ui/issues/issue-69725.rs @@ -1,4 +1,6 @@ +// run-rustfix // aux-build:issue-69725.rs +#![allow(dead_code)] extern crate issue_69725; use issue_69725::Struct; diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr index b1ba89f6cbe..6395bca300c 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/issues/issue-69725.stderr @@ -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 |
