Merge commit 'f712eb5cdc' into clippy-subtree-update
This commit is contained in:
parent
4847c40c8b
commit
6ced8c33c0
248 changed files with 5023 additions and 900 deletions
40
clippy_lints/src/utils/attr_collector.rs
Normal file
40
clippy_lints/src/utils/attr_collector.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use std::mem;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use rustc_ast::{Attribute, Crate};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct AttrStorage(pub Lrc<OnceLock<Vec<Span>>>);
|
||||
|
||||
pub struct AttrCollector {
|
||||
storage: AttrStorage,
|
||||
attrs: Vec<Span>,
|
||||
}
|
||||
|
||||
impl AttrCollector {
|
||||
pub fn new(storage: AttrStorage) -> Self {
|
||||
Self {
|
||||
storage,
|
||||
attrs: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(AttrCollector => []);
|
||||
|
||||
impl EarlyLintPass for AttrCollector {
|
||||
fn check_attribute(&mut self, _cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
self.attrs.push(attr.span);
|
||||
}
|
||||
|
||||
fn check_crate_post(&mut self, _: &EarlyContext<'_>, _: &Crate) {
|
||||
self.storage
|
||||
.0
|
||||
.set(mem::take(&mut self.attrs))
|
||||
.expect("should only be called once");
|
||||
}
|
||||
}
|
||||
|
|
@ -396,7 +396,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
self.pat(field!(let_expr.pat));
|
||||
// Does what ExprKind::Cast does, only adds a clause for the type
|
||||
// if it's a path
|
||||
if let Some(TyKind::Path(ref qpath)) = let_expr.value.ty.as_ref().map(|ty| &ty.kind) {
|
||||
if let Some(TyKind::Path(qpath)) = let_expr.value.ty.as_ref().map(|ty| &ty.kind) {
|
||||
bind!(self, qpath);
|
||||
chain!(self, "let TyKind::Path(ref {qpath}) = {let_expr}.ty.kind");
|
||||
self.qpath(qpath);
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ pub mod lint_without_lint_pass;
|
|||
pub mod msrv_attr_impl;
|
||||
pub mod outer_expn_data_pass;
|
||||
pub mod produce_ice;
|
||||
pub mod slow_symbol_comparisons;
|
||||
pub mod unnecessary_def_path;
|
||||
pub mod unsorted_clippy_utils_paths;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
|
|||
|
||||
if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind
|
||||
&& is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
|
||||
&& let ExprKind::Closure(&Closure { body, .. }) = &call_f.kind
|
||||
&& let ExprKind::Closure(&Closure { body, .. }) = call_f.kind
|
||||
&& let body = cx.tcx.hir().body(body)
|
||||
&& let only_expr = peel_blocks_with_stmt(body.value)
|
||||
&& let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ declare_clippy_lint! {
|
|||
///
|
||||
/// ### Why is this bad?
|
||||
/// The compiler only knows lints via a `LintPass`. Without
|
||||
/// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
|
||||
/// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not
|
||||
/// know the name of the lint.
|
||||
///
|
||||
/// ### Known problems
|
||||
|
|
@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
|||
.expect("lints must have a description field");
|
||||
|
||||
if let ExprKind::Lit(Spanned {
|
||||
node: LitKind::Str(ref sym, _),
|
||||
node: LitKind::Str(sym, _),
|
||||
..
|
||||
}) = field.expr.kind
|
||||
{
|
||||
|
|
@ -159,8 +159,8 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
|||
let body = cx.tcx.hir().body_owned_by(
|
||||
impl_item_refs
|
||||
.iter()
|
||||
.find(|iiref| iiref.ident.as_str() == "get_lints")
|
||||
.expect("LintPass needs to implement get_lints")
|
||||
.find(|iiref| iiref.ident.as_str() == "lint_vec")
|
||||
.expect("LintPass needs to implement lint_vec")
|
||||
.id
|
||||
.owner_id
|
||||
.def_id,
|
||||
|
|
@ -218,9 +218,7 @@ pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
|
|||
|
||||
fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) {
|
||||
if let Some(value) = extract_clippy_version_value(cx, item) {
|
||||
// The `sym!` macro doesn't work as it only expects a single token.
|
||||
// It's better to keep it this way and have a direct `Symbol::intern` call here.
|
||||
if value == Symbol::intern("pre 1.29.0") {
|
||||
if value.as_str() == "pre 1.29.0" {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +249,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
|
|||
pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
attrs.iter().find_map(|attr| {
|
||||
if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind
|
||||
if let ast::AttrKind::Normal(attr_kind) = &attr.kind
|
||||
// Identify attribute
|
||||
&& let [tool_name, attr_name] = &attr_kind.item.path.segments[..]
|
||||
&& tool_name.ident.name == sym::clippy
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
|
|||
.filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
|
||||
.any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
|
||||
})
|
||||
&& !items.iter().any(|item| item.ident.name == sym!(check_attributes))
|
||||
&& !items.iter().any(|item| item.ident.name.as_str() == "check_attributes")
|
||||
{
|
||||
let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
|
||||
let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::match_type;
|
||||
use clippy_utils::{match_function_call, paths};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
///
|
||||
/// Detects symbol comparision using `Symbol::intern`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// Comparision via `Symbol::as_str()` is faster if the interned symbols are not reused.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// None, see suggestion.
|
||||
pub SLOW_SYMBOL_COMPARISONS,
|
||||
internal,
|
||||
"detects slow comparisions of symbol"
|
||||
}
|
||||
|
||||
declare_lint_pass!(SlowSymbolComparisons => [SLOW_SYMBOL_COMPARISONS]);
|
||||
|
||||
fn check_slow_comparison<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
op1: &'tcx Expr<'tcx>,
|
||||
op2: &'tcx Expr<'tcx>,
|
||||
) -> Option<(Span, String)> {
|
||||
if match_type(cx, cx.typeck_results().expr_ty(op1), &paths::SYMBOL)
|
||||
&& let Some([symbol_name_expr]) = match_function_call(cx, op2, &paths::SYMBOL_INTERN)
|
||||
&& let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr)
|
||||
{
|
||||
Some((op1.span, symbol_name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for SlowSymbolComparisons {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let ExprKind::Binary(op, left, right) = expr.kind
|
||||
&& (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne)
|
||||
&& let Some((symbol_span, symbol_name)) =
|
||||
check_slow_comparison(cx, left, right).or_else(|| check_slow_comparison(cx, right, left))
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SLOW_SYMBOL_COMPARISONS,
|
||||
expr.span,
|
||||
"comparing `Symbol` via `Symbol::intern`",
|
||||
"use `Symbol::as_str` and check the string instead",
|
||||
format!(
|
||||
"{}.as_str() {} \"{symbol_name}\"",
|
||||
snippet_with_applicability(cx, symbol_span, "symbol", &mut applicability),
|
||||
op.node.as_str()
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
pub mod attr_collector;
|
||||
pub mod author;
|
||||
pub mod dump_hir;
|
||||
pub mod format_args_collector;
|
||||
|
||||
#[cfg(feature = "internal")]
|
||||
pub mod internal_lints;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue