diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2d8a2c6321fa8..dc5894cd6b91f 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -392,81 +392,72 @@ declare_lint! {
     "nested occurrence of `impl Trait` type"
 }
 
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// that are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct HardwiredLints;
-
-impl LintPass for HardwiredLints {
-    fn name(&self) -> &'static str {
-        "HardwiredLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-            EXCEEDING_BITSHIFTS,
-            UNUSED_IMPORTS,
-            UNUSED_EXTERN_CRATES,
-            UNUSED_QUALIFICATIONS,
-            UNKNOWN_LINTS,
-            UNUSED_VARIABLES,
-            UNUSED_ASSIGNMENTS,
-            DEAD_CODE,
-            UNREACHABLE_CODE,
-            UNREACHABLE_PATTERNS,
-            UNUSED_MACROS,
-            WARNINGS,
-            UNUSED_FEATURES,
-            STABLE_FEATURES,
-            UNKNOWN_CRATE_TYPES,
-            TRIVIAL_CASTS,
-            TRIVIAL_NUMERIC_CASTS,
-            PRIVATE_IN_PUBLIC,
-            EXPORTED_PRIVATE_DEPENDENCIES,
-            PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-            INVALID_TYPE_PARAM_DEFAULT,
-            CONST_ERR,
-            RENAMED_AND_REMOVED_LINTS,
-            SAFE_EXTERN_STATICS,
-            SAFE_PACKED_BORROWS,
-            PATTERNS_IN_FNS_WITHOUT_BODY,
-            LEGACY_DIRECTORY_OWNERSHIP,
-            LEGACY_CONSTRUCTOR_VISIBILITY,
-            MISSING_FRAGMENT_SPECIFIER,
-            PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-            LATE_BOUND_LIFETIME_ARGUMENTS,
-            INCOHERENT_FUNDAMENTAL_IMPLS,
-            ORDER_DEPENDENT_TRAIT_OBJECTS,
-            DEPRECATED,
-            UNUSED_UNSAFE,
-            UNUSED_MUT,
-            UNCONDITIONAL_RECURSION,
-            SINGLE_USE_LIFETIMES,
-            UNUSED_LIFETIMES,
-            UNUSED_LABELS,
-            TYVAR_BEHIND_RAW_POINTER,
-            ELIDED_LIFETIMES_IN_PATHS,
-            BARE_TRAIT_OBJECTS,
-            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-            UNSTABLE_NAME_COLLISIONS,
-            IRREFUTABLE_LET_PATTERNS,
-            DUPLICATE_MACRO_EXPORTS,
-            INTRA_DOC_LINK_RESOLUTION_FAILURE,
-            MISSING_DOC_CODE_EXAMPLES,
-            PRIVATE_DOC_TESTS,
-            WHERE_CLAUSES_OBJECT_SAFETY,
-            PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-            MACRO_USE_EXTERN_CRATE,
-            MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-            parser::QUESTION_MARK_MACRO_SEP,
-            parser::ILL_FORMED_ATTRIBUTE_INPUT,
-            DEPRECATED_IN_FUTURE,
-            AMBIGUOUS_ASSOCIATED_ITEMS,
-            NESTED_IMPL_TRAIT,
-            DUPLICATE_MATCHER_BINDING_NAME,
-        )
-    }
+declare_lint_pass! {
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// that are used by other parts of the compiler.
+    HardwiredLints => [
+        ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+        EXCEEDING_BITSHIFTS,
+        UNUSED_IMPORTS,
+        UNUSED_EXTERN_CRATES,
+        UNUSED_QUALIFICATIONS,
+        UNKNOWN_LINTS,
+        UNUSED_VARIABLES,
+        UNUSED_ASSIGNMENTS,
+        DEAD_CODE,
+        UNREACHABLE_CODE,
+        UNREACHABLE_PATTERNS,
+        UNUSED_MACROS,
+        WARNINGS,
+        UNUSED_FEATURES,
+        STABLE_FEATURES,
+        UNKNOWN_CRATE_TYPES,
+        TRIVIAL_CASTS,
+        TRIVIAL_NUMERIC_CASTS,
+        PRIVATE_IN_PUBLIC,
+        EXPORTED_PRIVATE_DEPENDENCIES,
+        PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+        INVALID_TYPE_PARAM_DEFAULT,
+        CONST_ERR,
+        RENAMED_AND_REMOVED_LINTS,
+        SAFE_EXTERN_STATICS,
+        SAFE_PACKED_BORROWS,
+        PATTERNS_IN_FNS_WITHOUT_BODY,
+        LEGACY_DIRECTORY_OWNERSHIP,
+        LEGACY_CONSTRUCTOR_VISIBILITY,
+        MISSING_FRAGMENT_SPECIFIER,
+        PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+        LATE_BOUND_LIFETIME_ARGUMENTS,
+        INCOHERENT_FUNDAMENTAL_IMPLS,
+        ORDER_DEPENDENT_TRAIT_OBJECTS,
+        DEPRECATED,
+        UNUSED_UNSAFE,
+        UNUSED_MUT,
+        UNCONDITIONAL_RECURSION,
+        SINGLE_USE_LIFETIMES,
+        UNUSED_LIFETIMES,
+        UNUSED_LABELS,
+        TYVAR_BEHIND_RAW_POINTER,
+        ELIDED_LIFETIMES_IN_PATHS,
+        BARE_TRAIT_OBJECTS,
+        ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
+        UNSTABLE_NAME_COLLISIONS,
+        IRREFUTABLE_LET_PATTERNS,
+        DUPLICATE_MACRO_EXPORTS,
+        INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        MISSING_DOC_CODE_EXAMPLES,
+        PRIVATE_DOC_TESTS,
+        WHERE_CLAUSES_OBJECT_SAFETY,
+        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
+        MACRO_USE_EXTERN_CRATE,
+        MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+        parser::QUESTION_MARK_MACRO_SEP,
+        parser::ILL_FORMED_ATTRIBUTE_INPUT,
+        DEPRECATED_IN_FUTURE,
+        AMBIGUOUS_ASSOCIATED_ITEMS,
+        NESTED_IMPL_TRAIT,
+        DUPLICATE_MATCHER_BINDING_NAME,
+    ]
 }
 
 // this could be a closure, but then implementing derive traits
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index a5506bb8f59f4..e1807026e6d2e 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -181,6 +181,27 @@ pub trait LintPass {
     fn get_lints(&self) -> LintArray;
 }
 
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+            fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
+
 #[macro_export]
 macro_rules! late_lint_methods {
     ($macro:path, $args:tt, [$hir:tt]) => (
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 1fae931e9f1fd..cf9795941bdc7 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -63,18 +63,7 @@ declare_lint! {
     "suggest using `loop { }` instead of `while true { }`"
 }
 
-#[derive(Copy, Clone)]
-pub struct WhileTrue;
-
-impl LintPass for WhileTrue {
-    fn name(&self) -> &'static str {
-        "WhileTrue"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(WHILE_TRUE)
-    }
-}
+declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
@@ -105,8 +94,7 @@ declare_lint! {
     "use of owned (Box type) heap memory"
 }
 
-#[derive(Copy, Clone)]
-pub struct BoxPointers;
+declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
 
 impl BoxPointers {
     fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) {
@@ -119,16 +107,6 @@ impl BoxPointers {
     }
 }
 
-impl LintPass for BoxPointers {
-    fn name(&self) -> &'static str {
-        "BoxPointers"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BOX_POINTERS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
@@ -169,18 +147,7 @@ declare_lint! {
     "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonShorthandFieldPatterns;
-
-impl LintPass for NonShorthandFieldPatterns {
-    fn name(&self) -> &'static str {
-        "NonShorthandFieldPatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
-    }
-}
+declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat) {
@@ -226,18 +193,7 @@ declare_lint! {
     "usage of `unsafe` code"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafeCode;
-
-impl LintPass for UnsafeCode {
-    fn name(&self) -> &'static str {
-        "UnsafeCode"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSAFE_CODE)
-    }
-}
+declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
 
 impl UnsafeCode {
     fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, desc: &'static str) {
@@ -327,6 +283,8 @@ pub struct MissingDoc {
     private_traits: FxHashSet<hir::HirId>,
 }
 
+impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
+
 fn has_doc(attr: &ast::Attribute) -> bool {
     if !attr.check_name("doc") {
         return false;
@@ -394,16 +352,6 @@ impl MissingDoc {
     }
 }
 
-impl LintPass for MissingDoc {
-    fn name(&self) -> &'static str {
-        "MissingDoc"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DOCS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext<'_, '_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden() ||
@@ -541,18 +489,7 @@ declare_lint! {
     "detects potentially-forgotten implementations of `Copy`"
 }
 
-#[derive(Copy, Clone)]
-pub struct MissingCopyImplementations;
-
-impl LintPass for MissingCopyImplementations {
-    fn name(&self) -> &'static str {
-        "MissingCopyImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
-    }
-}
+declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -609,22 +546,14 @@ pub struct MissingDebugImplementations {
     impling_types: Option<HirIdSet>,
 }
 
+impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
+
 impl MissingDebugImplementations {
     pub fn new() -> MissingDebugImplementations {
         MissingDebugImplementations { impling_types: None }
     }
 }
 
-impl LintPass for MissingDebugImplementations {
-    fn name(&self) -> &'static str {
-        "MissingDebugImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         if !cx.access_levels.is_reachable(item.hir_id) {
@@ -672,19 +601,10 @@ declare_lint! {
     "detects anonymous parameters"
 }
 
-/// Checks for use of anonymous parameters (RFC 1685).
-#[derive(Copy, Clone)]
-pub struct AnonymousParameters;
-
-impl LintPass for AnonymousParameters {
-    fn name(&self) -> &'static str {
-        "AnonymousParameters"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ANONYMOUS_PARAMETERS)
-    }
-}
+declare_lint_pass!(
+    /// Checks for use of anonymous parameters (RFC 1685).
+    AnonymousParameters => [ANONYMOUS_PARAMETERS]
+);
 
 impl EarlyLintPass for AnonymousParameters {
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
@@ -736,6 +656,8 @@ pub struct DeprecatedAttr {
     depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeTemplate, AttributeGate)>,
 }
 
+impl_lint_pass!(DeprecatedAttr => []);
+
 impl DeprecatedAttr {
     pub fn new() -> DeprecatedAttr {
         DeprecatedAttr {
@@ -744,16 +666,6 @@ impl DeprecatedAttr {
     }
 }
 
-impl LintPass for DeprecatedAttr {
-    fn name(&self) -> &'static str {
-        "DeprecatedAttr"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
-
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         let name = attr.name_or_empty();
@@ -786,18 +698,7 @@ declare_lint! {
     "detects doc comments that aren't used by rustdoc"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedDocComment;
-
-impl LintPass for UnusedDocComment {
-    fn name(&self) -> &'static str {
-        "UnusedDocComment"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![UNUSED_DOC_COMMENTS]
-    }
-}
+declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
 
 impl UnusedDocComment {
     fn warn_if_doc(
@@ -884,18 +785,7 @@ declare_lint! {
     "compiler plugin used as ordinary library in non-plugin crate"
 }
 
-#[derive(Copy, Clone)]
-pub struct PluginAsLibrary;
-
-impl LintPass for PluginAsLibrary {
-    fn name(&self) -> &'static str {
-        "PluginAsLibrary"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![PLUGIN_AS_LIBRARY]
-    }
-}
+declare_lint_pass!(PluginAsLibrary => [PLUGIN_AS_LIBRARY]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -940,19 +830,7 @@ declare_lint! {
     "generic items must be mangled"
 }
 
-#[derive(Copy, Clone)]
-pub struct InvalidNoMangleItems;
-
-impl LintPass for InvalidNoMangleItems {
-    fn name(&self) -> &'static str {
-        "InvalidNoMangleItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NO_MANGLE_CONST_ITEMS,
-                    NO_MANGLE_GENERIC_ITEMS)
-    }
-}
+declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -1011,24 +889,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct MutableTransmutes;
-
 declare_lint! {
     MUTABLE_TRANSMUTES,
     Deny,
     "mutating transmuted &mut T from &T may cause undefined behavior"
 }
 
-impl LintPass for MutableTransmutes {
-    fn name(&self) -> &'static str {
-        "MutableTransmutes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MUTABLE_TRANSMUTES)
-    }
-}
+declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr) {
@@ -1074,25 +941,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     }
 }
 
-/// Forbids using the `#[feature(...)]` attribute
-#[derive(Copy, Clone)]
-pub struct UnstableFeatures;
-
 declare_lint! {
     UNSTABLE_FEATURES,
     Allow,
     "enabling unstable features (deprecated. do not use)"
 }
 
-impl LintPass for UnstableFeatures {
-    fn name(&self) -> &'static str {
-        "UnstableFeatures"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSTABLE_FEATURES)
-    }
-}
+declare_lint_pass!(
+    /// Forbids using the `#[feature(...)]` attribute
+    UnstableFeatures => [UNSTABLE_FEATURES]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     fn check_attribute(&mut self, ctx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -1106,24 +964,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     }
 }
 
