Skip to content

Commit 5945e85

Browse files
committed
Auto merge of #6823 - Jarcho:diagnostic_items, r=phansch
Use diagnostic or language items instead of paths I think that gets everything except ones used in a list of paths to check. changelog: none
2 parents 13271d3 + e4ffff9 commit 5945e85

File tree

8 files changed

+109
-85
lines changed

8 files changed

+109
-85
lines changed

clippy_lints/src/case_sensitive_file_extension_comparisons.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use crate::utils::paths::STRING;
2-
use crate::utils::{match_def_path, span_lint_and_help};
1+
use crate::utils::span_lint_and_help;
32
use if_chain::if_chain;
43
use rustc_ast::ast::LitKind;
54
use rustc_hir::{Expr, ExprKind, PathSegment};
65
use rustc_lint::{LateContext, LateLintPass};
76
use rustc_middle::ty;
87
use rustc_session::{declare_lint_pass, declare_tool_lint};
9-
use rustc_span::{source_map::Spanned, Span};
8+
use rustc_span::{source_map::Spanned, symbol::sym, Span};
109

1110
declare_clippy_lint! {
1211
/// **What it does:**
@@ -59,7 +58,7 @@ fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: &
5958
return Some(span);
6059
},
6160
ty::Adt(&ty::AdtDef { did, .. }, _) => {
62-
if match_def_path(ctx, did, &STRING) {
61+
if ctx.tcx.is_diagnostic_item(sym::string_type, did) {
6362
return Some(span);
6463
}
6564
},

clippy_lints/src/derive.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::utils::paths;
22
use crate::utils::{
3-
get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, match_path, span_lint_and_help,
3+
get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, span_lint_and_help,
44
span_lint_and_note, span_lint_and_then,
55
};
66
use if_chain::if_chain;
@@ -293,7 +293,7 @@ fn check_ord_partial_ord<'tcx>(
293293

294294
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
295295
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
296-
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
296+
if cx.tcx.lang_items().clone_trait() == trait_ref.trait_def_id() {
297297
if !is_copy(cx, ty) {
298298
return;
299299
}

clippy_lints/src/lifetimes.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use crate::utils::paths;
2-
use crate::utils::{get_trait_def_id, in_macro, span_lint, trait_ref_of_method};
1+
use crate::utils::{in_macro, span_lint, trait_ref_of_method};
32
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
43
use rustc_hir::intravisit::{
54
walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty,
@@ -8,8 +7,8 @@ use rustc_hir::intravisit::{
87
use rustc_hir::FnRetTy::Return;
98
use rustc_hir::{
109
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem,
11-
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier, TraitFn,
12-
TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
10+
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier,
11+
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
1312
};
1413
use rustc_lint::{LateContext, LateLintPass};
1514
use rustc_middle::hir::map::Map;
@@ -300,7 +299,7 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
300299
lts.iter().collect::<FxHashSet<_>>().len()
301300
}
302301

303-
const CLOSURE_TRAIT_BOUNDS: [&[&str]; 3] = [&paths::FN, &paths::FN_MUT, &paths::FN_ONCE];
302+
const CLOSURE_TRAIT_BOUNDS: [LangItem; 3] = [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
304303

305304
/// A visitor usable for `rustc_front::visit::walk_ty()`.
306305
struct RefVisitor<'a, 'tcx> {
@@ -361,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
361360
let trait_ref = &poly_tref.trait_ref;
362361
if CLOSURE_TRAIT_BOUNDS
363362
.iter()
364-
.any(|trait_path| trait_ref.trait_def_id() == get_trait_def_id(self.cx, trait_path))
363+
.any(|&item| trait_ref.trait_def_id() == self.cx.tcx.lang_items().require(item).ok())
365364
{
366365
let mut sub_visitor = RefVisitor::new(self.cx);
367366
sub_visitor.visit_trait_ref(trait_ref);

clippy_lints/src/map_clone.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
7979
},
8080
hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
8181
if ident_eq(name, obj) && method.ident.name == sym::clone;
82-
if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT);
82+
if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
83+
if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
84+
if Some(trait_id) == cx.tcx.lang_items().clone_trait();
8385
// no autoderefs
8486
if !cx.typeck_results().expr_adjustments(obj).iter()
8587
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))));

