Skip to content
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

Make use of more diagnostic items #5449

Merged
merged 4 commits into from Apr 14, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,5 +1,5 @@
use crate::utils::{
get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_sugg,
get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, span_lint_and_sugg,
span_lint_and_then, SpanlessEq,
};
use if_chain::if_chain;
@@ -249,7 +249,9 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> {
},
ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
let type_of_receiver = cx.tables.expr_ty(&args[0]);
if !match_type(cx, type_of_receiver, &paths::OPTION) && !match_type(cx, type_of_receiver, &paths::RESULT) {
if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
&& !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))
{
return None;
}
METHODS_WITH_NEGATION
@@ -9,7 +9,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::BytePos;

use crate::utils::{match_type, paths, snippet_opt, span_lint_and_help, LimitStack};
use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack};

declare_clippy_lint! {
/// **What it does:** Checks for methods with high cognitive complexity.
@@ -61,7 +61,7 @@ impl CognitiveComplexity {
helper.visit_expr(expr);
let CCHelper { cc, returns } = helper;
let ret_ty = cx.tables.node_type(expr.hir_id);
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym!(result_type)) {
returns
} else {
#[allow(clippy::integer_division)]
@@ -1,4 +1,4 @@
use crate::utils::{implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint};
use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_ast::ast::{AttrKind, Attribute};
@@ -217,7 +217,7 @@ fn lint_for_missing_headers<'a, 'tcx>(
);
}
if !headers.errors {
if match_type(cx, return_ty(cx, hir_id), &paths::RESULT) {
if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type)) {
span_lint(
cx,
MISSING_ERRORS_DOC,
@@ -235,7 +235,7 @@ fn lint_for_missing_headers<'a, 'tcx>(
if let ty::Opaque(_, subs) = ret_ty.kind;
if let Some(gen) = subs.types().next();
if let ty::Generator(_, subs, _) = gen.kind;
if match_type(cx, subs.as_generator().return_ty(), &paths::RESULT);
if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym!(result_type));
then {
span_lint(
cx,
@@ -1,10 +1,12 @@
use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT};
use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty};
use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT};
use crate::utils::{
is_expn_of, is_type_diagnostic_item, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;

@@ -76,7 +78,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0]));
if match_type(self.lcx, reciever_ty, &OPTION) || match_type(self.lcx, reciever_ty, &RESULT) {
if is_type_diagnostic_item(self.lcx, reciever_ty, sym!(option_type))
|| is_type_diagnostic_item(self.lcx, reciever_ty, sym!(result_type))
{
self.result.push(expr.span);
}
}
@@ -124,10 +128,3 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
}
}
}

fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
match ty.kind {
ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
_ => false,
}
}
@@ -1,4 +1,4 @@
use crate::utils::{match_type, method_chain_args, paths, snippet_with_applicability, span_lint_and_sugg};
use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath};
@@ -45,8 +45,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok()
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT);
if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type;
if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type));
if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";