-/// Lint for unions that contain fields with possibly non-trivial destructors.
-pub struct UnionsWithDropFields;
-
 declare_lint! {
     UNIONS_WITH_DROP_FIELDS,
     Warn,
     "use of unions that contain fields with possibly non-trivial drop code"
 }
 
-impl LintPass for UnionsWithDropFields {
-    fn name(&self) -> &'static str {
-        "UnionsWithDropFields"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNIONS_WITH_DROP_FIELDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for unions that contain fields with possibly non-trivial destructors.
+    UnionsWithDropFields => [UNIONS_WITH_DROP_FIELDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -1143,25 +993,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     }
 }
 
-/// Lint for items marked `pub` that aren't reachable from other crates.
-#[derive(Copy, Clone)]
-pub struct UnreachablePub;
-
 declare_lint! {
     pub UNREACHABLE_PUB,
     Allow,
     "`pub` items not reachable from crate root"
 }
 
-impl LintPass for UnreachablePub {
-    fn name(&self) -> &'static str {
-        "UnreachablePub"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNREACHABLE_PUB)
-    }
-}
+declare_lint_pass!(
+    /// Lint for items marked `pub` that aren't reachable from other crates.
+    UnreachablePub => [UNREACHABLE_PUB]
+);
 
 impl UnreachablePub {
     fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: hir::HirId,
@@ -1197,7 +1038,6 @@ impl UnreachablePub {
     }
 }
 
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
@@ -1217,27 +1057,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     }
 }
 