clippy_lints/src/redundant_clone.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
165165
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
166166
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
167167
if res == cloned;
168-
if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
168+
if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id);
169169
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
170170
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
171171
then {

clippy_lints/src/types.rs

+71-62
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use rustc_hir as hir;
1111
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
1212
use rustc_hir::{
1313
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
14-
ImplItem, ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt,
15-
StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
14+
ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node,
15+
QPath, Stmt, StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
1616
};
1717
use rustc_lint::{LateContext, LateLintPass, LintContext};
1818
use rustc_middle::hir::map::Map;
@@ -23,7 +23,7 @@ use rustc_semver::RustcVersion;
2323
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
2424
use rustc_span::hygiene::{ExpnKind, MacroKind};
2525
use rustc_span::source_map::Span;
26-
use rustc_span::symbol::sym;
26+
use rustc_span::symbol::{sym, Symbol};
2727
use rustc_target::abi::LayoutOf;
2828
use rustc_target::spec::abi::Abi;
2929
use rustc_typeck::hir_ty_to_ty;
@@ -32,9 +32,9 @@ use crate::consts::{constant, Constant};
3232
use crate::utils::paths;
3333
use crate::utils::sugg::Sugg;
3434
use crate::utils::{
35-
clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant,
36-
is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args,
37-
multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt,
35+
clip, comparisons, differing_macro_contexts, get_qpath_generic_tys, higher, in_constant, indent_of, int_bits,
36+
is_hir_ty_cfg_dependant, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv,
37+
method_chain_args, multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt,
3838
snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
3939
span_lint_and_then, unsext,
4040
};
@@ -287,37 +287,55 @@ impl<'tcx> LateLintPass<'tcx> for Types {
287287
}
288288
}
289289

290-
/// Checks if `qpath` has last segment with type parameter matching `path`
291-
fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> {
292-
let last = last_path_segment(qpath);
293-
if_chain! {
294-
if let Some(ref params) = last.args;
295-
if !params.parenthesized;
296-
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
297-
GenericArg::Type(ty) => Some(ty),
298-
_ => None,
299-
});
300-
if let TyKind::Path(ref qpath) = ty.kind;
301-
if let Some(did) = cx.qpath_res(qpath, ty.hir_id).opt_def_id();
302-
if match_def_path(cx, did, path);
303-
then {
304-
return Some(ty.span);
305-
}
290+
/// Checks if the first type parameter is a lang item.
291+
fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
292+
let ty = get_qpath_generic_tys(qpath).next()?;
293+
294+
if let TyKind::Path(qpath) = &ty.kind {
295+
cx.qpath_res(qpath, ty.hir_id)
296+
.opt_def_id()
297+
.and_then(|id| (cx.tcx.lang_items().require(item) == Ok(id)).then(|| ty))
298+
} else {
299+
None
306300
}
307-
None
308301
}
309302

310-
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
311-
if match_type_parameter(cx, qpath, &paths::STRING).is_some() {
312-
return Some("str");
303+
/// Checks if the first type parameter is a diagnostic item.
304+
fn is_ty_param_diagnostic_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: Symbol) -> Option<&'tcx hir::Ty<'tcx>> {
305+
let ty = get_qpath_generic_tys(qpath).next()?;
306+
307+
if let TyKind::Path(qpath) = &ty.kind {
308+
cx.qpath_res(qpath, ty.hir_id)
309+
.opt_def_id()
310+
.and_then(|id| cx.tcx.is_diagnostic_item(item, id).then(|| ty))
311+
} else {
312+
None
313313
}
314-
if match_type_parameter(cx, qpath, &paths::OS_STRING).is_some() {
315-
return Some("std::ffi::OsStr");
314+
}
315+
316+
/// Checks if the first type parameter is a given item.
317+
fn is_ty_param_path(cx: &LateContext<'_>, qpath: &QPath<'tcx>, path: &[&str]) -> Option<&'tcx hir::Ty<'tcx>> {
318+
let ty = get_qpath_generic_tys(qpath).next()?;
319+
320+
if let TyKind::Path(qpath) = &ty.kind {
321+
cx.qpath_res(qpath, ty.hir_id)
322+
.opt_def_id()
323+
.and_then(|id| match_def_path(cx, id, path).then(|| ty))
324+
} else {
325+
None
316326
}
317-
if match_type_parameter(cx, qpath, &paths::PATH_BUF).is_some() {
318-
return Some("std::path::Path");
327+
}
328+
329+
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
330+
if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
331+
Some("str")
332+
} else if is_ty_param_path(cx, qpath, &paths::OS_STRING).is_some() {
333+
Some("std::ffi::OsStr")
334+
} else if is_ty_param_path(cx, qpath, &paths::PATH_BUF).is_some() {
335+
Some("std::path::Path")
336+
} else {
337+
None
319338
}
320-
None
321339
}
322340

