diff options
| author | bors <bors@rust-lang.org> | 2023-01-09 05:09:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-09 05:09:45 +0000 |
| commit | 2e677c0645862d17a12c6d04b3019203c8e23fcc (patch) | |
| tree | 70970b8d512c1f88c62d13cfbec27794a1879f02 /compiler/rustc_trait_selection/src | |
| parent | a377893da2cd7124e5a18c7116cbb70e16dd5541 (diff) | |
| parent | 5e8e97f98115191bca09600491d3687e9cf2e8fb (diff) | |
| download | rust-2e677c0645862d17a12c6d04b3019203c8e23fcc.tar.gz rust-2e677c0645862d17a12c6d04b3019203c8e23fcc.zip | |
Auto merge of #106616 - compiler-errors:rollup-emcj0o3, r=compiler-errors
Rollup of 8 pull requests Successful merges: - #104163 (Don't derive Debug for `OnceWith` & `RepeatWith`) - #106131 (Mention "signature" rather than "fn pointer" when impl/trait methods are incompatible) - #106363 (Structured suggestion for `&mut dyn Iterator` when possible) - #106497 (Suggest using clone when we have &T and T implemented Clone) - #106584 (Document that `Vec::from_raw_parts[_in]` must be given a pointer from the correct allocator.) - #106600 (Suppress type errors that come from private fields) - #106602 (Add goml scripts to tidy checks) - #106606 (Do not emit structured suggestion for turbofish with wrong span) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 58 |
2 files changed, 62 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 17331a50105..9c098e1a2fc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -873,6 +873,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } + if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { + err.emit(); + return; + } + if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) { err.emit(); return; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 28f76b14146..c52365ae3b7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -10,7 +10,7 @@ use crate::infer::InferCtxt; use crate::traits::{NormalizeExt, ObligationCtxt}; use hir::def::CtorOf; -use hir::HirId; +use hir::{Expr, HirId}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ @@ -206,6 +206,13 @@ pub trait TypeErrCtxtExt<'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ); + fn suggest_add_clone_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool; + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, @@ -1102,6 +1109,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + fn suggest_add_clone_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); + let ty = self.tcx.erase_late_bound_regions(self_ty); + let owner = self.tcx.hir().get_parent_item(obligation.cause.body_id); + let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false }; + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; + let ty::Param(param) = inner_ty.kind() else { return false }; + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false }; + let arg_node = self.tcx.hir().get(*arg_hir_id); + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false }; + + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = |ty| { + self.type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions() + }; + + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), + ); + + if self.predicate_may_hold(&new_obligation) && has_clone(ty) { + if !has_clone(param.to_ty(self.tcx)) { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait), + ); + } + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, + ); + return true; + } + false + } + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, |
