From 7383a6196847fbf2d233ad252af2c3a555f0be9e Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 30 Jul 2021 08:56:45 +0000 Subject: [PATCH 1/5] add eq constraints on associated constants --- clippy_utils/src/ast_utils.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 3d3180521ab7a..d4f037677e089 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -645,12 +645,13 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } -pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool { - use AssocTyConstraintKind::*; +pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { + use AssocConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r), (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound), + (ConstEquality { c: l }, ConstEquality { c: r }) => eq_anon_const(l, r), _ => false, } } From 05b8c727d87bfca6b3adde3fd814a748154d123d Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 7 Jan 2022 03:58:32 +0000 Subject: [PATCH 2/5] Add term Instead of having a separate enum variant for types and consts have one but have either a const or type. --- clippy_utils/src/ast_utils.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index d4f037677e089..604c95d2bc81f 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -645,13 +645,20 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } +fn eq_term(l: &Term, r: &Term) -> bool { + match (l, r) { + (Term::Ty(l), Term::Ty(r)) => eq_ty(l,r), + (Term::Const(l), Term::Const(r)) => eq_anon_const(l,r), + _ => false, + } +} + pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { use AssocConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { - (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r), + (Equality { term: l }, Equality { term: r }) => eq_term(l, r), (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound), - (ConstEquality { c: l }, ConstEquality { c: r }) => eq_anon_const(l, r), _ => false, } } From 9fb0bff18e6de75328b1bdb63c0ab29e2e413b68 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 8 Jan 2022 09:28:12 +0000 Subject: [PATCH 3/5] Use Term in ProjectionPredicate ProjectionPredicate should be able to handle both associated types and consts so this adds the first step of that. It mainly just pipes types all the way down, not entirely sure how to handle consts, but hopefully that'll come with time. --- clippy_lints/src/manual_async_fn.rs | 4 ++-- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- clippy_lints/src/unit_return_expecting_ord.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index 86819752f90ff..2af3555e370a4 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId, + Term, AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId, IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; @@ -140,7 +140,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t if args.bindings.len() == 1; let binding = &args.bindings[0]; if binding.ident.name == sym::Output; - if let TypeBindingKind::Equality{ty: output} = binding.kind; + if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind; then { return Some(output) } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ed5136e7d00ff..c0e65e520f23a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2143,10 +2143,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(projection_predicate.ty, self_adt) { + if contains_adt_constructor(projection_predicate.term.ty(), self_adt) { return; } - } else if contains_ty(projection_predicate.ty, self_ty) { + } else if contains_ty(projection_predicate.term.ty(), self_ty) { return; } } diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index e5b6d296b2d25..865a36a5cd1d6 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -243,7 +243,7 @@ fn check_other_call_arg<'tcx>( if if trait_predicate.def_id() == deref_trait_id { if let [projection_predicate] = projection_predicates[..] { let normalized_ty = - cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty); + cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty()); implements_trait(cx, receiver_ty, deref_trait_id, &[]) && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty) } else { diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index fe35ff33d35a4..09f9e1ee09990 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -98,9 +98,9 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve if trait_pred.self_ty() == inp; if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); then { - if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) { + if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) { args_to_check.push((i, "Ord".to_string())); - } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) { + } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) { args_to_check.push((i, "PartialOrd".to_string())); } } From a783912d2c48d2758c14db11d97fcbeca6e099a0 Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 10 Jan 2022 23:39:21 +0000 Subject: [PATCH 4/5] Update term for use in more places Replace use of `ty()` on term and use it in more places. This will allow more flexibility in the future, but slightly worried it allows items which are consts which only accept types. --- clippy_lints/src/methods/mod.rs | 8 ++++++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 5 +++-- clippy_lints/src/unit_return_expecting_ord.rs | 5 +++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index c0e65e520f23a..ca8bbbd8f9169 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2141,12 +2141,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // one of the associated types must be Self for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { + let assoc_ty = match projection_predicate.term { + ty::Term::Ty(ty) => ty, + ty::Term::Const(c) => c.ty, + }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(projection_predicate.term.ty(), self_adt) { + if contains_adt_constructor(assoc_ty, self_adt) { return; } - } else if contains_ty(projection_predicate.term.ty(), self_ty) { + } else if contains_ty(assoc_ty, self_ty) { return; } } diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 865a36a5cd1d6..9162de3cceafa 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -243,9 +243,10 @@ fn check_other_call_arg<'tcx>( if if trait_predicate.def_id() == deref_trait_id { if let [projection_predicate] = projection_predicates[..] { let normalized_ty = - cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty()); + cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term); implements_trait(cx, receiver_ty, deref_trait_id, &[]) - && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty) + && get_associated_type(cx, receiver_ty, deref_trait_id, + "Target").map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty) } else { false } diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index 09f9e1ee09990..68156df2ecea8 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -98,9 +98,10 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve if trait_pred.self_ty() == inp; if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); then { - if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) { + if ord_preds.iter().any(|ord| Some(ord.self_ty()) == + return_ty_pred.term.ty()) { args_to_check.push((i, "Ord".to_string())); - } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) { + } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) { args_to_check.push((i, "PartialOrd".to_string())); } } From 109583e215a99e9998283c165e9f396f79194b83 Mon Sep 17 00:00:00 2001 From: kadmin Date: Tue, 11 Jan 2022 19:18:18 +0000 Subject: [PATCH 5/5] Update w/ comments Removes uses of ty() where a method is implemented on TypeFoldable, and also directly formats a Term. --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ca8bbbd8f9169..d5b928de4a81a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2143,7 +2143,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { let assoc_ty = match projection_predicate.term { ty::Term::Ty(ty) => ty, - ty::Term::Const(c) => c.ty, + ty::Term::Const(_c) => continue, }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() {