then {
let mut applicability = Applicability::MachineApplicable;
@@ -1392,7 +1392,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e
/// Checks for `for` loops over `Option`s and `Result`s.
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) {
if is_type_diagnostic_item(cx, ty, sym!(option_type)) {
span_lint_and_help(
cx,
FOR_LOOP_OVER_OPTION,
@@ -1408,7 +1408,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
snippet(cx, arg.span, "_")
),
);
} else if match_type(cx, ty, &paths::RESULT) {
} else if is_type_diagnostic_item(cx, ty, sym!(result_type)) {
span_lint_and_help(
cx,
FOR_LOOP_OVER_RESULT,
@@ -1,6 +1,6 @@
use crate::utils::paths;
use crate::utils::{
is_copy, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
};
use if_chain::if_chain;
use rustc_ast::ast::Ident;
@@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
if args.len() == 2;
if method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]);
if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR);
if is_type_diagnostic_item(cx, ty, sym!(option_type)) || match_trait_method(cx, e, &paths::ITERATOR);
if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
let closure_body = cx.tcx.hir().body(body_id);
let closure_expr = remove_blocks(&closure_body.value);
@@ -1,5 +1,4 @@
use crate::utils::paths;
use crate::utils::{iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
use crate::utils::{is_type_diagnostic_item, iter_input_pats, method_chain_args, snippet, span_lint_and_then};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
@@ -206,9 +205,9 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
let var_arg = &map_args[0];

let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) {
let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(option_type)) {
("Option", "Some", OPTION_MAP_UNIT_FN)
} else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) {
} else if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(result_type)) {
("Result", "Ok", RESULT_MAP_UNIT_FN)
} else {
return;
@@ -3,10 +3,10 @@ use crate::utils::paths;
use crate::utils::sugg::Sugg;
use crate::utils::usage::is_unused;
use crate::utils::{
expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild,
match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block,
snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
walk_ptrs_ty,
expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
span_lint_and_then, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
@@ -642,7 +642,7 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<'

fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
if match_type(cx, ex_ty, &paths::RESULT) {
if is_type_diagnostic_item(cx, ex_ty, sym!(result_type)) {
for arm in arms {
if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind {
let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false));
@@ -9,6 +9,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;

declare_clippy_lint! {
/// **What it does:** Checks for `mem::replace()` on an `Option` with
@@ -141,15 +142,15 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
then {
if match_def_path(cx, repl_def_id, &paths::MEM_UNINITIALIZED) {
if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
span_lint_and_help(
cx,
MEM_REPLACE_WITH_UNINIT,
expr_span,
"replacing with `mem::uninitialized()`",
"consider using the `take_mut` crate instead",
);
} else if match_def_path(cx, repl_def_id, &paths::MEM_ZEROED) &&
} else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
!cx.tables.expr_ty(src).is_primitive() {
span_lint_and_help(
cx,
@@ -1836,9 +1836,9 @@ fn lint_expect_fun_call(
}

let receiver_type = cx.tables.expr_ty_adjusted(&args[0]);
let closure_args = if match_type(cx, receiver_type, &paths::OPTION) {
let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym!(option_type)) {
"||"
} else if match_type(cx, receiver_type, &paths::RESULT) {
} else if is_type_diagnostic_item(cx, receiver_type, sym!(result_type)) {
"|_|"
} else {
return;
@@ -1998,9 +1998,9 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &h
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg));

if let ty::Adt(_, subst) = obj_ty.kind {
let caller_type = if match_type(cx, obj_ty, &paths::RC) {
let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
"Rc"
} else if match_type(cx, obj_ty, &paths::ARC) {
} else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) {
"Arc"
} else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) {
"Weak"
@@ -2067,7 +2067,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, source: &
if_chain! {
let source_type = cx.tables.expr_ty(source);
if let ty::Adt(def, substs) = source_type.kind;
if match_def_path(cx, def.did, &paths::RESULT);
if cx.tcx.is_diagnostic_item(sym!(result_type), def.did);
if match_type(cx, substs.type_at(0), &paths::CSTRING);
then {
span_lint_and_then(
@@ -2395,9 +2395,9 @@ fn derefs_to_slice<'a, 'tcx>(
fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0]));

let mess = if match_type(cx, obj_ty, &paths::OPTION) {
let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) {
Some((OPTION_UNWRAP_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) {
} else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) {
Some((RESULT_UNWRAP_USED, "a Result", "Err"))
} else {
None
@@ -2422,9 +2422,9 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi
fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0]));

let mess = if match_type(cx, obj_ty, &paths::OPTION) {
let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) {
Some((OPTION_EXPECT_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) {
} else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) {
Some((RESULT_EXPECT_USED, "a Result", "Err"))
} else {
None
@@ -2445,7 +2445,7 @@ fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hi
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) {
if_chain! {
// lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT);
if is_type_diagnostic_item(cx, cx.tables.expr_ty(&ok_args[0]), sym!(result_type));
let result_type = cx.tables.expr_ty(&ok_args[0]);
if let Some(error_type) = get_error_type(cx, result_type);
if has_debug_impl(error_type, cx);
@@ -2491,8 +2491,8 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
unwrap_args: &'tcx [hir::Expr<'_>],
) {
// lint if the caller of `map()` is an `Option`
let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION);
let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT);
let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type));
let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(result_type));

if is_option || is_result {
// Don't make a suggestion that may fail to compile due to mutably borrowing
@@ -2559,8 +2559,8 @@ fn lint_map_or_none<'a, 'tcx>(
expr: &'tcx hir::Expr<'_>,
map_or_args: &'tcx [hir::Expr<'_>],
) {
let is_option = match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION);
let is_result = match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::RESULT);
let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(option_type));
let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(result_type));

// There are two variants of this `map_or` lint:
// (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
@@ -3209,10 +3209,7 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool {
match ty.kind {
ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component),
ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)),
ty::Adt(ref adt, _) => {
// needs to be a MaybeUninit
match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT)
},
ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT),
_ => false,
}
}
@@ -3326,7 +3323,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
/// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> {
match ty.kind {
ty::Adt(_, substs) if match_type(cx, ty, &paths::RESULT) => substs.types().nth(1),
ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym!(result_type)) => substs.types().nth(1),
_ => None,
}
}
@@ -1,5 +1,5 @@
use crate::utils::{differing_macro_contexts, paths, snippet_with_applicability, span_lint_and_then};
use crate::utils::{is_copy, match_type};
use crate::utils::{differing_macro_contexts, snippet_with_applicability, span_lint_and_then};
use crate::utils::{is_copy, is_type_diagnostic_item};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
@@ -20,7 +20,7 @@ pub(super) fn lint<'a, 'tcx>(
map_span: Span,
) {
// lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
if is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type)) {
if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) {
// Do not lint if the `map` argument uses identifiers in the `map`
// argument that are also used in the `unwrap_or` argument
@@ -5,10 +5,10 @@ use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatK
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::paths::{OPTION, OPTION_NONE};
use crate::utils::sugg::Sugg;
use crate::utils::{
higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_sugg, SpanlessEq,
higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
span_lint_and_sugg, SpanlessEq,
};

declare_clippy_lint! {
@@ -141,7 +141,7 @@ impl QuestionMark {
fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
let expr_ty = cx.tables.expr_ty(expression);

match_type(cx, expr_ty, &OPTION)
is_type_diagnostic_item(cx, expr_ty, sym!(option_type))
}

fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
@@ -158,7 +158,7 @@ impl QuestionMark {
if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
cx.tables.qpath_res(qp, expression.hir_id)
{
return match_def_path(cx, def_id, &OPTION_NONE);
return match_def_path(cx, def_id, &paths::OPTION_NONE);
}

false
@@ -420,7 +420,7 @@ impl Types {
return; // don't recurse into the type
}
}
} else if match_def_path(cx, def_id, &paths::OPTION) {
} else if cx.tcx.is_diagnostic_item(sym!(option_type), def_id) {
if match_type_parameter(cx, qpath, &paths::OPTION).is_some() {
span_lint(
cx,