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
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
use crate::utils::paths::STRING;
|
use crate::utils::span_lint_and_help;
|
||||||
use crate::utils::{match_def_path, span_lint_and_help};
|
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_hir::{Expr, ExprKind, PathSegment};
|
use rustc_hir::{Expr, ExprKind, PathSegment};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::{source_map::Spanned, Span};
|
use rustc_span::{source_map::Spanned, symbol::sym, Span};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:**
|
/// **What it does:**
|
||||||
@@ -59,7 +58,7 @@ fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: &
|
|||||||
return Some(span);
|
return Some(span);
|
||||||
},
|
},
|
||||||
ty::Adt(&ty::AdtDef { did, .. }, _) => {
|
ty::Adt(&ty::AdtDef { did, .. }, _) => {
|
||||||
if match_def_path(ctx, did, &STRING) {
|
if ctx.tcx.is_diagnostic_item(sym::string_type, did) {
|
||||||
return Some(span);
|
return Some(span);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::utils::paths;
|
use crate::utils::paths;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, match_path, span_lint_and_help,
|
get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, span_lint_and_help,
|
||||||
span_lint_and_note, span_lint_and_then,
|
span_lint_and_note, span_lint_and_then,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
@@ -293,7 +293,7 @@ fn check_ord_partial_ord<'tcx>(
|
|||||||
|
|
||||||
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
|
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
|
||||||
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
|
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
|
||||||
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
|
if cx.tcx.lang_items().clone_trait() == trait_ref.trait_def_id() {
|
||||||
if !is_copy(cx, ty) {
|
if !is_copy(cx, ty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::utils::paths;
|
use crate::utils::{in_macro, span_lint, trait_ref_of_method};
|
||||||
use crate::utils::{get_trait_def_id, in_macro, span_lint, trait_ref_of_method};
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_hir::intravisit::{
|
use rustc_hir::intravisit::{
|
||||||
walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty,
|
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::{
|
|||||||
use rustc_hir::FnRetTy::Return;
|
use rustc_hir::FnRetTy::Return;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem,
|
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem,
|
||||||
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier, TraitFn,
|
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier,
|
||||||
TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
|
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
@@ -300,7 +299,7 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
|
|||||||
lts.iter().collect::<FxHashSet<_>>().len()
|
lts.iter().collect::<FxHashSet<_>>().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLOSURE_TRAIT_BOUNDS: [&[&str]; 3] = [&paths::FN, &paths::FN_MUT, &paths::FN_ONCE];
|
const CLOSURE_TRAIT_BOUNDS: [LangItem; 3] = [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
|
||||||
|
|
||||||
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
||||||
struct RefVisitor<'a, 'tcx> {
|
struct RefVisitor<'a, 'tcx> {
|
||||||
@@ -361,7 +360,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
|||||||
let trait_ref = &poly_tref.trait_ref;
|
let trait_ref = &poly_tref.trait_ref;
|
||||||
if CLOSURE_TRAIT_BOUNDS
|
if CLOSURE_TRAIT_BOUNDS
|
||||||
.iter()
|
.iter()
|
||||||
.any(|trait_path| trait_ref.trait_def_id() == get_trait_def_id(self.cx, trait_path))
|
.any(|&item| trait_ref.trait_def_id() == self.cx.tcx.lang_items().require(item).ok())
|
||||||
{
|
{
|
||||||
let mut sub_visitor = RefVisitor::new(self.cx);
|
let mut sub_visitor = RefVisitor::new(self.cx);
|
||||||
sub_visitor.visit_trait_ref(trait_ref);
|
sub_visitor.visit_trait_ref(trait_ref);
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
|
|||||||
},
|
},
|
||||||
hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
|
hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
|
||||||
if ident_eq(name, obj) && method.ident.name == sym::clone;
|
if ident_eq(name, obj) && method.ident.name == sym::clone;
|
||||||
if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT);
|
if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
|
||||||
|
if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
|
||||||
|
if Some(trait_id) == cx.tcx.lang_items().clone_trait();
|
||||||
// no autoderefs
|
// no autoderefs
|
||||||
if !cx.typeck_results().expr_adjustments(obj).iter()
|
if !cx.typeck_results().expr_adjustments(obj).iter()
|
||||||
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))));
|
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))));
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
|
|||||||
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
|
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
|
||||||
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
|
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
|
||||||
if res == cloned;
|
if res == cloned;
|
||||||
if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
|
if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id);
|
||||||
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|
||||||
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
|
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
|
||||||
then {
|
then {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
|
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,
|
ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node,
|
||||||
StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
|
QPath, Stmt, StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
@@ -23,7 +23,7 @@ use rustc_semver::RustcVersion;
|
|||||||
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_target::abi::LayoutOf;
|
use rustc_target::abi::LayoutOf;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_typeck::hir_ty_to_ty;
|
use rustc_typeck::hir_ty_to_ty;
|
||||||
@@ -32,9 +32,9 @@ use crate::consts::{constant, Constant};
|
|||||||
use crate::utils::paths;
|
use crate::utils::paths;
|
||||||
use crate::utils::sugg::Sugg;
|
use crate::utils::sugg::Sugg;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant,
|
clip, comparisons, differing_macro_contexts, get_qpath_generic_tys, higher, in_constant, indent_of, int_bits,
|
||||||
is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args,
|
is_hir_ty_cfg_dependant, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv,
|
||||||
multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt,
|
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,
|
snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
|
||||||
span_lint_and_then, unsext,
|
span_lint_and_then, unsext,
|
||||||
};
|
};
|
||||||
@@ -287,38 +287,56 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if `qpath` has last segment with type parameter matching `path`
|
/// Checks if the first type parameter is a lang item.
|
||||||
fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> {
|
fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
|
||||||
let last = last_path_segment(qpath);
|
let ty = get_qpath_generic_tys(qpath).next()?;
|
||||||
if_chain! {
|
|
||||||
if let Some(ref params) = last.args;
|
if let TyKind::Path(qpath) = &ty.kind {
|
||||||
if !params.parenthesized;
|
cx.qpath_res(qpath, ty.hir_id)
|
||||||
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
|
.opt_def_id()
|
||||||
GenericArg::Type(ty) => Some(ty),
|
.and_then(|id| (cx.tcx.lang_items().require(item) == Ok(id)).then(|| ty))
|
||||||
_ => None,
|
} else {
|
||||||
});
|
|
||||||
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
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the first type parameter is a diagnostic item.
|
||||||
|
fn is_ty_param_diagnostic_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: Symbol) -> Option<&'tcx hir::Ty<'tcx>> {
|
||||||
|
let ty = get_qpath_generic_tys(qpath).next()?;
|
||||||
|
|
||||||
|
if let TyKind::Path(qpath) = &ty.kind {
|
||||||
|
cx.qpath_res(qpath, ty.hir_id)
|
||||||
|
.opt_def_id()
|
||||||
|
.and_then(|id| cx.tcx.is_diagnostic_item(item, id).then(|| ty))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the first type parameter is a given item.
|
||||||
|
fn is_ty_param_path(cx: &LateContext<'_>, qpath: &QPath<'tcx>, path: &[&str]) -> Option<&'tcx hir::Ty<'tcx>> {
|
||||||
|
let ty = get_qpath_generic_tys(qpath).next()?;
|
||||||
|
|
||||||
|
if let TyKind::Path(qpath) = &ty.kind {
|
||||||
|
cx.qpath_res(qpath, ty.hir_id)
|
||||||
|
.opt_def_id()
|
||||||
|
.and_then(|id| match_def_path(cx, id, path).then(|| ty))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
|
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
|
||||||
if match_type_parameter(cx, qpath, &paths::STRING).is_some() {
|
if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
|
||||||
return Some("str");
|
Some("str")
|
||||||
}
|
} else if is_ty_param_path(cx, qpath, &paths::OS_STRING).is_some() {
|
||||||
if match_type_parameter(cx, qpath, &paths::OS_STRING).is_some() {
|
Some("std::ffi::OsStr")
|
||||||
return Some("std::ffi::OsStr");
|
} else if is_ty_param_path(cx, qpath, &paths::PATH_BUF).is_some() {
|
||||||
}
|
Some("std::path::Path")
|
||||||
if match_type_parameter(cx, qpath, &paths::PATH_BUF).is_some() {
|
} else {
|
||||||
return Some("std::path::Path");
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
|
fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
|
||||||
let last = last_path_segment(qpath);
|
let last = last_path_segment(qpath);
|
||||||
@@ -381,7 +399,7 @@ impl Types {
|
|||||||
);
|
);
|
||||||
return; // don't recurse into the type
|
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(
|
span_lint_and_help(
|
||||||
cx,
|
cx,
|
||||||
BOX_VEC,
|
BOX_VEC,
|
||||||
@@ -393,7 +411,7 @@ impl Types {
|
|||||||
return; // don't recurse into the type
|
return; // don't recurse into the type
|
||||||
}
|
}
|
||||||
} else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
|
} 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;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
@@ -401,22 +419,19 @@ impl Types {
|
|||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
"usage of `Rc<Rc<T>>`",
|
"usage of `Rc<Rc<T>>`",
|
||||||
"try",
|
"try",
|
||||||
snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
|
snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
return; // don't recurse into the type
|
return; // don't recurse into the type
|
||||||
}
|
}
|
||||||
if match_type_parameter(cx, qpath, &paths::BOX).is_some() {
|
if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
|
||||||
let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
|
let qpath = match &ty.kind {
|
||||||
GenericArg::Type(ty) => match &ty.kind {
|
|
||||||
TyKind::Path(qpath) => qpath,
|
TyKind::Path(qpath) => qpath,
|
||||||
_ => return,
|
_ => return,
|
||||||
},
|
|
||||||
_ => return,
|
|
||||||
};
|
};
|
||||||
let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] {
|
let inner_span = match get_qpath_generic_tys(qpath).next() {
|
||||||
GenericArg::Type(ty) => ty.span,
|
Some(ty) => ty.span,
|
||||||
_ => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
@@ -445,17 +460,14 @@ impl Types {
|
|||||||
);
|
);
|
||||||
return; // don't recurse into the type
|
return; // don't recurse into the type
|
||||||
}
|
}
|
||||||
if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
|
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
|
||||||
let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
|
let qpath = match &ty.kind {
|
||||||
GenericArg::Type(ty) => match &ty.kind {
|
|
||||||
TyKind::Path(qpath) => qpath,
|
TyKind::Path(qpath) => qpath,
|
||||||
_ => return,
|
_ => return,
|
||||||
},
|
|
||||||
_ => return,
|
|
||||||
};
|
};
|
||||||
let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
|
let inner_span = match get_qpath_generic_tys(qpath).next() {
|
||||||
GenericArg::Type(ty) => ty.span,
|
Some(ty) => ty.span,
|
||||||
_ => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
@@ -498,17 +510,14 @@ impl Types {
|
|||||||
);
|
);
|
||||||
return; // don't recurse into the type
|
return; // don't recurse into the type
|
||||||
}
|
}
|
||||||
if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
|
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
|
||||||
let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
|
let qpath = match &ty.kind {
|
||||||
GenericArg::Type(ty) => match &ty.kind {
|
|
||||||
TyKind::Path(qpath) => qpath,
|
TyKind::Path(qpath) => qpath,
|
||||||
_ => return,
|
_ => return,
|
||||||
},
|
|
||||||
_ => return,
|
|
||||||
};
|
};
|
||||||
let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
|
let inner_span = match get_qpath_generic_tys(qpath).next() {
|
||||||
GenericArg::Type(ty) => ty.span,
|
Some(ty) => ty.span,
|
||||||
_ => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
@@ -563,7 +572,7 @@ impl Types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if cx.tcx.is_diagnostic_item(sym::option_type, def_id) {
|
} 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(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
OPTION_OPTION,
|
OPTION_OPTION,
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
|||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind,
|
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, GenericArgs, HirId, ImplItem, ImplItemKind, Item,
|
||||||
MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety,
|
ItemKind, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind,
|
||||||
|
Unsafety,
|
||||||
};
|
};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||||
@@ -272,6 +273,27 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_qpath_generics(path: &QPath<'tcx>) -> Option<&'tcx GenericArgs<'tcx>> {
|
||||||
|
match path {
|
||||||
|
QPath::Resolved(_, p) => p.segments.last().and_then(|s| s.args),
|
||||||
|
QPath::TypeRelative(_, s) => s.args,
|
||||||
|
QPath::LangItem(..) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
|
||||||
|
get_qpath_generics(path)
|
||||||
|
.map_or([].as_ref(), |a| a.args)
|
||||||
|
.iter()
|
||||||
|
.filter_map(|a| {
|
||||||
|
if let hir::GenericArg::Type(ty) = a {
|
||||||
|
Some(ty)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
|
pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
|
||||||
match *path {
|
match *path {
|
||||||
QPath::Resolved(_, ref path) => path.segments.get(0),
|
QPath::Resolved(_, ref path) => path.segments.get(0),
|
||||||
|
|||||||
@@ -12,11 +12,9 @@ pub(super) const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"];
|
|||||||
pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
|
pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
|
||||||
pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
|
pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
|
||||||
pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
|
pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
|
||||||
pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"];
|
|
||||||
pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
|
pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
|
||||||
pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"];
|
pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"];
|
||||||
pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
|
pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
|
||||||
pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"];
|
|
||||||
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
|
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
|
||||||
pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
|
pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
|
||||||
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
|
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
|
||||||
@@ -43,9 +41,6 @@ pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"];
|
|||||||
pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
|
pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
|
||||||
pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
|
pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
|
||||||
pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"];
|
pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"];
|
||||||
pub const FN: [&str; 3] = ["core", "ops", "Fn"];
|
|
||||||
pub const FN_MUT: [&str; 3] = ["core", "ops", "FnMut"];
|
|
||||||
pub const FN_ONCE: [&str; 3] = ["core", "ops", "FnOnce"];
|
|
||||||
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
|
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
|
||||||
pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"];
|
pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"];
|
||||||
pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
|
pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
|
||||||
@@ -114,7 +109,6 @@ pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_
|
|||||||
pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
|
pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
|
||||||
pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
|
pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
|
||||||
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
|
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
|
||||||
pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
|
|
||||||
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
||||||
pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
|
pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
|
||||||
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
||||||
@@ -143,7 +137,6 @@ pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"];
|
|||||||
pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
|
pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
|
||||||
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
|
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
|
||||||
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
|
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
|
||||||
pub const STRING: [&str; 3] = ["alloc", "string", "String"];
|
|
||||||
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
|
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
|
||||||
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
|
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
|
||||||
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
|
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
|
||||||
|
|||||||
Reference in New Issue
Block a user