Factor out some ty param utils

This commit is contained in:
Cameron Steffen 2022-01-05 20:56:29 -06:00
parent 145d7fc529
commit 66a83d33ea
6 changed files with 63 additions and 90 deletions

View File

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_ty_param_diagnostic_item;
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_hir::{self as hir, def_id::DefId, QPath};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
use rustc_span::{sym, Symbol};
use super::BOX_COLLECTION;
@ -11,10 +11,9 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
if Some(def_id) == cx.tcx.lang_items().owned_box();
if let Some(item_type) = get_std_collection(cx, qpath);
then {
let generic = if item_type == "String" {
""
} else {
"<..>"
let generic = match item_type {
sym::String => "",
_ => "<..>",
};
span_lint_and_help(
cx,
@ -37,14 +36,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
}
}
fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
if is_ty_param_diagnostic_item(cx, qpath, sym::Vec).is_some() {
Some("Vec")
} else if is_ty_param_diagnostic_item(cx, qpath, sym::String).is_some() {
Some("String")
} else if is_ty_param_diagnostic_item(cx, qpath, sym::HashMap).is_some() {
Some("HashMap")
} else {
None
}
fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Symbol> {
let param = qpath_generic_tys(qpath).next()?;
let id = path_def_id(cx, param)?;
cx.tcx
.get_diagnostic_name(id)
.filter(|&name| matches!(name, sym::HashMap | sym::String | sym::Vec))
}

View File

@ -1,5 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_ty_param_diagnostic_item;
use clippy_utils::{path_def_id, qpath_generic_tys};
use if_chain::if_chain;
use rustc_hir::{self as hir, def_id::DefId, QPath};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
@ -7,16 +8,21 @@ use rustc_span::symbol::sym;
use super::OPTION_OPTION;
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
if cx.tcx.is_diagnostic_item(sym::Option, def_id) && is_ty_param_diagnostic_item(cx, qpath, sym::Option).is_some() {
span_lint(
cx,
OPTION_OPTION,
hir_ty.span,
"consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
enum if you need to distinguish all 3 cases",
);
true
} else {
false
if_chain! {
if cx.tcx.is_diagnostic_item(sym::Option, def_id);
if let Some(arg) = qpath_generic_tys(qpath).next();
if path_def_id(cx, arg) == Some(def_id);
then {
span_lint(
cx,
OPTION_OPTION,
hir_ty.span,
"consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
enum if you need to distinguish all 3 cases",
);
true
} else {
false
}
}
}

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_ty_param_diagnostic_item, qpath_generic_tys};
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability;
use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
use rustc_lint::LateContext;
@ -20,7 +20,12 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
format!("Rc<{}>", alternate),
Applicability::MachineApplicable,
);
} else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Vec) {
} else {
let Some(ty) = qpath_generic_tys(qpath).next() else { return false };
let Some(id) = path_def_id(cx, ty) else { return false };
if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
return false;
}
let qpath = match &ty.kind {
TyKind::Path(qpath) => qpath,
_ => return false,
@ -55,7 +60,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
format!("Arc<{}>", alternate),
Applicability::MachineApplicable,
);
} else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Vec) {
} else if let Some(ty) = qpath_generic_tys(qpath).next() {
let Some(id) = path_def_id(cx, ty) else { return false };
if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
return false;
}
let qpath = match &ty.kind {
TyKind::Path(qpath) => qpath,
_ => return false,
@ -85,13 +94,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
}
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
if is_ty_param_diagnostic_item(cx, qpath, sym::String).is_some() {
Some("str")
} else if is_ty_param_diagnostic_item(cx, qpath, sym::OsString).is_some() {
Some("std::ffi::OsStr")
} else if is_ty_param_diagnostic_item(cx, qpath, sym::PathBuf).is_some() {
Some("std::path::Path")
} else {
None
}
let ty = qpath_generic_tys(qpath).next()?;
let id = path_def_id(cx, ty)?;
let path = match cx.tcx.get_diagnostic_name(id)? {
sym::String => "str",
sym::OsString => "std::ffi::OsStr",
sym::PathBuf => "std::path::Path",
_ => return None,
};
Some(path)
}

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_ty_param_diagnostic_item;
use clippy_utils::{path_def_id, qpath_generic_tys};
use if_chain::if_chain;
use rustc_hir::{self as hir, def_id::DefId, QPath};
use rustc_lint::LateContext;
@ -10,7 +10,9 @@ use super::RC_MUTEX;
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
if_chain! {
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym::Mutex) ;
if let Some(arg) = qpath_generic_tys(qpath).next();
if let Some(id) = path_def_id(cx, arg);
if cx.tcx.is_diagnostic_item(sym::Mutex, id);
then {
span_lint_and_help(
cx,

View File

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::{is_ty_param_diagnostic_item, is_ty_param_lang_item, qpath_generic_tys};
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability;
use rustc_hir::{self as hir, def_id::DefId, LangItem, QPath, TyKind};
use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
@ -39,14 +39,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
return true;
}
let (inner_sym, ty) = if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
("Box", ty)
} else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
("Rc", ty)
} else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Arc) {
("Arc", ty)
} else {
return false;
let Some(ty) = qpath_generic_tys(qpath).next() else { return false };
let Some(id) = path_def_id(cx, ty) else { return false };
let (inner_sym, ty) = match cx.tcx.get_diagnostic_name(id) {
Some(sym::Arc) => ("Arc", ty),
Some(sym::Rc) => ("Rc", ty),
_ if Some(id) == cx.tcx.lang_items().owned_box() => ("Box", ty),
_ => return false,
};
let inner_qpath = match &ty.kind {

View File

@ -262,44 +262,6 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
matches!(pat.kind, PatKind::Wild)
}
/// Checks if the first type parameter is a lang item.
pub fn is_ty_param_lang_item<'tcx>(
cx: &LateContext<'_>,
qpath: &QPath<'tcx>,
item: LangItem,
) -> Option<&'tcx hir::Ty<'tcx>> {
let ty = qpath_generic_tys(qpath).next()?;
if let TyKind::Path(qpath) = &ty.kind {
cx.qpath_res(qpath, ty.hir_id)
.opt_def_id()
.map_or(false, |id| {
cx.tcx.lang_items().require(item).map_or(false, |lang_id| id == lang_id)
})
.then(|| ty)
} else {
None
}
}
/// Checks if the first type parameter is a diagnostic item.
pub fn is_ty_param_diagnostic_item<'tcx>(
cx: &LateContext<'_>,
qpath: &QPath<'tcx>,
item: Symbol,
) -> Option<&'tcx hir::Ty<'tcx>> {
let ty = qpath_generic_tys(qpath).next()?;
if let TyKind::Path(qpath) = &ty.kind {
cx.qpath_res(qpath, ty.hir_id)
.opt_def_id()
.map_or(false, |id| cx.tcx.is_diagnostic_item(item, id))
.then(|| ty)
} else {
None
}
}
/// Checks if the method call given in `expr` belongs to the given trait.
/// This is a deprecated function, consider using [`is_trait_method`].
pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {