]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/attrs.rs
Auto merge of #3985 - phansch:move_some_cast_tests, r=flip1995
[rust.git] / clippy_lints / src / attrs.rs
index a72944bbe028f8e518156d914dc0e9a557d9c347..45250e1eca629cec41924c74935a9a97f471adf0 100644 (file)
 
 use crate::reexport::*;
 use crate::utils::{
-    in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg,
-    span_lint_and_then, without_block_comments,
+    in_macro, last_line_of_span, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then,
+    without_block_comments,
 };
 use if_chain::if_chain;
 use rustc::hir::*;
 use rustc::lint::{
-    CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
+    in_external_macro, CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray,
+    LintContext, LintPass,
 };
-use rustc::ty::{self, TyCtxt};
-use rustc::{declare_tool_lint, lint_array};
+use rustc::ty;
+use rustc::{declare_lint_pass, declare_tool_lint};
 use rustc_errors::Applicability;
 use semver::Version;
-use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
+use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use syntax::source_map::Span;
 
-/// **What it does:** Checks for items annotated with `#[inline(always)]`,
-/// unless the annotated function is empty or simply panics.
-///
-/// **Why is this bad?** While there are valid uses of this annotation (and once
-/// you know when to use it, by all means `allow` this lint), it's a common
-/// newbie-mistake to pepper one's code with it.
-///
-/// As a rule of thumb, before slapping `#[inline(always)]` on a function,
-/// measure if that additional function call really affects your runtime profile
-/// sufficiently to make up for the increase in compile time.
-///
-/// **Known problems:** False positives, big time. This lint is meant to be
-/// deactivated by everyone doing serious performance work. This means having
-/// done the measurement.
-///
-/// **Example:**
-/// ```rust
-/// #[inline(always)]
-/// fn not_quite_hot_code(..) { ... }
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for items annotated with `#[inline(always)]`,
+    /// unless the annotated function is empty or simply panics.
+    ///
+    /// **Why is this bad?** While there are valid uses of this annotation (and once
+    /// you know when to use it, by all means `allow` this lint), it's a common
+    /// newbie-mistake to pepper one's code with it.
+    ///
+    /// As a rule of thumb, before slapping `#[inline(always)]` on a function,
+    /// measure if that additional function call really affects your runtime profile
+    /// sufficiently to make up for the increase in compile time.
+    ///
+    /// **Known problems:** False positives, big time. This lint is meant to be
+    /// deactivated by everyone doing serious performance work. This means having
+    /// done the measurement.
+    ///
+    /// **Example:**
+    /// ```ignore
+    /// #[inline(always)]
+    /// fn not_quite_hot_code(..) { ... }
+    /// ```
     pub INLINE_ALWAYS,
     pedantic,
     "use of `#[inline(always)]`"
 }
 
-/// **What it does:** Checks for `extern crate` and `use` items annotated with
-/// lint attributes.
-///
-/// This lint whitelists `#[allow(unused_imports)]` and `#[allow(deprecated)]` on
-/// `use` items and `#[allow(unused_imports)]` on `extern crate` items with a
-/// `#[macro_use]` attribute.
-///
-/// **Why is this bad?** Lint attributes have no effect on crate imports. Most
-/// likely a `!` was forgotten.
-///
-/// **Known problems:** None.
-///
-/// **Example:**
-/// ```rust
-/// // Bad
-/// #[deny(dead_code)]
-/// extern crate foo;
-/// #[forbid(dead_code)]
-/// use foo::bar;
-///
-/// // Ok
-/// #[allow(unused_imports)]
-/// use foo::baz;
-/// #[allow(unused_imports)]
-/// #[macro_use]
-/// extern crate baz;
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for `extern crate` and `use` items annotated with
+    /// lint attributes.
+    ///
+    /// This lint whitelists `#[allow(unused_imports)]` and `#[allow(deprecated)]` on
+    /// `use` items and `#[allow(unused_imports)]` on `extern crate` items with a
+    /// `#[macro_use]` attribute.
+    ///
+    /// **Why is this bad?** Lint attributes have no effect on crate imports. Most
+    /// likely a `!` was forgotten.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```ignore
+    /// // Bad
+    /// #[deny(dead_code)]
+    /// extern crate foo;
+    /// #[forbid(dead_code)]
+    /// use foo::bar;
+    ///
+    /// // Ok
+    /// #[allow(unused_imports)]
+    /// use foo::baz;
+    /// #[allow(unused_imports)]
+    /// #[macro_use]
+    /// extern crate baz;
+    /// ```
     pub USELESS_ATTRIBUTE,
     correctness,
     "use of lint attributes on `extern crate` items"
 }
 
