X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_hir_typeck%2Fsrc%2Ffn_ctxt%2Fsuggestions.rs;h=407d6ac8544c211a8cce00fa74b0cfb983bddbea;hb=39b2a41b39b445bf7efab02f6eade16135d7df85;hp=4f92477b5d87ef221239c71054742025efb7bf32;hpb=91b8f34ac2272e3c94a97bebc033abe8e2f17101;p=rust.git diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 4f92477b5d8..407d6ac8544 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -13,7 +13,9 @@ use rustc_infer::infer; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty}; +use rustc_middle::ty::{ + self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty, +}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::symbol::sym; use rustc_span::Span; @@ -174,10 +176,10 @@ pub(in super::super) fn extract_callable_info( let fn_sig = substs.as_closure().sig(); Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..]))) } - ty::Opaque(def_id, substs) => { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() + && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() // args tuple will always be substs[1] && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() { @@ -194,7 +196,7 @@ pub(in super::super) fn extract_callable_info( ty::Dynamic(data, _, ty::Dyn) => { data.iter().find_map(|pred| { if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() - && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output() + && Some(proj.def_id) == self.tcx.lang_items().fn_once_output() // for existential projection, substs are shifted over by 1 && let ty::Tuple(args) = proj.substs.type_at(0).kind() { @@ -212,7 +214,7 @@ pub(in super::super) fn extract_callable_info( let def_id = self.tcx.generics_of(self.body_id.owner).type_param(¶m, self.tcx).def_id; self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| { if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() + && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() && proj.projection_ty.self_ty() == found // args tuple will always be substs[1] && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() @@ -1276,18 +1278,14 @@ pub(crate) fn note_type_is_not_clone( && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..))) // Check that we're in fact trying to clone into the expected type && self.can_coerce(*pointee_ty, expected_ty) + && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty])) // And the expected type doesn't implement `Clone` - && !self.predicate_must_hold_considering_regions(&traits::Obligation { - cause: traits::ObligationCause::dummy(), - param_env: self.param_env, - recursion_depth: 0, - predicate: ty::Binder::dummy(ty::TraitRef { - def_id: clone_trait_did, - substs: self.tcx.mk_substs([expected_ty.into()].iter()), - }) - .without_const() - .to_predicate(self.tcx), - }) + && !self.predicate_must_hold_considering_regions(&traits::Obligation::new( + self.tcx, + traits::ObligationCause::dummy(), + self.param_env, + trait_ref, + )) { diag.span_note( callee_expr.span, @@ -1295,6 +1293,19 @@ pub(crate) fn note_type_is_not_clone( "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead" ), ); + let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id); + if let ty::Param(param) = expected_ty.kind() + && let Some(generics) = self.tcx.hir().get_generics(owner) + { + suggest_constraining_type_params( + self.tcx, + generics, + diag, + vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(), + ); + } else { + self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]); + } } }