mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 14:38:46 +00:00
Auto merge of #7897 - camsteffen:in-macro, r=flip1995
Replace `in_macro` usage with `from_expansion` changelog: none Generally replace `in_macro(span)` with `span.from_expansion()`. If we're just trying to avoid expanded code, this seems more appropriate because any kind of expanded code is prone to false positives. One place I did not touch is `macro_use.rs`. I think this lint could use a rewrite so I moved `in_macro` there, the only place it is still used.
This commit is contained in:
commit
9a60a93cac
46 changed files with 194 additions and 208 deletions
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::{eq_expr_value, get_trait_def_id, in_macro, paths};
|
||||
use clippy_utils::{eq_expr_value, get_trait_def_id, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -453,22 +453,20 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
|
|||
type Map = Map<'tcx>;
|
||||
|
||||
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||
if in_macro(e.span) {
|
||||
return;
|
||||
}
|
||||
match &e.kind {
|
||||
ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => {
|
||||
self.bool_expr(e);
|
||||
},
|
||||
ExprKind::Unary(UnOp::Not, inner) => {
|
||||
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
|
||||
if !e.span.from_expansion() {
|
||||
match &e.kind {
|
||||
ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => {
|
||||
self.bool_expr(e);
|
||||
} else {
|
||||
walk_expr(self, e);
|
||||
}
|
||||
},
|
||||
_ => walk_expr(self, e),
|
||||
},
|
||||
ExprKind::Unary(UnOp::Not, inner) => {
|
||||
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
|
||||
self.bool_expr(e);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
walk_expr(self, e);
|
||||
}
|
||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||
NestedVisitorMap::None
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
|
||||
use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
|
||||
use clippy_utils::{
|
||||
both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, is_else_clause,
|
||||
is_lint_allowed, search_same, ContainsName, SpanlessEq, SpanlessHash,
|
||||
both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, is_else_clause, is_lint_allowed,
|
||||
search_same, ContainsName, SpanlessEq, SpanlessHash,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
@ -623,7 +623,7 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) {
|
|||
|
||||
let eq: &dyn Fn(&&Expr<'_>, &&Expr<'_>) -> bool = &|&lhs, &rhs| -> bool {
|
||||
// Do not lint if any expr originates from a macro
|
||||
if in_macro(lhs.span) || in_macro(rhs.span) {
|
||||
if lhs.span.from_expansion() || rhs.span.from_expansion() {
|
||||
return false;
|
||||
}
|
||||
// Do not spawn warning if `IFS_SAME_COND` already produced it.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::ty::{has_drop, is_copy};
|
||||
use clippy_utils::{any_parent_is_automatically_derived, contains_name, in_macro, match_def_path, paths};
|
||||
use clippy_utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -78,7 +78,7 @@ impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);
|
|||
impl LateLintPass<'_> for Default {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if_chain! {
|
||||
if !in_macro(expr.span);
|
||||
if !expr.span.from_expansion();
|
||||
// Avoid cases already linted by `field_reassign_with_default`
|
||||
if !self.reassigned_linted.contains(&expr.span);
|
||||
if let ExprKind::Call(path, ..) = expr.kind;
|
||||
|
@ -125,7 +125,7 @@ impl LateLintPass<'_> for Default {
|
|||
if let StmtKind::Local(local) = stmt.kind;
|
||||
if let Some(expr) = local.init;
|
||||
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
|
||||
if !in_macro(expr.span);
|
||||
if !expr.span.from_expansion();
|
||||
// only take bindings to identifiers
|
||||
if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
|
||||
// only when assigning `... = Default::default()`
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::peel_mid_ty_refs;
|
||||
use clippy_utils::{get_parent_node, in_macro, is_lint_allowed};
|
||||
use clippy_utils::{get_parent_node, is_lint_allowed};
|
||||
use rustc_ast::util::parser::PREC_PREFIX;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
|
||||
|
@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
|
|||
}
|
||||
|
||||
// Stop processing sub expressions when a macro call is seen
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
if let Some((state, data)) = self.state.take() {
|
||||
report(cx, expr, state, data);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::{in_macro, is_automatically_derived, is_default_equivalent, remove_blocks};
|
||||
use clippy_utils::{is_automatically_derived, is_default_equivalent, remove_blocks};
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
|
||||
|
@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
|||
}) = item.kind;
|
||||
if let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if !is_automatically_derived(attrs);
|
||||
if !in_macro(item.span);
|
||||
if !item.span.from_expansion();
|
||||
if let Some(def_id) = trait_ref.trait_def_id();
|
||||
if cx.tcx.is_diagnostic_item(sym::Default, def_id);
|
||||
if let impl_item_hir = child.id.hir_id();
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_then};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::{implements_trait, is_copy};
|
||||
use clippy_utils::{
|
||||
ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, in_macro, is_expn_of, is_in_test_function,
|
||||
};
|
||||
use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, is_expn_of, is_in_test_function};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind};
|
||||
|
@ -102,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
|||
}
|
||||
let macro_with_not_op = |expr_kind: &ExprKind<'_>| {
|
||||
if let ExprKind::Unary(_, expr) = *expr_kind {
|
||||
in_macro(expr.span)
|
||||
expr.span.from_expansion()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::in_macro;
|
||||
use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
@ -135,7 +134,7 @@ fn is_bool_ty(ty: &Ty) -> bool {
|
|||
|
||||
impl EarlyLintPass for ExcessiveBools {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if in_macro(item.span) {
|
||||
if item.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
match &item.kind {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::higher;
|
||||
use clippy_utils::{in_macro, SpanlessEq};
|
||||
use clippy_utils::SpanlessEq;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -39,7 +39,7 @@ declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
if_chain! {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet;
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -66,7 +65,7 @@ declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRU
|
|||
impl LateLintPass<'_> for InconsistentStructConstructor {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
if_chain! {
|
||||
if !in_macro(expr.span);
|
||||
if !expr.span.from_expansion();
|
||||
if let ExprKind::Struct(qpath, fields, base) = expr.kind;
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if let Some(adt_def) = ty.ty_adt_def();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! lint on inherent implementations
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use clippy_utils::{in_macro, is_lint_allowed};
|
||||
use clippy_utils::is_lint_allowed;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::{def_id::LocalDefId, Item, ItemKind, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
@ -123,8 +123,10 @@ fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option<Span> {
|
|||
..
|
||||
}) = cx.tcx.hir().get(id)
|
||||
{
|
||||
(!in_macro(span) && impl_item.generics.params.is_empty() && !is_lint_allowed(cx, MULTIPLE_INHERENT_IMPL, id))
|
||||
.then(|| span)
|
||||
(!span.from_expansion()
|
||||
&& impl_item.generics.params.is_empty()
|
||||
&& !is_lint_allowed(cx, MULTIPLE_INHERENT_IMPL, id))
|
||||
.then(|| span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{in_macro, trait_ref_of_method};
|
||||
use clippy_utils::trait_ref_of_method;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::intravisit::{
|
||||
walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty,
|
||||
|
@ -128,7 +128,7 @@ fn check_fn_inner<'tcx>(
|
|||
span: Span,
|
||||
report_extra_lifetimes: bool,
|
||||
) {
|
||||
if in_macro(span) || has_where_lifetimes(cx, &generics.where_clause) {
|
||||
if span.from_expansion() || has_where_lifetimes(cx, &generics.where_clause) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
//! floating-point literal expressions.
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{
|
||||
in_macro,
|
||||
numeric_literal::{NumericLiteral, Radix},
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -283,7 +280,7 @@ impl LiteralDigitGrouping {
|
|||
| WarningType::InconsistentDigitGrouping
|
||||
| WarningType::UnusualByteGroupings
|
||||
| WarningType::LargeDigitGroups => {
|
||||
!in_macro(lit.span)
|
||||
!lit.span.from_expansion()
|
||||
}
|
||||
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => {
|
||||
true
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet;
|
||||
use hir::def::{DefKind, Res};
|
||||
use if_chain::if_chain;
|
||||
|
@ -9,6 +8,7 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::hygiene::ExpnKind;
|
||||
use rustc_span::{edition::Edition, sym, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -213,3 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn in_macro(span: Span) -> bool {
|
||||
span.from_expansion() && !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ use clippy_utils::sugg::Sugg;
|
|||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use clippy_utils::{
|
||||
get_parent_expr, in_macro, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild,
|
||||
meets_msrv, msrvs, path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns,
|
||||
remove_blocks, strip_pat_refs,
|
||||
get_parent_expr, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs,
|
||||
path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks,
|
||||
strip_pat_refs,
|
||||
};
|
||||
use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
|
||||
use core::array;
|
||||
|
@ -26,7 +26,6 @@ use rustc_hir::{
|
|||
};
|
||||
use rustc_hir::{HirIdMap, HirIdSet};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty, TyS, VariantDef};
|
||||
use rustc_semver::RustcVersion;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
@ -601,7 +600,7 @@ impl_lint_pass!(Matches => [
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for Matches {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -640,8 +639,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||
|
||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
||||
if_chain! {
|
||||
if !in_external_macro(cx.sess(), local.span);
|
||||
if !in_macro(local.span);
|
||||
if !local.span.from_expansion();
|
||||
if let Some(expr) = local.init;
|
||||
if let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind;
|
||||
if arms.len() == 1 && arms[0].guard.is_none();
|
||||
|
@ -676,8 +674,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||
|
||||
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
||||
if_chain! {
|
||||
if !in_external_macro(cx.sess(), pat.span);
|
||||
if !in_macro(pat.span);
|
||||
if !pat.span.from_expansion();
|
||||
if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind;
|
||||
if let Some(def_id) = path.res.opt_def_id();
|
||||
let ty = cx.tcx.type_of(def_id);
|
||||
|
@ -704,7 +701,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||
#[rustfmt::skip]
|
||||
fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
||||
if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
// Don't lint match expressions present in
|
||||
// macro_rules! block
|
||||
return;
|
||||
|
@ -1447,7 +1444,7 @@ fn find_bool_lit(ex: &ExprKind<'_>, is_if_let: bool) -> Option<bool> {
|
|||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
||||
if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) {
|
||||
if expr.span.from_expansion() || arms.len() != 1 || is_refutable(cx, arms[0].pat) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::ty::is_non_aggregate_primitive_type;
|
||||
use clippy_utils::{in_macro, is_default_equivalent, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths};
|
||||
use clippy_utils::{is_default_equivalent, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::LangItem::OptionNone;
|
||||
|
@ -213,7 +213,7 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
|
|||
expr_span,
|
||||
"replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
|
||||
|diag| {
|
||||
if !in_macro(expr_span) {
|
||||
if !expr_span.from_expansion() {
|
||||
let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
|
||||
|
||||
diag.span_suggestion(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{contains_return, BIND_INSTEAD_OF_MAP};
|
||||
use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
|
||||
use clippy_utils::{in_macro, remove_blocks, visitors::find_all_ret_expressions};
|
||||
use clippy_utils::{remove_blocks, visitors::find_all_ret_expressions};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
@ -106,7 +106,7 @@ pub(crate) trait BindInsteadOfMap {
|
|||
let mut suggs = Vec::new();
|
||||
let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| {
|
||||
if_chain! {
|
||||
if !in_macro(ret_expr.span);
|
||||
if !ret_expr.span.from_expansion();
|
||||
if let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind;
|
||||
if let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind;
|
||||
if Self::is_variant(cx, path.res);
|
||||
|
|
|
@ -68,7 +68,7 @@ use bind_instead_of_map::BindInsteadOfMap;
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
|
||||
use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, meets_msrv, msrvs, paths, return_ty};
|
||||
use clippy_utils::{contains_return, get_trait_def_id, iter_input_pats, meets_msrv, msrvs, paths, return_ty};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
|
@ -1900,7 +1900,7 @@ macro_rules! method_call {
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -78,7 +77,7 @@ fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mod
|
|||
let self_param = match (binding_mode, mutbl) {
|
||||
(Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
|
||||
(Mode::Ref(Some(lifetime)), Mutability::Mut) => {
|
||||
if in_macro(lifetime.ident.span) {
|
||||
if lifetime.ident.span.from_expansion() {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
"&'_ mut self".to_string()
|
||||
} else {
|
||||
|
@ -87,7 +86,7 @@ fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mod
|
|||
},
|
||||
(Mode::Ref(None), Mutability::Not) => "&self".to_string(),
|
||||
(Mode::Ref(Some(lifetime)), Mutability::Not) => {
|
||||
if in_macro(lifetime.ident.span) {
|
||||
if lifetime.ident.span.from_expansion() {
|
||||
applicability = Applicability::HasPlaceholders;
|
||||
"&'_ self".to_string()
|
||||
} else {
|
||||
|
@ -114,7 +113,7 @@ fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mod
|
|||
impl EarlyLintPass for NeedlessArbitrarySelfType {
|
||||
fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) {
|
||||
// Bail out if the parameter it's not a receiver or was not written by the user
|
||||
if !p.is_self() || in_macro(p.span) {
|
||||
if !p.is_self() || p.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -41,7 +40,7 @@ declare_lint_pass!(NeedlessBitwiseBool => [NEEDLESS_BITWISE_BOOL]);
|
|||
fn is_bitwise_operation(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if_chain! {
|
||||
if !in_macro(expr.span);
|
||||
if !expr.span.from_expansion();
|
||||
if let (&ExprKind::Binary(ref op, _, right), &ty::Bool) = (&expr.kind, &ty.kind());
|
||||
if op.node == BinOpKind::BitAnd || op.node == BinOpKind::BitOr;
|
||||
if let ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) | ExprKind::Unary(..) = right.kind;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context};
|
||||
use clippy_utils::{get_parent_expr, in_macro, path_to_local};
|
||||
use clippy_utils::{get_parent_expr, path_to_local};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
|
@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
|
|||
if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
|
||||
// This binding id has been seen before. Add this pattern to the list of changes.
|
||||
if let Some(prev_pat) = opt_prev_pat {
|
||||
if in_macro(pat.span) {
|
||||
if pat.span.from_expansion() {
|
||||
// Doesn't match the context of the previous pattern. Can't lint here.
|
||||
*opt_prev_pat = None;
|
||||
} else {
|
||||
|
@ -174,7 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
|
|||
}
|
||||
|
||||
if_chain! {
|
||||
if !in_macro(pat.span);
|
||||
if !pat.span.from_expansion();
|
||||
if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
|
||||
// only lint immutable refs, because borrowed `&mut T` cannot be moved out
|
||||
if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
|
||||
|
@ -248,12 +248,12 @@ impl NeedlessBorrow {
|
|||
span,
|
||||
kind: ExprKind::Unary(UnOp::Deref, _),
|
||||
..
|
||||
}) if !in_macro(span) => {
|
||||
}) if !span.from_expansion() => {
|
||||
// Remove explicit deref.
|
||||
let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
|
||||
pat.replacements.push((span, snip.into()));
|
||||
},
|
||||
Some(parent) if !in_macro(parent.span) => {
|
||||
Some(parent) if !parent.span.from_expansion() => {
|
||||
// Double reference might be needed at this point.
|
||||
if parent.precedence().order() == PREC_POSTFIX {
|
||||
// Parentheses would be needed here, don't lint.
|
||||
|
@ -264,7 +264,7 @@ impl NeedlessBorrow {
|
|||
pat.replacements.push((e.span, format!("&{}", snip)));
|
||||
}
|
||||
},
|
||||
_ if !in_macro(e.span) => {
|
||||
_ if !e.span.from_expansion() => {
|
||||
// Double reference might be needed at this point.
|
||||
pat.always_deref = false;
|
||||
let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -38,7 +37,7 @@ declare_lint_pass!(OptionNeedlessDeref=> [
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if expr.span.from_expansion() || in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
let typeck = cx.typeck_results();
|
||||
|
|
|
@ -3,14 +3,16 @@ use std::{
|
|||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
use clippy_utils::{diagnostics::span_lint_and_help, in_macro, is_direct_expn_of, source::snippet_opt};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use serde::{de, Deserialize};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -37,7 +39,7 @@ declare_clippy_lint! {
|
|||
const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
|
||||
|
||||
/// The (name, (open brace, close brace), source snippet)
|
||||
type MacroInfo<'a> = (&'a str, &'a (String, String), String);
|
||||
type MacroInfo<'a> = (Symbol, &'a (String, String), String);
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MacroBraces {
|
||||
|
@ -93,17 +95,16 @@ impl EarlyLintPass for MacroBraces {
|
|||
|
||||
fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option<MacroInfo<'a>> {
|
||||
let unnested_or_local = || {
|
||||
let nested = in_macro(span.ctxt().outer_expn_data().call_site);
|
||||
!nested
|
||||
!span.ctxt().outer_expn_data().call_site.from_expansion()
|
||||
|| span
|
||||
.macro_backtrace()
|
||||
.last()
|
||||
.map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
|
||||
};
|
||||
if_chain! {
|
||||
// Make sure we are only one level deep otherwise there are to many FP's
|
||||
if in_macro(span);
|
||||
if let Some((name, braces)) = find_matching_macro(span, &mac_braces.macro_braces);
|
||||
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind;
|
||||
let name = &*mac_name.as_str();
|
||||
if let Some(braces) = mac_braces.macro_braces.get(name);
|
||||
if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
|
||||
// we must check only invocation sites
|
||||
// https://github.com/rust-lang/rust-clippy/issues/7422
|
||||
|
@ -114,14 +115,14 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac
|
|||
if !c.starts_with(&format!("{}!{}", name, braces.0));
|
||||
if !mac_braces.done.contains(&span.ctxt().outer_expn_data().call_site);
|
||||
then {
|
||||
Some((name, braces, snip))
|
||||
Some((mac_name, braces, snip))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: &str, span: Span) {
|
||||
fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: Symbol, span: Span) {
|
||||
let with_space = &format!("! {}", braces.0);
|
||||
let without_space = &format!("!{}", braces.0);
|
||||
let mut help = snip;
|
||||
|
@ -144,15 +145,6 @@ fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), nam
|
|||
);
|
||||
}
|
||||
|
||||
fn find_matching_macro(
|
||||
span: Span,
|
||||
braces: &FxHashMap<String, (String, String)>,
|
||||
) -> Option<(&String, &(String, String))> {
|
||||
braces
|
||||
.iter()
|
||||
.find(|(macro_name, _)| is_direct_expn_of(span, macro_name).is_some())
|
||||
}
|
||||
|
||||
fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
|
||||
let mut braces = vec![
|
||||
macro_matcher!(
|
||||
|
|
|
@ -3,7 +3,7 @@ use clippy_utils::higher;
|
|||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{
|
||||
can_move_expr_to_closure, eager_or_lazy, in_constant, in_macro, is_else_clause, is_lang_ctor, peel_hir_expr_while,
|
||||
can_move_expr_to_closure, eager_or_lazy, in_constant, is_else_clause, is_lang_ctor, peel_hir_expr_while,
|
||||
CaptureKind,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
|
@ -126,7 +126,7 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo
|
|||
/// this construct is found, or None if this construct is not found.
|
||||
fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionIfLetElseOccurence> {
|
||||
if_chain! {
|
||||
if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly
|
||||
if !expr.span.from_expansion(); // Don't lint macros, because it behaves weirdly
|
||||
if !in_constant(cx, expr.hir_id);
|
||||
if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
|
||||
= higher::IfLet::hir(cx, expr);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -41,7 +40,7 @@ static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
|
|||
|
||||
impl LateLintPass<'_> for PtrEq {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::get_parent_expr;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use clippy_utils::{get_parent_expr, in_macro};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
|
||||
|
@ -43,7 +43,7 @@ declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING]);
|
|||
|
||||
impl LateLintPass<'_> for RedundantSlicing {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use if_chain::if_chain;
|
||||
|
@ -50,7 +49,7 @@ impl EarlyLintPass for DerefAddrOf {
|
|||
if_chain! {
|
||||
if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind;
|
||||
if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind;
|
||||
if !in_macro(addrof_target.span);
|
||||
if !addrof_target.span.from_expansion();
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let sugg = if e.span.from_expansion() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use clippy_utils::consts::{constant_context, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use if_chain::if_chain;
|
||||
|
@ -49,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
|
|||
if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
|
||||
if path.ident.name == sym!(repeat);
|
||||
if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1));
|
||||
if !in_macro(receiver.span);
|
||||
if !receiver.span.from_expansion();
|
||||
then {
|
||||
let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
|
||||
if ty.is_str() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{fn_def_id, in_macro, path_to_local_id};
|
||||
use clippy_utils::{fn_def_id, path_to_local_id};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -90,8 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
if !last_statement_borrows(cx, initexpr);
|
||||
if !in_external_macro(cx.sess(), initexpr.span);
|
||||
if !in_external_macro(cx.sess(), retexpr.span);
|
||||
if !in_external_macro(cx.sess(), local.span);
|
||||
if !in_macro(local.span);
|
||||
if !local.span.from_expansion();
|
||||
then {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use clippy_utils::in_macro;
|
||||
use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind, VisibilityKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
|
@ -110,7 +109,7 @@ fn track_uses(
|
|||
single_use_usages: &mut Vec<(Symbol, Span, bool)>,
|
||||
macros: &mut Vec<Symbol>,
|
||||
) {
|
||||
if in_macro(item.span) || item.vis.kind.is_pub() {
|
||||
if item.span.from_expansion() || item.vis.kind.is_pub() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::in_macro;
|
||||
use clippy_utils::paths;
|
||||
use clippy_utils::source::snippet_with_macro_callsite;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, is_type_ref_to_diagnostic_item};
|
||||
|
@ -40,7 +39,7 @@ declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]);
|
|||
|
||||
impl LateLintPass<'tcx> for StrlenOnCStrings {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
if in_macro(expr.span) {
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::{in_macro, SpanlessHash};
|
||||
use clippy_utils::SpanlessHash;
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
|
@ -93,7 +93,7 @@ fn get_trait_res_span_from_bound(bound: &GenericBound<'_>) -> Option<(Res, Span)
|
|||
|
||||
impl TraitBounds {
|
||||
fn check_type_repetition(self, cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
|
||||
if in_macro(gen.span) {
|
||||
if gen.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
let hash = |ty| -> u64 {
|
||||
|
@ -107,7 +107,7 @@ impl TraitBounds {
|
|||
if_chain! {
|
||||
if let WherePredicate::BoundPredicate(ref p) = bound;
|
||||
if p.bounds.len() as u64 <= self.max_trait_bounds;
|
||||
if !in_macro(p.span);
|
||||
if !p.span.from_expansion();
|
||||
let h = hash(p.bounded_ty);
|
||||
if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>());
|
||||
|
||||
|
@ -151,7 +151,7 @@ impl TraitBounds {
|
|||
}
|
||||
|
||||
fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
|
||||
if in_macro(gen.span) || gen.params.is_empty() || gen.where_clause.predicates.is_empty() {
|
||||
if gen.span.from_expansion() || gen.params.is_empty() || gen.where_clause.predicates.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
|
|||
for predicate in gen.where_clause.predicates {
|
||||
if_chain! {
|
||||
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
|
||||
if !in_macro(bound_predicate.span);
|
||||
if !bound_predicate.span.from_expansion();
|
||||
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
|
||||
if let Some(segment) = segments.first();
|
||||
if let Some(trait_resolutions_direct) = map.get(&segment.ident);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{differing_macro_contexts, get_parent_expr, in_macro, is_lang_ctor, match_def_path, paths};
|
||||
use clippy_utils::{get_parent_expr, is_lang_ctor, match_def_path, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::LangItem::ResultErr;
|
||||
|
@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{hygiene, sym};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
@ -93,15 +93,9 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
|
|||
};
|
||||
|
||||
let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
|
||||
let differing_contexts = differing_macro_contexts(expr.span, err_arg.span);
|
||||
|
||||
let origin_snippet = if in_macro(expr.span) && in_macro(err_arg.span) && differing_contexts {
|
||||
snippet(cx, err_arg.span.ctxt().outer_expn_data().call_site, "_")
|
||||
} else if err_arg.span.from_expansion() && !in_macro(expr.span) {
|
||||
snippet_with_macro_callsite(cx, err_arg.span, "_")
|
||||
} else {
|
||||
snippet(cx, err_arg.span, "_")
|
||||
};
|
||||
let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
|
||||
let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
|
||||
"" // already returns
|
||||
} else {
|
||||
|
@ -120,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
|
|||
"returning an `Err(_)` with the `?` operator",
|
||||
"try this",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use clippy_utils::is_lint_allowed;
|
||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet};
|
||||
use clippy_utils::{in_macro, is_lint_allowed};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, HirId, Local, UnsafeSource};
|
||||
|
@ -134,7 +134,7 @@ impl UndocumentedUnsafeBlocks {
|
|||
|
||||
let enclosing_scope_span = map.opt_span(enclosing_hir_id)?;
|
||||
|
||||
let between_span = if in_macro(block_span) {
|
||||
let between_span = if block_span.from_expansion() {
|
||||
self.macro_expansion = true;
|
||||
enclosing_scope_span.with_hi(block_span.hi())
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{contains_return, in_macro, is_lang_ctor, return_ty, visitors::find_all_ret_expressions};
|
||||
use clippy_utils::{contains_return, is_lang_ctor, return_ty, visitors::find_all_ret_expressions};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
|
@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
|
|||
let mut suggs = Vec::new();
|
||||
let can_sugg = find_all_ret_expressions(cx, &body.value, |ret_expr| {
|
||||
if_chain! {
|
||||
if !in_macro(ret_expr.span);
|
||||
if !ret_expr.span.from_expansion();
|
||||
// Check if a function call.
|
||||
if let ExprKind::Call(func, [arg]) = ret_expr.kind;
|
||||
// Check if OPTION_SOME or RESULT_OK, depending on return type.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::ty::same_type_and_consts;
|
||||
use clippy_utils::{in_macro, meets_msrv, msrvs};
|
||||
use clippy_utils::{meets_msrv, msrvs};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -197,7 +197,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
|
||||
if_chain! {
|
||||
if !in_macro(hir_ty.span);
|
||||
if !hir_ty.span.from_expansion();
|
||||
if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
|
||||
if let Some(&StackItem::Check {
|
||||
impl_id,
|
||||
|
@ -214,8 +214,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
};
|
||||
if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
|
||||
let hir = cx.tcx.hir();
|
||||
let id = hir.get_parent_node(hir_ty.hir_id);
|
||||
if !hir.opt_span(id).map_or(false, in_macro);
|
||||
// prevents false positive on `#[derive(serde::Deserialize)]`
|
||||
if !hir.span(hir.get_parent_node(hir_ty.hir_id)).in_derive_expansion();
|
||||
then {
|
||||
span_lint(cx, hir_ty.span);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if !in_macro(expr.span);
|
||||
if !expr.span.from_expansion();
|
||||
if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
|
||||
if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
|
||||
if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_test_module_or_function;
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::{in_macro, is_test_module_or_function};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
|
@ -196,7 +196,7 @@ impl LateLintPass<'_> for WildcardImports {
|
|||
|
||||
impl WildcardImports {
|
||||
fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
|
||||
in_macro(item.span)
|
||||
item.span.from_expansion()
|
||||
|| is_prelude_import(segments)
|
||||
|| (is_super_only_import(segments) && self.test_modules_deep > 0)
|
||||
}
|
||||
|
|
|
@ -250,12 +250,6 @@ pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem
|
|||
false
|
||||
}
|
||||
|
||||
/// Returns `true` if this `span` was expanded by any macro.
|
||||
#[must_use]
|
||||
pub fn in_macro(span: Span) -> bool {
|
||||
span.from_expansion() && !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
|
||||
}
|
||||
|
||||
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
|
||||
matches!(
|
||||
expr.kind,
|
||||
|
|
|
@ -179,7 +179,7 @@ impl<'tcx> Visitor<'tcx> for ReturnBreakContinueMacroVisitor {
|
|||
// desugaring, as this will detect a break if there's a while loop
|
||||
// or a for loop inside the expression.
|
||||
_ => {
|
||||
if utils::in_macro(ex.span) {
|
||||
if ex.span.from_expansion() {
|
||||
self.seen_return_break_continue = true;
|
||||
} else {
|
||||
rustc_hir::intravisit::walk_expr(self, ex);
|
||||
|
|
|
@ -8,7 +8,7 @@ You may need following tooltips to catch up with common operations.
|
|||
- [Checking for a specific type](#checking-for-a-specific-type)
|
||||
- [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
|
||||
- [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
|
||||
- [Dealing with macros](#dealing-with-macros)
|
||||
- [Dealing with macros](#dealing-with-macros-and-expansions)
|
||||
|
||||
Useful Rustc dev guide links:
|
||||
- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation)
|
||||
|
@ -182,64 +182,78 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
|
|||
}
|
||||
```
|
||||
|
||||
## Dealing with macros
|
||||
## Dealing with macros and expansions
|
||||
|
||||
There are several helpers in [`clippy_utils`][utils] to deal with macros:
|
||||
Keep in mind that macros are already expanded and desugaring is already applied
|
||||
to the code representation that you are working with in Clippy. This unfortunately causes a lot of
|
||||
false positives because macro expansions are "invisible" unless you actively check for them.
|
||||
Generally speaking, code with macro expansions should just be ignored by Clippy because that code can be
|
||||
dynamic in ways that are difficult or impossible to see.
|
||||
Use the following functions to deal with macros:
|
||||
|
||||
- `in_macro()`: detect if the given span is expanded by a macro
|
||||
- `span.from_expansion()`: detects if a span is from macro expansion or desugaring.
|
||||
Checking this is a common first step in a lint.
|
||||
|
||||
You may want to use this for example to not start linting in any macro.
|
||||
```rust
|
||||
if expr.span.from_expansion() {
|
||||
// just forget it
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
macro_rules! foo {
|
||||
($param:expr) => {
|
||||
match $param {
|
||||
"bar" => println!("whatever"),
|
||||
_ => ()
|
||||
}
|
||||
};
|
||||
}
|
||||
- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, which macro call expanded it.
|
||||
It is sometimes useful to check if the context of two spans are equal.
|
||||
|
||||
foo!("bar");
|
||||
```rust
|
||||
// expands to `1 + 0`, but don't lint
|
||||
1 + mac!()
|
||||
```
|
||||
```rust
|
||||
if left.span.ctxt() != right.span.ctxt() {
|
||||
// the coder most likely cannot modify this expression
|
||||
return;
|
||||
}
|
||||
```
|
||||
Note: Code that is not from expansion is in the "root" context. So any spans where `from_expansion` returns `true` can
|
||||
be assumed to have the same context. And so just using `span.from_expansion()` is often good enough.
|
||||
|
||||
// if we lint the `match` of `foo` call and test its span
|
||||
assert_eq!(in_macro(match_span), true);
|
||||
```
|
||||
|
||||
- `in_external_macro()`: detect if the given span is from an external macro, defined in a foreign crate
|
||||
- `in_external_macro(span)`: detect if the given span is from a macro defined in a foreign crate.
|
||||
If you want the lint to work with macro-generated code, this is the next line of defense to avoid macros
|
||||
not defined in the current crate. It doesn't make sense to lint code that the coder can't change.
|
||||
|
||||
You may want to use it for example to not start linting in macros from other crates
|
||||
You may want to use it for example to not start linting in macros from other crates
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate a_crate_with_macros;
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate a_crate_with_macros;
|
||||
|
||||
// `foo` is defined in `a_crate_with_macros`
|
||||
foo!("bar");
|
||||
// `foo` is defined in `a_crate_with_macros`
|
||||
foo!("bar");
|
||||
|
||||
// if we lint the `match` of `foo` call and test its span
|
||||
assert_eq!(in_external_macro(cx.sess(), match_span), true);
|
||||
```
|
||||
// if we lint the `match` of `foo` call and test its span
|
||||
assert_eq!(in_external_macro(cx.sess(), match_span), true);
|
||||
```
|
||||
|
||||
- `differing_macro_contexts()`: returns true if the two given spans are not from the same context
|
||||
|
||||
```rust
|
||||
macro_rules! m {
|
||||
($a:expr, $b:expr) => {
|
||||
if $a.is_some() {
|
||||
$b;
|
||||
}
|
||||
}
|
||||
}
|
||||
```rust
|
||||
macro_rules! m {
|
||||
($a:expr, $b:expr) => {
|
||||
if $a.is_some() {
|
||||
$b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let x: Option<u32> = Some(42);
|
||||
m!(x, x.unwrap());
|
||||
let x: Option<u32> = Some(42);
|
||||
m!(x, x.unwrap());
|
||||
|
||||
// These spans are not from the same context
|
||||
// x.is_some() is from inside the macro
|
||||
// x.unwrap() is from outside the macro
|
||||
assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
|
||||
```
|
||||
// These spans are not from the same context
|
||||
// x.is_some() is from inside the macro
|
||||
// x.unwrap() is from outside the macro
|
||||
assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
|
||||
```
|
||||
|
||||
[TyS]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyS.html
|
||||
[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
|
||||
|
@ -249,4 +263,3 @@ assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
|
|||
[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
|
||||
[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
|
||||
[paths]: ../clippy_utils/src/paths.rs
|
||||
[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![warn(clippy::if_chain_style)]
|
||||
#![allow(clippy::no_effect)]
|
||||
#![allow(clippy::no_effect, clippy::nonminimal_bool)]
|
||||
|
||||
extern crate if_chain;
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// [edition2018] edition:2018
|
||||
// [edition2021] edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_assert)]
|
||||
#![allow(clippy::nonminimal_bool)]
|
||||
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:22:5
|
||||
--> $DIR/manual_assert.rs:24:5
|
||||
|
|
||||
LL | / if !a.is_empty() {
|
||||
LL | | panic!("qaqaq{:?}", a);
|
||||
|
@ -9,7 +9,7 @@ LL | | }
|
|||
= note: `-D clippy::manual-assert` implied by `-D warnings`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:25:5
|
||||
--> $DIR/manual_assert.rs:27:5
|
||||
|
|
||||
LL | / if !a.is_empty() {
|
||||
LL | | panic!("qwqwq");
|
||||
|
@ -17,7 +17,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:42:5
|
||||
--> $DIR/manual_assert.rs:44:5
|
||||
|
|
||||
LL | / if b.is_empty() {
|
||||
LL | | panic!("panic1");
|
||||
|
@ -25,7 +25,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:45:5
|
||||
--> $DIR/manual_assert.rs:47:5
|
||||
|
|
||||
LL | / if b.is_empty() && a.is_empty() {
|
||||
LL | | panic!("panic2");
|
||||
|
@ -33,7 +33,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:48:5
|
||||
--> $DIR/manual_assert.rs:50:5
|
||||
|
|
||||
LL | / if a.is_empty() && !b.is_empty() {
|
||||
LL | | panic!("panic3");
|
||||
|
@ -41,7 +41,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:51:5
|
||||
--> $DIR/manual_assert.rs:53:5
|
||||
|
|
||||
LL | / if b.is_empty() || a.is_empty() {
|
||||
LL | | panic!("panic4");
|
||||
|
@ -49,7 +49,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:54:5
|
||||
--> $DIR/manual_assert.rs:56:5
|
||||
|
|
||||
LL | / if a.is_empty() || !b.is_empty() {
|
||||
LL | | panic!("panic5");
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// [edition2018] edition:2018
|
||||
// [edition2021] edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_assert)]
|
||||
#![allow(clippy::nonminimal_bool)]
|
||||
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:22:5
|
||||
--> $DIR/manual_assert.rs:24:5
|
||||
|
|
||||
LL | / if !a.is_empty() {
|
||||
LL | | panic!("qaqaq{:?}", a);
|
||||
|
@ -9,7 +9,7 @@ LL | | }
|
|||
= note: `-D clippy::manual-assert` implied by `-D warnings`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:25:5
|
||||
--> $DIR/manual_assert.rs:27:5
|
||||
|
|
||||
LL | / if !a.is_empty() {
|
||||
LL | | panic!("qwqwq");
|
||||
|
@ -17,7 +17,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:42:5
|
||||
--> $DIR/manual_assert.rs:44:5
|
||||
|
|
||||
LL | / if b.is_empty() {
|
||||
LL | | panic!("panic1");
|
||||
|
@ -25,7 +25,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:45:5
|
||||
--> $DIR/manual_assert.rs:47:5
|
||||
|
|
||||
LL | / if b.is_empty() && a.is_empty() {
|
||||
LL | | panic!("panic2");
|
||||
|
@ -33,7 +33,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:48:5
|
||||
--> $DIR/manual_assert.rs:50:5
|
||||
|
|
||||
LL | / if a.is_empty() && !b.is_empty() {
|
||||
LL | | panic!("panic3");
|
||||
|
@ -41,7 +41,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:51:5
|
||||
--> $DIR/manual_assert.rs:53:5
|
||||
|
|
||||
LL | / if b.is_empty() || a.is_empty() {
|
||||
LL | | panic!("panic4");
|
||||
|
@ -49,7 +49,7 @@ LL | | }
|
|||
| |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
|
||||
|
||||
error: only a `panic!` in `if`-then statement
|
||||
--> $DIR/manual_assert.rs:54:5
|
||||
--> $DIR/manual_assert.rs:56:5
|
||||
|
|
||||
LL | / if a.is_empty() || !b.is_empty() {
|
||||
LL | | panic!("panic5");
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// [edition2018] edition:2018
|
||||
// [edition2021] edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_assert)]
|
||||
#![allow(clippy::nonminimal_bool)]
|
||||
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3];
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// [edition2018] edition:2018
|
||||
// [edition2021] edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_assert)]
|
||||
#![allow(clippy::nonminimal_bool)]
|
||||
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3];
|
||||
|
|
Loading…
Add table
Reference in a new issue