-/// Lint for trait and lifetime bounds in type aliases being mostly ignored.
-/// They are relevant when using associated types, but otherwise neither checked
-/// at definition site nor enforced at use site.
-
-pub struct TypeAliasBounds;
-
 declare_lint! {
     TYPE_ALIAS_BOUNDS,
     Warn,
     "bounds in type aliases are not enforced"
 }
 
-impl LintPass for TypeAliasBounds {
-    fn name(&self) -> &'static str {
-        "TypeAliasBounds"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TYPE_ALIAS_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds in type aliases being mostly ignored.
+    /// They are relevant when using associated types, but otherwise neither checked
+    /// at definition site nor enforced at use site.
+    TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
+);
 
 impl TypeAliasBounds {
     fn is_type_variable_assoc(qpath: &hir::QPath) -> bool {
@@ -1331,21 +1162,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
     }
 }
 
-/// Lint constants that are erroneous.
-/// Without this lint, we might not get any diagnostic if the constant is
-/// unused within this crate, even though downstream crates can't use it
-/// without producing an error.
-pub struct UnusedBrokenConst;
-
-impl LintPass for UnusedBrokenConst {
-    fn name(&self) -> &'static str {
-        "UnusedBrokenConst"
-    }
+declare_lint_pass!(
+    /// Lint constants that are erroneous.
+    /// Without this lint, we might not get any diagnostic if the constant is
+    /// unused within this crate, even though downstream crates can't use it
+    /// without producing an error.
+    UnusedBrokenConst => []
+);
 
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
 fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
     let def_id = cx.tcx.hir().body_owner_def_id(body_id);
     let is_static = cx.tcx.is_static(def_id).is_some();
