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;
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,
}
}
-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))
}
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;
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
+ }
}
}
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;
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,
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,
}
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)
}
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;
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,
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;
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 {
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 {