From f60e43ee05620e413d5e7dc069b3334ff4d1d0ed Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 18 Nov 2022 19:58:07 +0000 Subject: [PATCH] Fix clippy's missing substs --- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 4 +++- clippy_lints/src/methods/unnecessary_to_owned.rs | 4 ++-- clippy_lints/src/needless_pass_by_value.rs | 4 ++-- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_utils/src/ty.rs | 14 +++++++++----- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 102a02138bc8..1d9af7cdbd35 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -466,12 +466,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r if let Some(def_id) = trait_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id); let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id); - if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]); + if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []); // If all of our fields implement `Eq`, we can implement `Eq` too if adt .all_fields() .map(|f| f.ty(cx.tcx, substs)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])); + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, [])); then { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 7b9786d7e570..ea4e5e052d02 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -119,11 +119,13 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { let callee_ty_unadjusted = cx.typeck_results().expr_ty(callee).peel_refs(); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc); + if let ty::Closure(_, substs) = *closure_ty.kind(); then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() - && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &[]) + && let args = cx.tcx.erase_late_bound_regions(ty::ClosureSubsts { substs }.sig()).inputs() + && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &args.iter().copied().map(Into::into).collect::>()) && path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr)) { // Mutable closure is used after current expr; we cannot consume it. diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index c7775313ecd0..375ebc903b40 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -474,7 +474,7 @@ fn is_cow_into_owned(cx: &LateContext<'_>, method_name: Symbol, method_def_id: D } /// Returns true if the named method is `ToString::to_string` and it's called on a type that -/// is string-like i.e. implements `AsRef` or `Deref`. +/// is string-like i.e. implements `AsRef` or `Deref`. fn is_to_string_on_string_like<'a>( cx: &LateContext<'_>, call_expr: &'a Expr<'a>, @@ -490,7 +490,7 @@ fn is_to_string_on_string_like<'a>( && let GenericArgKind::Type(ty) = generic_arg.unpack() && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) - && (implements_trait(cx, ty, deref_trait_id, &[cx.tcx.types.str_.into()]) || + && (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { true } else { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 79aa15b06ef4..eeff15bbfb42 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::ptr::get_spans; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::{get_trait_def_id, is_self, paths}; use if_chain::if_chain; use rustc_ast::ast::Attribute; @@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !ty.is_mutable_ptr(); if !is_copy(cx, ty); if ty.is_sized(cx.tcx, cx.param_env); - if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); + if !allowed_traits.iter().any(|&t| implements_trait_with_env(cx.tcx, cx.param_env, ty, t, [None])); if !implements_borrow_trait; if !all_borrowable_trait; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 5c2b96f5b2ce..a022fc156fca 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { let implements_partial_ord = { if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { - implements_trait(cx, ty, id, &[]) + implements_trait(cx, ty, id, &[ty.into()]) } else { return; } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index a1698a61e601..a8047fe9e5ea 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{TyCtxtInferExt, type_variable::{TypeVariableOrigin, TypeVariableOriginKind}}; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ @@ -18,7 +18,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Size, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; @@ -153,7 +153,7 @@ pub fn implements_trait<'tcx>( trait_id: DefId, ty_params: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params) + implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params.iter().map(|&arg| Some(arg))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. @@ -162,7 +162,7 @@ pub fn implements_trait_with_env<'tcx>( param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, - ty_params: &[GenericArg<'tcx>], + ty_params: impl IntoIterator>>, ) -> bool { // Clippy shouldn't have infer types assert!(!ty.needs_infer()); @@ -171,8 +171,12 @@ pub fn implements_trait_with_env<'tcx>( if ty.has_escaping_bound_vars() { return false; } - let ty_params = tcx.mk_substs(ty_params.iter()); let infcx = tcx.infer_ctxt().build(); + let orig = TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: DUMMY_SP, + }; + let ty_params = tcx.mk_substs(ty_params.into_iter().map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into()))); infcx .type_implements_trait(trait_id, ty, ty_params, param_env) .must_apply_modulo_regions()