@@ -1378,25 +1202,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
     }
 }
 
-/// Lint for trait and lifetime bounds that don't depend on type parameters
-/// which either do nothing, or stop the item from being used.
-pub struct TrivialConstraints;
-
 declare_lint! {
     TRIVIAL_BOUNDS,
     Warn,
     "these bounds don't depend on an type parameters"
 }
 
-impl LintPass for TrivialConstraints {
-    fn name(&self) -> &'static str {
-        "TrivialConstraints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TRIVIAL_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds that don't depend on type parameters
+    /// which either do nothing, or stop the item from being used.
+    TrivialConstraints => [TRIVIAL_BOUNDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     fn check_item(
@@ -1440,40 +1256,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     }
 }
 
-
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// which are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct SoftLints;
-
-impl LintPass for SoftLints {
-    fn name(&self) -> &'static str {
-        "SoftLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            WHILE_TRUE,
-            BOX_POINTERS,
-            NON_SHORTHAND_FIELD_PATTERNS,
-            UNSAFE_CODE,
-            MISSING_DOCS,
-            MISSING_COPY_IMPLEMENTATIONS,
-            MISSING_DEBUG_IMPLEMENTATIONS,
-            ANONYMOUS_PARAMETERS,
-            UNUSED_DOC_COMMENTS,
-            PLUGIN_AS_LIBRARY,
-            NO_MANGLE_CONST_ITEMS,
-            NO_MANGLE_GENERIC_ITEMS,
-            MUTABLE_TRANSMUTES,
-            UNSTABLE_FEATURES,
-            UNIONS_WITH_DROP_FIELDS,
-            UNREACHABLE_PUB,
-            TYPE_ALIAS_BOUNDS,
-            TRIVIAL_BOUNDS
-        )
-    }
-}
+declare_lint_pass!(
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// which are used by other parts of the compiler.
+    SoftLints => [
+        WHILE_TRUE,
+        BOX_POINTERS,
+        NON_SHORTHAND_FIELD_PATTERNS,
+        UNSAFE_CODE,
+        MISSING_DOCS,
+        MISSING_COPY_IMPLEMENTATIONS,
+        MISSING_DEBUG_IMPLEMENTATIONS,
+        ANONYMOUS_PARAMETERS,
+        UNUSED_DOC_COMMENTS,
+        PLUGIN_AS_LIBRARY,
+        NO_MANGLE_CONST_ITEMS,
+        NO_MANGLE_GENERIC_ITEMS,
+        MUTABLE_TRANSMUTES,
+        UNSTABLE_FEATURES,
+        UNIONS_WITH_DROP_FIELDS,
+        UNREACHABLE_PUB,
+        TYPE_ALIAS_BOUNDS,
+        TRIVIAL_BOUNDS
+    ]
+);
 
 declare_lint! {
     pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
@@ -1481,18 +1287,7 @@ declare_lint! {
     "`...` range patterns are deprecated"
 }
 
-
-pub struct EllipsisInclusiveRangePatterns;
-
-impl LintPass for EllipsisInclusiveRangePatterns {
-    fn name(&self) -> &'static str {
-        "EllipsisInclusiveRangePatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS)
-    }
-}
+declare_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);
 
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat, visit_subpats: &mut bool) {
@@ -1553,6 +1348,8 @@ pub struct UnnameableTestItems {
     items_nameable: bool,
 }
 
+impl_lint_pass!(UnnameableTestItems => [UNNAMEABLE_TEST_ITEMS]);
+
 impl UnnameableTestItems {
     pub fn new() -> Self {
         Self {
@@ -1562,16 +1359,6 @@ impl UnnameableTestItems {
     }
 }
 
-impl LintPass for UnnameableTestItems {
-    fn name(&self) -> &'static str {
-        "UnnameableTestItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNNAMEABLE_TEST_ITEMS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         if self.items_nameable {
@@ -1605,19 +1392,10 @@ declare_lint! {
     "detects edition keywords being used as an identifier"
 }
 
-/// Check for uses of edition keywords used as an identifier.
-#[derive(Copy, Clone)]
-pub struct KeywordIdents;
-
-impl LintPass for KeywordIdents {
-    fn name(&self) -> &'static str {
-        "KeywordIdents"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(KEYWORD_IDENTS)
-    }
-}
+declare_lint_pass!(
+    /// Check for uses of edition keywords used as an identifier.
+    KeywordIdents => [KEYWORD_IDENTS]
+);
 
 struct UnderMacro(bool);
 
@@ -1740,18 +1518,7 @@ impl EarlyLintPass for KeywordIdents {
     }
 }
 
-
-pub struct ExplicitOutlivesRequirements;
-
-impl LintPass for ExplicitOutlivesRequirements {
-    fn name(&self) -> &'static str {
-        "ExplicitOutlivesRequirements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![EXPLICIT_OUTLIVES_REQUIREMENTS]
-    }
-}
+declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);
 
 impl ExplicitOutlivesRequirements {
     fn collect_outlives_bound_spans(
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 7a164dbcdf12d..1d8979f7d1c1b 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -38,6 +38,8 @@ declare_lint! {
     "types, variants, traits and type parameters should have camel case names"
 }
 
+declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]);
+
 fn char_has_case(c: char) -> bool {
     c.is_lowercase() || c.is_uppercase()
 }