-/// **What it does:** Checks for `#[deprecated]` annotations with a `since`
-/// field that is not a valid semantic version.
-///
-/// **Why is this bad?** For checking the version of the deprecation, it must be
-/// a valid semver. Failing that, the contained information is useless.
-///
-/// **Known problems:** None.
-///
-/// **Example:**
-/// ```rust
-/// #[deprecated(since = "forever")]
-/// fn something_else(..) { ... }
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for `#[deprecated]` annotations with a `since`
+    /// field that is not a valid semantic version.
+    ///
+    /// **Why is this bad?** For checking the version of the deprecation, it must be
+    /// a valid semver. Failing that, the contained information is useless.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// #[deprecated(since = "forever")]
+    /// fn something_else() { /* ... */ }
+    /// ```
     pub DEPRECATED_SEMVER,
     correctness,
     "use of `#[deprecated(since = \"x\")]` where x is not semver"
 }
 
-/// **What it does:** Checks for empty lines after outer attributes
-///
-/// **Why is this bad?**
-/// Most likely the attribute was meant to be an inner attribute using a '!'.
-/// If it was meant to be an outer attribute, then the following item
-/// should not be separated by empty lines.
-///
-/// **Known problems:** Can cause false positives.
-///
-/// From the clippy side it's difficult to detect empty lines between an attributes and the
-/// following item because empty lines and comments are not part of the AST. The parsing
-/// currently works for basic cases but is not perfect.
-///
-/// **Example:**
-/// ```rust
-/// // Bad
-/// #[inline(always)]
-///
-/// fn not_quite_good_code(..) { ... }
-///
-/// // Good (as inner attribute)
-/// #![inline(always)]
-///
-/// fn this_is_fine(..) { ... }
-///
-/// // Good (as outer attribute)
-/// #[inline(always)]
-/// fn this_is_fine_too(..) { ... }
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for empty lines after outer attributes
+    ///
+    /// **Why is this bad?**
+    /// Most likely the attribute was meant to be an inner attribute using a '!'.
+    /// If it was meant to be an outer attribute, then the following item
+    /// should not be separated by empty lines.
+    ///
+    /// **Known problems:** Can cause false positives.
+    ///
+    /// From the clippy side it's difficult to detect empty lines between an attributes and the
+    /// following item because empty lines and comments are not part of the AST. The parsing
+    /// currently works for basic cases but is not perfect.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// // Bad
+    /// #[inline(always)]
+    ///
+    /// fn not_quite_good_code(..) { ... }
+    ///
+    /// // Good (as inner attribute)
+    /// #![inline(always)]
+    ///
+    /// fn this_is_fine(..) { ... }
+    ///
+    /// // Good (as outer attribute)
+    /// #[inline(always)]
+    /// fn this_is_fine_too(..) { ... }
+    /// ```
     pub EMPTY_LINE_AFTER_OUTER_ATTR,
     nursery,
     "empty line after outer attribute"
 }
 
-/// **What it does:** Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy
-/// lints and if those lints exist in clippy. If there is a uppercase letter in the lint name
-/// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase
-/// the lint name.
-///
-/// **Why is this bad?** A lint attribute with a mistyped lint name won't have an effect.
-///
-/// **Known problems:** None.
-///
-/// **Example:**
-/// Bad:
-/// ```rust
-/// #![warn(if_not_els)]
-/// #![deny(clippy::All)]
-/// ```
-///
-/// Good:
-/// ```rust
-/// #![warn(if_not_else)]
-/// #![deny(clippy::all)]
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy
+    /// lints and if those lints exist in clippy. If there is a uppercase letter in the lint name
+    /// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase
+    /// the lint name.
+    ///
+    /// **Why is this bad?** A lint attribute with a mistyped lint name won't have an effect.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// Bad:
+    /// ```rust
+    /// #![warn(if_not_els)]
+    /// #![deny(clippy::All)]
+    /// ```
+    ///
+    /// Good:
+    /// ```rust
+    /// #![warn(if_not_else)]
+    /// #![deny(clippy::all)]
+    /// ```
     pub UNKNOWN_CLIPPY_LINTS,
     style,
     "unknown_lints for scoped Clippy lints"
 }
 
