use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
- ImplItem, ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt,
- StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
+ ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node,
+ QPath, Stmt, StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use crate::utils::paths;
use crate::utils::sugg::Sugg;
use crate::utils::{
- clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant,
- is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args,
- multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt,
- snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
- span_lint_and_then, unsext,
+ clip, comparisons, differing_macro_contexts, get_qpath_generic_tys, higher, in_constant, indent_of, int_bits,
+ is_hir_ty_cfg_dependant, is_ty_param_diagnostic_item, is_ty_param_lang_item, is_type_diagnostic_item,
+ last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args, multispan_sugg,
+ numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt, snippet_with_applicability,
+ snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
};
declare_clippy_lint! {
}
}
-/// Checks if `qpath` has last segment with type parameter matching `path`
-fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> {
- let last = last_path_segment(qpath);
- if_chain! {
- if let Some(ref params) = last.args;
- if !params.parenthesized;
- if let Some(ty) = params.args.iter().find_map(|arg| match arg {
- GenericArg::Type(ty) => Some(ty),
- _ => None,
- });
- if let TyKind::Path(ref qpath) = ty.kind;
- if let Some(did) = cx.qpath_res(qpath, ty.hir_id).opt_def_id();
- if match_def_path(cx, did, path);
- then {
- return Some(ty.span);
- }
- }
- None
-}
-
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
- if match_type_parameter(cx, qpath, &paths::STRING).is_some() {
- return Some("str");
- }
- if match_type_parameter(cx, qpath, &paths::OS_STRING).is_some() {
- return Some("std::ffi::OsStr");
- }
- if match_type_parameter(cx, qpath, &paths::PATH_BUF).is_some() {
- return Some("std::path::Path");
+ if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).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
}
- None
}
fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
);
return; // don't recurse into the type
}
- if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
+ if is_ty_param_diagnostic_item(cx, qpath, sym::vec_type).is_some() {
span_lint_and_help(
cx,
BOX_VEC,
return; // don't recurse into the type
}
} else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
- if let Some(span) = match_type_parameter(cx, qpath, &paths::RC) {
+ if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
hir_ty.span,
"usage of `Rc<Rc<T>>`",
"try",
- snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
+ snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
applicability,
);
return; // don't recurse into the type
}
- if match_type_parameter(cx, qpath, &paths::BOX).is_some() {
- let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
- GenericArg::Type(ty) => match &ty.kind {
- TyKind::Path(qpath) => qpath,
- _ => return,
- },
+ if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
+ let qpath = match &ty.kind {
+ TyKind::Path(qpath) => qpath,
_ => return,
};
- let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] {
- GenericArg::Type(ty) => ty.span,
- _ => return,
+ let inner_span = match get_qpath_generic_tys(qpath).next() {
+ Some(ty) => ty.span,
+ None => return,
};
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
);
return; // don't recurse into the type
}
- if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
- let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
- GenericArg::Type(ty) => match &ty.kind {
- TyKind::Path(qpath) => qpath,
- _ => return,
- },
+ if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
+ let qpath = match &ty.kind {
+ TyKind::Path(qpath) => qpath,
_ => return,
};
- let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
- GenericArg::Type(ty) => ty.span,
- _ => return,
+ let inner_span = match get_qpath_generic_tys(qpath).next() {
+ Some(ty) => ty.span,
+ None => return,
};
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
);
return; // don't recurse into the type
}
- if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
- let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
- GenericArg::Type(ty) => match &ty.kind {
- TyKind::Path(qpath) => qpath,
- _ => return,
- },
+ if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
+ let qpath = match &ty.kind {
+ TyKind::Path(qpath) => qpath,
_ => return,
};
- let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
- GenericArg::Type(ty) => ty.span,
- _ => return,
+ let inner_span = match get_qpath_generic_tys(qpath).next() {
+ Some(ty) => ty.span,
+ None => return,
};
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
}
}
} else if cx.tcx.is_diagnostic_item(sym::option_type, def_id) {
- if match_type_parameter(cx, qpath, &paths::OPTION).is_some() {
+ if is_ty_param_diagnostic_item(cx, qpath, sym::option_type).is_some() {
span_lint(
cx,
OPTION_OPTION,
cx,
LINKEDLIST,
hir_ty.span,
- "I see you're using a LinkedList! Perhaps you meant some other data structure?",
+ "you seem to be using a `LinkedList`! Perhaps you meant some other data structure?",
None,
"a `VecDeque` might work",
);