323341
fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
@@ -381,7 +399,7 @@ impl Types {
381399
);
382400
return; // don't recurse into the type
383401
}
384-
if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
402+
if is_ty_param_diagnostic_item(cx, qpath, sym::vec_type).is_some() {
385403
span_lint_and_help(
386404
cx,
387405
BOX_VEC,
@@ -393,30 +411,27 @@ impl Types {
393411
return; // don't recurse into the type
394412
}
395413
} else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
396-
if let Some(span) = match_type_parameter(cx, qpath, &paths::RC) {
414+
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
397415
let mut applicability = Applicability::MachineApplicable;
398416
span_lint_and_sugg(
399417
cx,
400418
REDUNDANT_ALLOCATION,
401419
hir_ty.span,
402420
"usage of `Rc<Rc<T>>`",
403421
"try",
404-
snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
422+
snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
405423
applicability,
406424
);
407425
return; // don't recurse into the type
408426
}
409-
if match_type_parameter(cx, qpath, &paths::BOX).is_some() {
410-
let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
411-
GenericArg::Type(ty) => match &ty.kind {
412-
TyKind::Path(qpath) => qpath,
413-
_ => return,
414-
},
427+
if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
428+
let qpath = match &ty.kind {
429+
TyKind::Path(qpath) => qpath,
415430
_ => return,
416431
};
417-
let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] {
418-
GenericArg::Type(ty) => ty.span,
419-
_ => return,
432+
let inner_span = match get_qpath_generic_tys(qpath).next() {
433+
Some(ty) => ty.span,
434+
None => return,
420435
};
421436
let mut applicability = Applicability::MachineApplicable;
422437
span_lint_and_sugg(
@@ -445,17 +460,14 @@ impl Types {
445460
);
446461
return; // don't recurse into the type
447462
}
448-
if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
449-
let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
450-
GenericArg::Type(ty) => match &ty.kind {
451-
TyKind::Path(qpath) => qpath,
452-
_ => return,
453-
},
463+
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
464+
let qpath = match &ty.kind {
465+
TyKind::Path(qpath) => qpath,
454466
_ => return,
455467
};
456-
let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
457-
GenericArg::Type(ty) => ty.span,
458-
_ => return,
468+
let inner_span = match get_qpath_generic_tys(qpath).next() {
469+
Some(ty) => ty.span,
470+
None => return,
459471
};
460472
let mut applicability = Applicability::MachineApplicable;
461473
span_lint_and_sugg(
@@ -498,17 +510,14 @@ impl Types {
498510
);
499511
return; // don't recurse into the type
500512
}
501-
if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
502-
let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
503-
GenericArg::Type(ty) => match &ty.kind {
504-
TyKind::Path(qpath) => qpath,
505-
_ => return,
506-
},
513+
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
514+
let qpath = match &ty.kind {
515+
TyKind::Path(qpath) => qpath,
507516
_ => return,
508517
};
509-
let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
510-
GenericArg::Type(ty) => ty.span,
511-
_ => return,
518+
let inner_span = match get_qpath_generic_tys(qpath).next() {
519+
Some(ty) => ty.span,
520+
None => return,
512521
};
513522
let mut applicability = Applicability::MachineApplicable;
514523
span_lint_and_sugg(
@@ -563,7 +572,7 @@ impl Types {
563572
}
564573
}
565574
} else if cx.tcx.is_diagnostic_item(sym::option_type, def_id) {
566-
if match_type_parameter(cx, qpath, &paths::OPTION).is_some() {
575+
if is_ty_param_diagnostic_item(cx, qpath, sym::option_type).is_some() {
567576
span_lint(
568577
cx,
569578
OPTION_OPTION,

clippy_utils/src/lib.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
6363
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
6464
use rustc_hir::Node;
6565
use rustc_hir::{
66-
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind,
67-
MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety,
66+
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, GenericArgs, HirId, ImplItem, ImplItemKind, Item,
67+
ItemKind, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind,
68+
Unsafety,
6869
};
6970
use rustc_infer::infer::TyCtxtInferExt;
7071
use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -272,6 +273,27 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
272273
}
273274
}
274275

276+
pub fn get_qpath_generics(path: &QPath<'tcx>) -> Option<&'tcx GenericArgs<'tcx>> {
277+
match path {
278+
QPath::Resolved(_, p) => p.segments.last().and_then(|s| s.args),
279+
QPath::TypeRelative(_, s) => s.args,
280+
QPath::LangItem(..) => None,
281+
}
282+
}
283+
284+
pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
285+
get_qpath_generics(path)
286+
.map_or([].as_ref(), |a| a.args)
287+
.iter()
288+
.filter_map(|a| {
289+
if let hir::GenericArg::Type(ty) = a {
290+
Some(ty)
291+
} else {
292+
None
293+
}
294+
})
295+
}
296+
275297
pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
276298
match *path {
277299
QPath::Resolved(_, ref path) => path.segments.get(0),

0 commit comments

Comments
 (0)