Skip to content

migrate paths to newly-added diagnostic items #6807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions clippy_lints/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
use rustc_span::symbol::sym;

use crate::consts::{constant, Constant};
use crate::utils::sugg::Sugg;
use crate::utils::{
get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_integer_const, iter_input_pats,
last_path_segment, match_qpath, match_trait_method, paths, snippet, snippet_opt, span_lint, span_lint_and_sugg,
get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_diagnostic_assoc_item, is_integer_const,
iter_input_pats, last_path_segment, match_qpath, snippet, snippet_opt, span_lint, span_lint_and_sugg,
span_lint_and_then, span_lint_hir_and_then, unsext, SpanlessEq,
};

Expand Down Expand Up @@ -554,11 +555,16 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:

let (arg_ty, snip) = match expr.kind {
ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
(cx.typeck_results().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
} else {
return;
}
if_chain!(
if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString)
|| is_diagnostic_assoc_item(cx, expr_def_id, sym::ToOwned);
then {
(cx.typeck_results().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
} else {
return;
}
)
},
ExprKind::Call(ref path, ref v) if v.len() == 1 => {
if let ExprKind::Path(ref path) = path.kind {
Expand Down
5 changes: 3 additions & 2 deletions clippy_lints/src/path_buf_push_overwrite.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::utils::{match_type, paths, span_lint_and_sugg};
use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
use std::path::{Component, Path};

declare_clippy_lint! {
Expand Down Expand Up @@ -46,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite {
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if path.ident.name == sym!(push);
if args.len() == 2;
if match_type(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), &paths::PATH_BUF);
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::PathBuf);
if let Some(get_index_arg) = args.get(1);
if let ExprKind::Lit(ref lit) = get_index_arg.kind;
if let LitKind::Str(ref path_lit, _) = lit.node;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
},
);
}
} else if match_type(cx, ty, &paths::PATH_BUF) {
} else if is_type_diagnostic_item(cx, ty, sym::PathBuf) {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
span_lint_and_then(
cx,
Expand Down
8 changes: 4 additions & 4 deletions clippy_lints/src/redundant_clone.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::utils::{
fn_has_unsatisfiable_preds, has_drop, is_copy, is_type_diagnostic_item, match_def_path, match_type, paths,
snippet_opt, span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth,
fn_has_unsatisfiable_preds, has_drop, is_copy, is_type_diagnostic_item, match_def_path, paths, snippet_opt,
span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth,
};
use if_chain::if_chain;
use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation};
Expand Down Expand Up @@ -166,8 +166,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
if res == cloned;
if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id);
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
if is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf)
|| is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString);
then {
(pred_arg, res)
} else {
Expand Down
6 changes: 4 additions & 2 deletions clippy_lints/src/to_string_in_display.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::utils::{match_def_path, match_trait_method, path_to_local_id, paths, span_lint};
use crate::utils::{is_diagnostic_assoc_item, match_def_path, path_to_local_id, paths, span_lint};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym;

declare_clippy_lint! {
/// **What it does:** Checks for uses of `to_string()` in `Display` traits.
Expand Down Expand Up @@ -92,7 +93,8 @@ impl LateLintPass<'_> for ToStringInDisplay {
if let Some(self_hir_id) = self.self_hir_id;
if let ExprKind::MethodCall(ref path, _, args, _) = expr.kind;
if path.ident.name == sym!(to_string);
if match_trait_method(cx, expr, &paths::TO_STRING);
if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString);
if path_to_local_id(&args[0], self_hir_id);
then {
span_lint(
Expand Down
53 changes: 7 additions & 46 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use rustc_semver::RustcVersion;
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::source_map::Span;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::sym;
use rustc_target::abi::LayoutOf;
use rustc_target::spec::abi::Abi;
use rustc_typeck::hir_ty_to_ty;
Expand All @@ -33,10 +33,10 @@ use crate::utils::paths;
use crate::utils::sugg::Sugg;
use crate::utils::{
clip, comparisons, differing_macro_contexts, get_qpath_generic_tys, 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,
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! {
Expand Down Expand Up @@ -287,51 +287,12 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
}

/// Checks if the first type parameter is a lang item.
fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> 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.lang_items().require(item) == Ok(id)).then(|| ty))
} else {
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> {
if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
Some("str")
} else if is_ty_param_path(cx, qpath, &paths::OS_STRING).is_some() {
} else if is_ty_param_diagnostic_item(cx, qpath, sym::OsString).is_some() {
Some("std::ffi::OsStr")
} else if is_ty_param_path(cx, qpath, &paths::PATH_BUF).is_some() {
} else if is_ty_param_diagnostic_item(cx, qpath, sym::PathBuf).is_some() {
Some("std::path::Path")
} else {
None
Expand Down
34 changes: 32 additions & 2 deletions clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::Node;
use rustc_hir::{
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
Item, ItemKind, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef,
TyKind, Unsafety,
Item, ItemKind, LangItem, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind,
TraitRef, TyKind, Unsafety,
};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, Level, Lint, LintContext};
Expand Down Expand Up @@ -232,6 +232,36 @@ pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangI
}
}

/// Checks if the first type parameter is a lang item.
pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> 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.lang_items().require(item) == Ok(id)).then(|| ty))
} else {
None
}
}

/// Checks if the first type parameter is a diagnostic item.
pub 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 method call given in `expr` belongs to the given trait.
pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
Expand Down
3 changes: 0 additions & 3 deletions clippy_utils/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ pub const OPTION: [&str; 3] = ["core", "option", "Option"];
pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"];
pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"];
pub const ORD: [&str; 3] = ["core", "cmp", "Ord"];
pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub(super) const PANICKING_PANIC: [&str; 3] = ["core", "panicking", "panic"];
Expand Down Expand Up @@ -155,9 +154,7 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol",
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
#[cfg(feature = "internal-lints")]
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
Expand Down