-/// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
-/// with `#[rustfmt::skip]`.
-///
-/// **Why is this bad?** Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))
-/// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.
-///
-/// **Known problems:** This lint doesn't detect crate level inner attributes, because they get
-/// processed before the PreExpansionPass lints get executed. See
-/// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
-///
-/// **Example:**
-///
-/// Bad:
-/// ```rust
-/// #[cfg_attr(rustfmt, rustfmt_skip)]
-/// fn main() { }
-/// ```
-///
-/// Good:
-/// ```rust
-/// #[rustfmt::skip]
-/// fn main() { }
-/// ```
 declare_clippy_lint! {
+    /// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
+    /// with `#[rustfmt::skip]`.
+    ///
+    /// **Why is this bad?** Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))
+    /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.
+    ///
+    /// **Known problems:** This lint doesn't detect crate level inner attributes, because they get
+    /// processed before the PreExpansionPass lints get executed. See
+    /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
+    ///
+    /// **Example:**
+    ///
+    /// Bad:
+    /// ```rust
+    /// #[cfg_attr(rustfmt, rustfmt_skip)]
+    /// fn main() { }
+    /// ```
+    ///
+    /// Good:
+    /// ```rust
+    /// #[rustfmt::skip]
+    /// fn main() { }
+    /// ```
     pub DEPRECATED_CFG_ATTR,
     complexity,
     "usage of `cfg_attr(rustfmt)` instead of `tool_attributes`"
 }
 
-#[derive(Copy, Clone)]
-pub struct AttrPass;
+declare_lint_pass!(Attributes => [
+    INLINE_ALWAYS,
+    DEPRECATED_SEMVER,
+    USELESS_ATTRIBUTE,
+    EMPTY_LINE_AFTER_OUTER_ATTR,
+    UNKNOWN_CLIPPY_LINTS,
+]);
 
