Merge commit 'f712eb5cdc' into clippy-subtree-update

This commit is contained in:
Philipp Krones 2024-11-07 22:31:20 +01:00
parent 4847c40c8b
commit 6ced8c33c0
248 changed files with 5023 additions and 900 deletions

View 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");
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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" };

View file

@ -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,
);
};
}
}

View file

@ -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;