Replace some iteration with get_[type_]diagnostic_name
This commit is contained in:
parent
9aa656df9f
commit
6993752607
@ -1,5 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
||||
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
|
||||
use clippy_utils::visitors::{for_each_expr, Visitable};
|
||||
use clippy_utils::{get_enclosing_block, path_to_local_id};
|
||||
use core::ops::ControlFlow;
|
||||
@ -7,7 +7,6 @@
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -44,24 +43,11 @@
|
||||
}
|
||||
declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]);
|
||||
|
||||
// Add `String` here when it is added to diagnostic items
|
||||
static COLLECTIONS: [Symbol; 9] = [
|
||||
sym::BTreeMap,
|
||||
sym::BTreeSet,
|
||||
sym::BinaryHeap,
|
||||
sym::HashMap,
|
||||
sym::HashSet,
|
||||
sym::LinkedList,
|
||||
sym::Option,
|
||||
sym::Vec,
|
||||
sym::VecDeque,
|
||||
];
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
|
||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
|
||||
// Look for local variables whose type is a container. Search surrounding block for read access.
|
||||
if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
||||
&& match_acceptable_type(cx, local, &COLLECTIONS)
|
||||
&& match_acceptable_type(cx, local)
|
||||
&& let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
|
||||
&& has_no_read_access(cx, local_id, enclosing_block)
|
||||
{
|
||||
@ -70,11 +56,22 @@ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool {
|
||||
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
|
||||
let ty = cx.typeck_results().pat_ty(local.pat);
|
||||
collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
|
||||
// String type is a lang item but not a diagnostic item for now so we need a separate check
|
||||
|| is_type_lang_item(cx, ty, LangItem::String)
|
||||
matches!(
|
||||
get_type_diagnostic_name(cx, ty),
|
||||
Some(
|
||||
sym::BTreeMap
|
||||
| sym::BTreeSet
|
||||
| sym::BinaryHeap
|
||||
| sym::HashMap
|
||||
| sym::HashSet
|
||||
| sym::LinkedList
|
||||
| sym::Option
|
||||
| sym::Vec
|
||||
| sym::VecDeque
|
||||
)
|
||||
) || is_type_lang_item(cx, ty, LangItem::String)
|
||||
}
|
||||
|
||||
fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool {
|
||||
|
@ -8,7 +8,7 @@
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
use clippy_utils::attrs::is_proc_macro;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
@ -193,17 +193,13 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
|
||||
}
|
||||
}
|
||||
|
||||
static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
|
||||
|
||||
fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
|
||||
match *ty.kind() {
|
||||
// primitive types are never mutable
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
|
||||
ty::Adt(adt, args) => {
|
||||
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
|
||||
|| KNOWN_WRAPPER_TYS
|
||||
.iter()
|
||||
.any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
|
||||
|| matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc))
|
||||
&& args.types().any(|ty| is_mutable_ty(cx, ty, tys))
|
||||
},
|
||||
ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
|
||||
|
@ -1,10 +1,10 @@
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::higher;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
|
||||
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -210,18 +210,6 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||
("product", 0),
|
||||
];
|
||||
|
||||
/// the paths of types that are known to be infinitely allocating
|
||||
const INFINITE_COLLECTORS: &[Symbol] = &[
|
||||
sym::BinaryHeap,
|
||||
sym::BTreeMap,
|
||||
sym::BTreeSet,
|
||||
sym::HashMap,
|
||||
sym::HashSet,
|
||||
sym::LinkedList,
|
||||
sym::Vec,
|
||||
sym::VecDeque,
|
||||
];
|
||||
|
||||
fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||
match expr.kind {
|
||||
ExprKind::MethodCall(method, receiver, args, _) => {
|
||||
@ -248,10 +236,19 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||
}
|
||||
} else if method.ident.name == sym!(collect) {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if INFINITE_COLLECTORS
|
||||
.iter()
|
||||
.any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
|
||||
{
|
||||
if matches!(
|
||||
get_type_diagnostic_name(cx, ty),
|
||||
Some(
|
||||
sym::BinaryHeap
|
||||
| sym::BTreeMap
|
||||
| sym::BTreeSet
|
||||
| sym::HashMap
|
||||
| sym::HashSet
|
||||
| sym::LinkedList
|
||||
| sym::Vec
|
||||
| sym::VecDeque,
|
||||
)
|
||||
) {
|
||||
return is_infinite(cx, receiver);
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
|
||||
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
|
||||
use clippy_utils::{match_def_path, paths, SpanlessEq};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::ExprKind::Assign;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{impl_lint_pass, RustcVersion};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -20,16 +20,6 @@
|
||||
&paths::SLICE_INTO,
|
||||
&paths::VEC_DEQUE_ITER,
|
||||
];
|
||||
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
|
||||
(sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
|
||||
(sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
|
||||
(sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
|
||||
(sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
|
||||
(sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)),
|
||||
(sym::Vec, None),
|
||||
(sym::VecDeque, None),
|
||||
];
|
||||
const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap];
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -264,16 +254,22 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo
|
||||
}
|
||||
|
||||
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| {
|
||||
is_type_diagnostic_item(cx, expr_ty, *ty)
|
||||
&& acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv))
|
||||
})
|
||||
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
let required = match get_type_diagnostic_name(cx, ty) {
|
||||
Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN,
|
||||
Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN,
|
||||
Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN,
|
||||
Some(sym::HashSet) => msrvs::HASH_SET_RETAIN,
|
||||
Some(sym::HashMap) => msrvs::HASH_MAP_RETAIN,
|
||||
Some(sym::Vec | sym::VecDeque) => return true,
|
||||
_ => return false,
|
||||
};
|
||||
msrv.meets(required)
|
||||
}
|
||||
|
||||
fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty))
|
||||
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap))
|
||||
}
|
||||
|
||||
fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
|
||||
use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
|
||||
use clippy_utils::{
|
||||
can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
|
||||
CaptureKind,
|
||||
@ -88,9 +88,10 @@ pub(super) fn check<'tcx>(
|
||||
Node::LetStmt(l) => {
|
||||
if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind
|
||||
&& let ty = cx.typeck_results().expr_ty(collect_expr)
|
||||
&& [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList]
|
||||
.into_iter()
|
||||
.any(|item| is_type_diagnostic_item(cx, ty, item))
|
||||
&& matches!(
|
||||
get_type_diagnostic_name(cx, ty),
|
||||
Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList)
|
||||
)
|
||||
&& let iter_ty = cx.typeck_results().expr_ty(iter_expr)
|
||||
&& let Some(block) = get_enclosing_block(cx, l.hir_id)
|
||||
&& let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
|
||||
|
@ -125,14 +125,12 @@ fn check_sig(&mut self, cx: &LateContext<'tcx>, fn_def_id: LocalDefId, decl: &hi
|
||||
// generics (because the compiler cannot ensure immutability for unknown types).
|
||||
fn check_ty_(&mut self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
|
||||
let ty = ty.peel_refs();
|
||||
if let ty::Adt(def, args) = ty.kind() {
|
||||
let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
|
||||
.iter()
|
||||
.any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
|
||||
if !is_keyed_type {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ty::Adt(def, args) = ty.kind()
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(def.did()),
|
||||
Some(sym::HashMap | sym::BTreeMap | sym::HashSet | sym::BTreeSet)
|
||||
)
|
||||
{
|
||||
let subst_ty = args.type_at(0);
|
||||
if self.interior_mut.is_interior_mut_ty(cx, subst_ty) {
|
||||
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
|
||||
|
Loading…
Reference in New Issue
Block a user