-impl LintPass for AttrPass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            INLINE_ALWAYS,
-            DEPRECATED_SEMVER,
-            USELESS_ATTRIBUTE,
-            EMPTY_LINE_AFTER_OUTER_ATTR,
-            UNKNOWN_CLIPPY_LINTS,
-        )
-    }
-
-    fn name(&self) -> &'static str {
-        "Attributes"
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes {
     fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
         if let Some(items) = &attr.meta_item_list() {
-            match &*attr.name().as_str() {
-                "allow" | "warn" | "deny" | "forbid" => {
-                    check_clippy_lint_names(cx, items);
-                },
-                _ => {},
-            }
-            if items.is_empty() || attr.name() != "deprecated" {
-                return;
-            }
-            for item in items {
-                if_chain! {
-                    if let NestedMetaItemKind::MetaItem(mi) = &item.node;
-                    if let MetaItemKind::NameValue(lit) = &mi.node;
-                    if mi.name() == "since";
-                    then {
-                        check_semver(cx, item.span, lit);
+            if let Some(ident) = attr.ident() {
+                match &*ident.as_str() {
+                    "allow" | "warn" | "deny" | "forbid" => {
+                        check_clippy_lint_names(cx, items);
+                    },
+                    _ => {},
+                }
+                if items.is_empty() || !attr.check_name("deprecated") {
+                    return;
+                }
+                for item in items {
+                    if_chain! {
+                        if let NestedMetaItem::MetaItem(mi) = &item;
+                        if let MetaItemKind::NameValue(lit) = &mi.node;
+                        if mi.check_name("since");
+                        then {
+                            check_semver(cx, item.span(), lit);
+                        }
                     }
                 }
             }
@@ -231,60 +223,65 @@ fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute)
     }
 
     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
-        if is_relevant_item(cx.tcx, item) {
+        if is_relevant_item(cx, item) {
             check_attrs(cx, item.span, item.ident.name, &item.attrs)
         }
         match item.node {
             ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
-                let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use");
+                let skip_unused_imports = item.attrs.iter().any(|attr| attr.check_name("macro_use"));
 
                 for attr in &item.attrs {
+                    if in_external_macro(cx.sess(), attr.span) {
+                        return;
+                    }
                     if let Some(lint_list) = &attr.meta_item_list() {
-                        match &*attr.name().as_str() {
-                            "allow" | "warn" | "deny" | "forbid" => {
-                                // whitelist `unused_imports` and `deprecated` for `use` items
-                                // and `unused_imports` for `extern crate` items with `macro_use`
-                                for lint in lint_list {
-                                    match item.node {
-                                        ItemKind::Use(..) => {
-                                            if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
-                                                return;
-                                            }
-                                        },
-                                        ItemKind::ExternCrate(..) => {
-                                            if is_word(lint, "unused_imports") && skip_unused_imports {
-                                                return;
-                                            }
-                                            if is_word(lint, "unused_extern_crates") {
-                                                return;
-                                            }
-                                        },
-                                        _ => {},
-                                    }
-                                }
-                                let line_span = last_line_of_span(cx, attr.span);
-
-                                if let Some(mut sugg) = snippet_opt(cx, line_span) {
-                                    if sugg.contains("#[") {
-                                        span_lint_and_then(
-                                            cx,
-                                            USELESS_ATTRIBUTE,
-                                            line_span,
-                                            "useless lint attribute",
-                                            |db| {
-                                                sugg = sugg.replacen("#[", "#![", 1);
-                                                db.span_suggestion(
-                                                    line_span,
-                                                    "if you just forgot a `!`, use",
-                                                    sugg,
-                                                    Applicability::MachineApplicable,
-                                                );
+                        if let Some(ident) = attr.ident() {
+                            match &*ident.as_str() {
+                                "allow" | "warn" | "deny" | "forbid" => {
+                                    // whitelist `unused_imports` and `deprecated` for `use` items
+                                    // and `unused_imports` for `extern crate` items with `macro_use`
+                                    for lint in lint_list {
+                                        match item.node {
+                                            ItemKind::Use(..) => {
+                                                if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
+                                                    return;
+                                                }
                                             },
-                                        );
+                                            ItemKind::ExternCrate(..) => {
+                                                if is_word(lint, "unused_imports") && skip_unused_imports {
+                                                    return;
+                                                }
+                                                if is_word(lint, "unused_extern_crates") {
+                                                    return;
+                                                }
+                                            },
+                                            _ => {},
+                                        }
                                     }
-                                }
-                            },
-                            _ => {},
+                                    let line_span = last_line_of_span(cx, attr.span);
+
+                                    if let Some(mut sugg) = snippet_opt(cx, line_span) {
+                                        if sugg.contains("#[") {
+                                            span_lint_and_then(
+                                                cx,
+                                                USELESS_ATTRIBUTE,
+                                                line_span,
+                                                "useless lint attribute",
+                                                |db| {
+                                                    sugg = sugg.replacen("#[", "#![", 1);
+                                                    db.span_suggestion(
+                                                        line_span,
+                                                        "if you just forgot a `!`, use",
+                                                        sugg,
+                                                        Applicability::MachineApplicable,
+                                                    );
+                                                },
+                                            );
+                                        }
+                                    }
+                                },
+                                _ => {},
+                            }
                         }
                     }
                 }
@@ -294,13 +291,13 @@ fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
-        if is_relevant_impl(cx.tcx, item) {
+        if is_relevant_impl(cx, item) {
             check_attrs(cx, item.span, item.ident.name, &item.attrs)
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
-        if is_relevant_trait(cx.tcx, item) {
+        if is_relevant_trait(cx, item) {
             check_attrs(cx, item.span, item.ident.name, &item.attrs)
         }
     }
@@ -311,10 +308,11 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
     let lint_store = cx.lints();
     for lint in items {
         if_chain! {
-            if let Some(word) = lint.word();
-            if let Some(tool_name) = word.is_scoped();
+            if let Some(meta_item) = lint.meta_item();
+            if meta_item.path.segments.len() > 1;
+            if let tool_name = meta_item.path.segments[0].ident;
             if tool_name.as_str() == "clippy";
-            let name = word.name();
+            let name = meta_item.path.segments.last().unwrap().ident.name;
             if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(
                 &name.as_str(),
                 Some(tool_name.as_str()),
@@ -323,7 +321,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
                 span_lint_and_then(
                     cx,
                     UNKNOWN_CLIPPY_LINTS,
-                    lint.span,
+                    lint.span(),
                     &format!("unknown clippy lint: clippy::{}", name),
                     |db| {
                         if name.as_str().chars().any(char::is_uppercase) {
@@ -337,7 +335,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
                                 CheckLintNameResult::NoLint(None) => (),
                                 _ => {
                                     db.span_suggestion(
-                                        lint.span,
+                                        lint.span(),
                                         "lowercase the lint name",
                                         name_lower,
                                         Applicability::MaybeIncorrect,
@@ -352,52 +350,52 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
     }
 }
 
-fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
+fn is_relevant_item(cx: &LateContext<'_, '_>, item: &Item) -> bool {
     if let ItemKind::Fn(_, _, _, eid) = item.node {
-        is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
+        is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value)
     } else {
         true
     }
 }
 
-fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool {
+fn is_relevant_impl(cx: &LateContext<'_, '_>, item: &ImplItem) -> bool {
     match item.node {
-        ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value),
+        ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value),
         _ => false,
     }
 }
 
-fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
+fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem) -> bool {
     match item.node {
         TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
         TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
-            is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
+            is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value)
         },
         _ => false,
     }
 }
 
-fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
+fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
     if let Some(stmt) = block.stmts.first() {
         match &stmt.node {
             StmtKind::Local(_) => true,
-            StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(tcx, tables, expr),
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, tables, expr),
             _ => false,
         }
     } else {
-        block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
+        block.expr.as_ref().map_or(false, |e| is_relevant_expr(cx, tables, e))
     }
 }
 
-fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
+fn is_relevant_expr(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
     match &expr.node {
-        ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block),
-        ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e),
+        ExprKind::Block(block, _) => is_relevant_block(cx, tables, block),
+        ExprKind::Ret(Some(e)) => is_relevant_expr(cx, tables, e),
         ExprKind::Ret(None) | ExprKind::Break(_, None) => false,
         ExprKind::Call(path_expr, _) => {
             if let ExprKind::Path(qpath) = &path_expr.node {
-                if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
-                    !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
+                if let Some(fun_id) = tables.qpath_def(qpath, path_expr.hir_id).opt_def_id() {
+                    !cx.match_def_path(fun_id, &paths::BEGIN_PANIC)
                 } else {
                     true
                 }
@@ -443,7 +441,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib
         }
 
         if let Some(values) = attr.meta_item_list() {
-            if values.len() != 1 || attr.name() != "inline" {
+            if values.len() != 1 || !attr.check_name("inline") {
                 continue;
             }
             if is_word(&values[0], "always") {
@@ -476,8 +474,8 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
 }
 
 fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
-    if let NestedMetaItemKind::MetaItem(mi) = &nmi.node {
-        mi.is_word() && mi.name() == expected
+    if let NestedMetaItem::MetaItem(mi) = &nmi {
+        mi.is_word() && mi.check_name(expected)
     } else {
         false
     }
@@ -497,32 +495,22 @@ fn is_present_in_source(cx: &LateContext<'_, '_>, span: Span) -> bool {
     true
 }
 
-#[derive(Copy, Clone)]
-pub struct CfgAttrPass;
-
-impl LintPass for CfgAttrPass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(DEPRECATED_CFG_ATTR,)
-    }
-
-    fn name(&self) -> &'static str {
-        "DeprecatedCfgAttribute"
-    }
-}
+declare_lint_pass!(DeprecatedCfgAttribute => [DEPRECATED_CFG_ATTR]);
 
-impl EarlyLintPass for CfgAttrPass {
+impl EarlyLintPass for DeprecatedCfgAttribute {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         if_chain! {
             // check cfg_attr
-            if attr.name() == "cfg_attr";
+            if attr.check_name("cfg_attr");
             if let Some(items) = attr.meta_item_list();
             if items.len() == 2;
             // check for `rustfmt`
             if let Some(feature_item) = items[0].meta_item();
-            if feature_item.name() == "rustfmt";
+            if feature_item.check_name("rustfmt");
             // check for `rustfmt_skip` and `rustfmt::skip`
             if let Some(skip_item) = &items[1].meta_item();
-            if skip_item.name() == "rustfmt_skip" || skip_item.name() == "skip";
+            if skip_item.check_name("rustfmt_skip") ||
+                skip_item.path.segments.last().expect("empty path in attribute").ident.name == "skip";
             // Only lint outer attributes, because custom inner attributes are unstable
             // Tracking issue: https://github.com/rust-lang/rust/issues/54726
             if let AttrStyle::Outer = attr.style;