@@ -105,9 +107,6 @@ fn to_camel_case(s: &str) -> String {
         .0
 }
 
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
 impl NonCamelCaseTypes {
     fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
         let name = &ident.name.as_str();
@@ -126,16 +125,6 @@ impl NonCamelCaseTypes {
     }
 }
 
-impl LintPass for NonCamelCaseTypes {
-    fn name(&self) -> &'static str {
-        "NonCamelCaseTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-}
-
 impl EarlyLintPass for NonCamelCaseTypes {
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         let has_repr_c = it.attrs
@@ -173,8 +162,7 @@ declare_lint! {
     "variables, methods, functions, lifetime parameters and modules should have snake case names"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
+declare_lint_pass!(NonSnakeCase => [NON_SNAKE_CASE]);
 
 impl NonSnakeCase {
     fn to_snake_case(mut str: &str) -> String {
@@ -256,16 +244,6 @@ impl NonSnakeCase {
     }
 }
 
-impl LintPass for NonSnakeCase {
-    fn name(&self) -> &'static str {
-        "NonSnakeCase"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) {
         if id != hir::CRATE_HIR_ID {
@@ -387,8 +365,7 @@ declare_lint! {
     "static constants should have uppercase identifiers"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
+declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
 
 impl NonUpperCaseGlobals {
     fn check_upper_case(cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) {
@@ -410,16 +387,6 @@ impl NonUpperCaseGlobals {
     }
 }
 
-impl LintPass for NonUpperCaseGlobals {
-    fn name(&self) -> &'static str {
-        "NonUpperCaseGlobals"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 494a9bb73ed4b..77c948023bbd5 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -49,23 +49,14 @@ pub struct TypeLimits {
     negated_expr_id: hir::HirId,
 }
 
+impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS]);
+
 impl TypeLimits {
     pub fn new() -> TypeLimits {
         TypeLimits { negated_expr_id: hir::DUMMY_HIR_ID }
     }
 }
 
-impl LintPass for TypeLimits {
-    fn name(&self) -> &'static str {
-        "TypeLimits"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_COMPARISONS,
-                    OVERFLOWING_LITERALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
         match e.node {
@@ -424,6 +415,8 @@ declare_lint! {
     "proper use of libc types in foreign modules"
 }
 
+declare_lint_pass!(ImproperCTypes => [IMPROPER_CTYPES]);
+
 struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
     cx: &'a LateContext<'a, 'tcx>,
 }
@@ -793,19 +786,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct ImproperCTypes;
-
-impl LintPass for ImproperCTypes {
-    fn name(&self) -> &'static str {
-        "ImproperCTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IMPROPER_CTYPES)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
         let mut vis = ImproperCTypesVisitor { cx };
@@ -824,17 +804,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     }
 }
 
-pub struct VariantSizeDifferences;
-
-impl LintPass for VariantSizeDifferences {
-    fn name(&self) -> &'static str {
-        "VariantSizeDifferences"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(VARIANT_SIZE_DIFFERENCES)
-    }
-}
+declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 37c147d93d85c..d41d97f58bcbe 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -32,18 +32,7 @@ declare_lint! {
     "unused result of an expression in a statement"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedResults;
-
-impl LintPass for UnusedResults {
-    fn name(&self) -> &'static str {
-        "UnusedResults"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
-    }
-}
+declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -203,18 +192,7 @@ declare_lint! {
     "path statements with no effect"
 }
 
-#[derive(Copy, Clone)]
-pub struct PathStatements;
-
-impl LintPass for PathStatements {
-    fn name(&self) -> &'static str {
-        "PathStatements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PATH_STATEMENTS)
-    }
-}
+declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -232,18 +210,7 @@ declare_lint! {
     "detects attributes that were not used by the compiler"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAttributes;
-
-impl LintPass for UnusedAttributes {
-    fn name(&self) -> &'static str {
-        "UnusedAttributes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ATTRIBUTES)
-    }
-}
+declare_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -305,8 +272,7 @@ declare_lint! {
     "`if`, `match`, `while` and `return` do not need parentheses"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedParens;
+declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
 
 impl UnusedParens {
     fn check_unused_parens_expr(&self,
@@ -383,16 +349,6 @@ impl UnusedParens {
     }
 }
 
-impl LintPass for UnusedParens {
-    fn name(&self) -> &'static str {
-        "UnusedParens"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_PARENS)
-    }
-}
-
 impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         use syntax::ast::ExprKind::*;
@@ -465,8 +421,7 @@ declare_lint! {
     "unnecessary braces around an imported item"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedImportBraces;
+declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
 
 impl UnusedImportBraces {
     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
@@ -505,16 +460,6 @@ impl UnusedImportBraces {
     }
 }
 
-impl LintPass for UnusedImportBraces {
-    fn name(&self) -> &'static str {
-        "UnusedImportBraces"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_IMPORT_BRACES)
-    }
-}
-
 impl EarlyLintPass for UnusedImportBraces {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
         if let ast::ItemKind::Use(ref use_tree) = item.node {
@@ -529,18 +474,7 @@ declare_lint! {
     "detects unnecessary allocations that can be eliminated"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAllocation;
-
-impl LintPass for UnusedAllocation {
-    fn name(&self) -> &'static str {
-        "UnusedAllocation"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ALLOCATION)
-    }
-}
+declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
index 09aa106ebbd9f..76d0906f97c9a 100644
--- a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -26,21 +26,14 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_attribute("whitelisted_attr".to_string(), Whitelisted);
 }
 
-declare_lint!(MISSING_WHITELISTED_ATTR, Deny,
-              "Checks for missing `whitelisted_attr` attribute");
-
-struct MissingWhitelistedAttrPass;
-
-impl LintPass for MissingWhitelistedAttrPass {
-    fn name(&self) -> &'static str {
-        "MissingWhitelistedAttrPass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_WHITELISTED_ATTR)
-    }
+declare_lint! {
+    MISSING_WHITELISTED_ATTR,
+    Deny,
+    "Checks for missing `whitelisted_attr` attribute"
 }
 
+declare_lint_pass!(MissingWhitelistedAttrPass => [MISSING_WHITELISTED_ATTR]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass {
     fn check_fn(&mut self,
                 cx: &LateContext<'a, 'tcx>,
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 82aa28b26b648..e8f1d2eedf559 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -12,20 +12,14 @@ use rustc_plugin::Registry;
 use rustc::hir;
 use syntax::attr;
 
-declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
-
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(CRATE_NOT_OKAY)
-    }
+declare_lint! {
+    CRATE_NOT_OKAY,
+    Warn,
+    "crate not marked with #![crate_okay]"
 }
 
+declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
         if !attr::contains_name(&krate.attrs, "crate_okay") {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 16630e2b31285..941fe25b14c70 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -16,17 +16,7 @@ declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, PLEASE_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 4e45189b42427..1d204e7bfcffa 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -16,17 +16,7 @@ use rustc_plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index d25a5ea374627..182d2899da185 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -19,17 +19,7 @@ declare_tool_lint!(
     Warn, "Warn about other stuff"
 );
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, TEST_GROUP)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {