about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml3
-rw-r--r--clippy_lints/src/attrs.rs160
-rw-r--r--clippy_lints/src/consts.rs6
-rw-r--r--clippy_lints/src/doc.rs2
-rw-r--r--clippy_lints/src/enum_glob_use.rs3
-rw-r--r--clippy_lints/src/eta_reduction.rs34
-rw-r--r--clippy_lints/src/fallible_impl_from.rs4
-rw-r--r--clippy_lints/src/functions.rs3
-rw-r--r--clippy_lints/src/inline_fn_without_body.rs2
-rw-r--r--clippy_lints/src/len_zero.rs11
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/lifetimes.rs3
-rw-r--r--clippy_lints/src/map_unit_fn.rs4
-rw-r--r--clippy_lints/src/matches.rs6
-rw-r--r--clippy_lints/src/methods/mod.rs7
-rw-r--r--clippy_lints/src/missing_doc.rs21
-rw-r--r--clippy_lints/src/missing_inline.rs18
-rw-r--r--clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--clippy_lints/src/new_without_default.rs3
-rw-r--r--clippy_lints/src/no_effect.rs6
-rw-r--r--clippy_lints/src/non_copy_const.rs4
-rw-r--r--clippy_lints/src/question_mark.rs2
-rw-r--r--clippy_lints/src/ranges.rs13
-rw-r--r--clippy_lints/src/redundant_clone.rs6
-rw-r--r--clippy_lints/src/returns.rs2
-rw-r--r--clippy_lints/src/transmute.rs2
-rw-r--r--clippy_lints/src/trivially_copy_pass_by_ref.rs2
-rw-r--r--clippy_lints/src/types.rs17
-rw-r--r--clippy_lints/src/use_self.rs5
-rw-r--r--clippy_lints/src/utils/conf.rs8
-rw-r--r--clippy_lints/src/utils/mod.rs128
-rw-r--r--clippy_lints/src/vec.rs5
-rw-r--r--doc/adding_lints.md4
-rw-r--r--src/driver.rs2
-rw-r--r--tests/compile-test.rs47
-rw-r--r--tests/ui/for_loop.stderr26
-rw-r--r--tests/ui/into_iter_on_ref.fixed2
-rw-r--r--tests/ui/into_iter_on_ref.stderr14
-rw-r--r--tests/ui/literals.rs18
-rw-r--r--tests/ui/literals.stderr110
-rw-r--r--tests/ui/missing-doc-crate-missing.rs3
-rw-r--r--tests/ui/missing-doc-crate-missing.stderr12
-rw-r--r--tests/ui/missing-doc-crate.rs5
-rw-r--r--tests/ui/missing-doc-crate.stderr0
-rw-r--r--tests/ui/mistyped_literal_suffix.fixed22
-rw-r--r--tests/ui/mistyped_literal_suffix.rs22
-rw-r--r--tests/ui/mistyped_literal_suffix.stderr76
-rw-r--r--tests/ui/needless_pass_by_value.rs2
-rw-r--r--tests/ui/unreadable_literal.fixed5
-rw-r--r--tests/ui/unreadable_literal.rs5
-rw-r--r--tests/ui/unreadable_literal.stderr26
-rw-r--r--tests/ui/use_self.fixed1
-rw-r--r--tests/ui/use_self.rs1
-rw-r--r--tests/ui/use_self.stderr14
-rw-r--r--tests/ui/useless_asref.fixed136
-rw-r--r--tests/ui/useless_asref.rs4
-rw-r--r--tests/ui/useless_asref.stderr24
57 files changed, 701 insertions, 374 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 024b8ff28ad..3d36e52d2df 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,7 +47,8 @@ rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"}
 [dev-dependencies]
 clippy_dev = { version = "0.0.1", path = "clippy_dev" }
 cargo_metadata = "0.7.1"
-compiletest_rs = "0.3.19"
+compiletest_rs = { version = "=0.3.19", features = ["tmp", "stable"] }
+libtest = "0.0.1"
 lazy_static = "1.0"
 serde_derive = "1.0"
 clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index ab3b7e471ac..c054a00894e 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -14,7 +14,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::{declare_tool_lint, lint_array};
 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;
 
 declare_clippy_lint! {
@@ -208,22 +208,24 @@ impl LintPass for AttrPass {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
     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);
+                        }
                     }
                 }
             }
@@ -236,55 +238,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
         }
         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 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,
+                                                    );
+                                                },
+                                            );
+                                        }
+                                    }
+                                },
+                                _ => {},
+                            }
                         }
                     }
                 }
@@ -311,10 +315,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 +328,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 +342,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,7 +357,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
     }
 }
 
-fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
+fn is_relevant_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &Item) -> bool {
     if let ItemKind::Fn(_, _, _, eid) = item.node {
         is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
     } else {
@@ -360,14 +365,14 @@ fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
     }
 }
 
-fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool {
+fn is_relevant_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &ImplItem) -> bool {
     match item.node {
         ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value),
         _ => false,
     }
 }
 
-fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
+fn is_relevant_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &TraitItem) -> bool {
     match item.node {
         TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
         TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
@@ -377,7 +382,7 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
     }
 }
 
-fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
+fn is_relevant_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
     if let Some(stmt) = block.stmts.first() {
         match &stmt.node {
             StmtKind::Local(_) => true,
@@ -389,7 +394,7 @@ fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, blo
     }
 }
 
-fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
+fn is_relevant_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 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),
@@ -443,7 +448,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 +481,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
     }
@@ -514,15 +519,16 @@ impl EarlyLintPass for CfgAttrPass {
     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;
diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs
index 8d71eb54277..61bfc78b3de 100644
--- a/clippy_lints/src/consts.rs
+++ b/clippy_lints/src/consts.rs
@@ -117,7 +117,7 @@ impl Hash for Constant {
 }
 
 impl Constant {
-    pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: ty::Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
+    pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
         match (left, right) {
             (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
             (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
@@ -268,7 +268,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
     }
 
     #[allow(clippy::cast_possible_wrap)]
-    fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
+    fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
         use self::Constant::*;
         match *o {
             Bool(b) => Some(Bool(!b)),
@@ -284,7 +284,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
         }
     }
 
-    fn constant_negate(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
+    fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
         use self::Constant::*;
         match *o {
             Int(value) => {
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index 0e8d47384f1..413645a091f 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -152,7 +152,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
                 spans.extend_from_slice(&current_spans);
                 doc.push_str(&current);
             }
-        } else if attr.name() == "doc" {
+        } else if attr.check_name("doc") {
             // ignore mix of sugared and non-sugared doc
             return;
         }
diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs
index 37575f10f19..afdf27376d8 100644
--- a/clippy_lints/src/enum_glob_use.rs
+++ b/clippy_lints/src/enum_glob_use.rs
@@ -39,9 +39,10 @@ impl LintPass for EnumGlobUse {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
     fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: HirId) {
+        let map = cx.tcx.hir();
         // only check top level `use` statements
         for item in &m.item_ids {
-            self.lint_item(cx, cx.tcx.hir().expect_item(item.id));
+            self.lint_item(cx, map.expect_item(map.hir_to_node_id(item.id)));
         }
     }
 }
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 1329e945b37..425f1e67147 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -1,7 +1,7 @@
 use if_chain::if_chain;
 use rustc::hir::*;
 use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
 
@@ -129,27 +129,27 @@ fn get_ufcs_type_name(
     method_def_id: def_id::DefId,
     self_arg: &Expr,
 ) -> std::option::Option<String> {
-    let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0].sty;
-    let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id).sty;
+    let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0];
+    let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id);
 
     if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) {
-        if match_borrow_depth(expected_type_of_self, actual_type_of_self) {
-            return Some(cx.tcx.item_path_str(trait_id));
+        if match_borrow_depth(expected_type_of_self, &actual_type_of_self) {
+            return Some(cx.tcx.def_path_str(trait_id));
         }
     }
 
     cx.tcx.impl_of_method(method_def_id).and_then(|_| {
         //a type may implicitly implement other type's methods (e.g. Deref)
-        if match_types(expected_type_of_self, actual_type_of_self) {
+        if match_types(expected_type_of_self, &actual_type_of_self) {
             return Some(get_type_name(cx, &actual_type_of_self));
         }
         None
     })
 }
 
-fn match_borrow_depth(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
-    match (lhs, rhs) {
-        (ty::Ref(_, t1, _), ty::Ref(_, t2, _)) => match_borrow_depth(&t1.sty, &t2.sty),
+fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
+    match (&lhs.sty, &rhs.sty) {
+        (ty::Ref(_, t1, _), ty::Ref(_, t2, _)) => match_borrow_depth(&t1, &t2),
         (l, r) => match (l, r) {
             (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _)) => false,
             (_, _) => true,
@@ -157,8 +157,8 @@ fn match_borrow_depth(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
     }
 }
 
-fn match_types(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
-    match (lhs, rhs) {
+fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
+    match (&lhs.sty, &rhs.sty) {
         (ty::Bool, ty::Bool)
         | (ty::Char, ty::Char)
         | (ty::Int(_), ty::Int(_))
@@ -166,17 +166,17 @@ fn match_types(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
         | (ty::Str, ty::Str) => true,
         (ty::Ref(_, t1, _), ty::Ref(_, t2, _))
         | (ty::Array(t1, _), ty::Array(t2, _))
-        | (ty::Slice(t1), ty::Slice(t2)) => match_types(&t1.sty, &t2.sty),
+        | (ty::Slice(t1), ty::Slice(t2)) => match_types(t1, t2),
         (ty::Adt(def1, _), ty::Adt(def2, _)) => def1 == def2,
         (_, _) => false,
     }
 }
 
-fn get_type_name(cx: &LateContext<'_, '_>, kind: &ty::TyKind<'_>) -> String {
-    match kind {
-        ty::Adt(t, _) => cx.tcx.item_path_str(t.did),
-        ty::Ref(_, r, _) => get_type_name(cx, &r.sty),
-        _ => kind.to_string(),
+fn get_type_name(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> String {
+    match ty.sty {
+        ty::Adt(t, _) => cx.tcx.def_path_str(t.did),
+        ty::Ref(_, r, _) => get_type_name(cx, &r),
+        _ => ty.to_string(),
     }
 }
 
diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index c59a5fc20a6..bed5964fb32 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/clippy_lints/src/fallible_impl_from.rs
@@ -3,7 +3,7 @@ use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_
 use if_chain::if_chain;
 use rustc::hir;
 use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::{declare_tool_lint, lint_array};
 use syntax_pos::Span;
 
@@ -132,7 +132,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
     }
 }
 
-fn match_type(tcx: ty::TyCtxt<'_, '_, '_>, ty: ty::Ty<'_>, path: &[&str]) -> bool {
+fn match_type<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>, path: &[&str]) -> bool {
     match ty.sty {
         ty::Adt(adt, _) => match_def_path(tcx, adt.did, path),
         _ => false,
diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs
index 5378f7d455f..4313d040474 100644
--- a/clippy_lints/src/functions.rs
+++ b/clippy_lints/src/functions.rs
@@ -256,8 +256,7 @@ impl<'a, 'tcx> Functions {
         hir_id: hir::HirId,
     ) {
         let expr = &body.value;
-        let node_id = cx.tcx.hir().hir_to_node_id(hir_id);
-        if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(node_id) {
+        if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
             let raw_ptrs = iter_input_pats(decl, body)
                 .zip(decl.inputs.iter())
                 .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs
index cced334f43a..3e13d0073fe 100644
--- a/clippy_lints/src/inline_fn_without_body.rs
+++ b/clippy_lints/src/inline_fn_without_body.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
 
 fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
     for attr in attrs {
-        if attr.name() != "inline" {
+        if !attr.check_name("inline") {
             continue;
         }
 
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 4762ce760c9..177c85adde5 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -148,9 +148,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items
         }
     }
 
-    let trait_node_id = cx.tcx.hir().hir_to_node_id(visited_trait.hir_id);
-
-    if cx.access_levels.is_exported(trait_node_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
+    if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
         let mut current_and_super_traits = FxHashSet::default();
         let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id);
         fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);
@@ -193,10 +191,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
     }
 
     let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
-        if cx
-            .access_levels
-            .is_exported(cx.tcx.hir().hir_to_node_id(is_empty.id.hir_id))
-        {
+        if cx.access_levels.is_exported(is_empty.id.hir_id) {
             return;
         } else {
             "a private"
@@ -206,7 +201,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
     };
 
     if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
-        if cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(i.id.hir_id)) {
+        if cx.access_levels.is_exported(i.id.hir_id) {
             let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
             let ty = cx.tcx.type_of(def_id);
 
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 4a7f23bc858..bf98aa7e2b5 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -1,10 +1,10 @@
 // error-pattern:cargo-clippy
 
 #![feature(box_syntax)]
+#![feature(never_type)]
 #![feature(rustc_private)]
 #![feature(slice_patterns)]
 #![feature(stmt_expr_attributes)]
-#![feature(range_contains)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![recursion_limit = "256"]
 #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 4b2ba60090f..cd717e586e7 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -356,7 +356,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
                 self.collect_anonymous_lifetimes(path, ty);
             },
             TyKind::Def(item, _) => {
-                if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir().expect_item(item.id).node {
+                let map = self.cx.tcx.hir();
+                if let ItemKind::Existential(ref exist_ty) = map.expect_item(map.hir_to_node_id(item.id)).node {
                     for bound in &exist_ty.bounds {
                         if let GenericBound::Outlives(_) = *bound {
                             self.record(&None);
diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index f96418201da..22c336b8c47 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -3,7 +3,7 @@ use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, sni
 use if_chain::if_chain;
 use rustc::hir;
 use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
 use syntax::source_map::Span;
@@ -87,7 +87,7 @@ impl LintPass for Pass {
     }
 }
 
-fn is_unit_type(ty: ty::Ty<'_>) -> bool {
+fn is_unit_type(ty: Ty<'_>) -> bool {
     match ty.sty {
         ty::Tuple(slice) => slice.is_empty(),
         ty::Never => true,
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 7bd3fd7f4c4..34cb2422e1c 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -516,11 +516,11 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
             for pat in &arm.pats {
                 if let PatKind::Path(ref path) = pat.deref().node {
                     if let QPath::Resolved(_, p) = path {
-                        missing_variants.retain(|e| e.did != p.def.def_id());
+                        missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id()));
                     }
                 } else if let PatKind::TupleStruct(ref path, ..) = pat.deref().node {
                     if let QPath::Resolved(_, p) = path {
-                        missing_variants.retain(|e| e.did != p.def.def_id());
+                        missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id()));
                     }
                 }
             }
@@ -539,7 +539,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
                     String::new()
                 };
                 // This path assumes that the enum type is imported into scope.
-                format!("{}{}{}", ident_str, cx.tcx.item_path_str(v.did), suffix)
+                format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.def_id), suffix)
             })
             .collect();
 
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d7ab3505765..858184d7ea1 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -918,8 +918,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
             if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next();
             if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node;
             then {
-                let node_id = cx.tcx.hir().hir_to_node_id(implitem.hir_id);
-                if cx.access_levels.is_exported(node_id) {
+                if cx.access_levels.is_exported(implitem.hir_id) {
                 // check missing trait implementations
                     for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
                         if name == method_name &&
@@ -2196,7 +2195,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re
 
 fn ty_has_iter_method(
     cx: &LateContext<'_, '_>,
-    self_ref_ty: ty::Ty<'_>,
+    self_ref_ty: Ty<'_>,
 ) -> Option<(&'static Lint, &'static str, &'static str)> {
     if let Some(ty_name) = has_iter_method(cx, self_ref_ty) {
         let lint = match ty_name {
@@ -2217,7 +2216,7 @@ fn ty_has_iter_method(
     }
 }
 
-fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::Ty<'_>, method_span: Span) {
+fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_>, method_span: Span) {
     if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) {
         return;
     }
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index d7e4dd22123..721cfd87020 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -6,11 +6,12 @@
 //
 
 use crate::utils::{in_macro, span_lint};
+use if_chain::if_chain;
 use rustc::hir;
 use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
 use rustc::ty;
 use rustc::{declare_tool_lint, lint_array};
-use syntax::ast;
+use syntax::ast::{self, MetaItem, MetaItemKind};
 use syntax::attr;
 use syntax::source_map::Span;
 
@@ -52,6 +53,20 @@ impl MissingDoc {
         *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
     }
 
+    fn has_include(meta: Option<MetaItem>) -> bool {
+        if_chain! {
+            if let Some(meta) = meta;
+            if let MetaItemKind::List(list) = meta.node;
+            if let Some(meta) = list.get(0);
+            if let Some(name) = meta.ident();
+            then {
+                name.as_str() == "include"
+            } else {
+                false
+            }
+        }
+    }
+
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_, '_>,
@@ -74,7 +89,9 @@ impl MissingDoc {
             return;
         }
 
-        let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
+        let has_doc = attrs
+            .iter()
+            .any(|a| a.check_name("doc") && (a.is_value_str() || Self::has_include(a.meta())));
         if !has_doc {
             span_lint(
                 cx,
diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index 87bf3b5485f..c6b1b7eaf51 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/clippy_lints/src/missing_inline.rs
@@ -59,7 +59,7 @@ declare_clippy_lint! {
 pub struct MissingInline;
 
 fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
-    let has_inline = attrs.iter().any(|a| a.name() == "inline");
+    let has_inline = attrs.iter().any(|a| a.check_name("inline"));
     if !has_inline {
         span_lint(
             cx,
@@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
             return;
         }
 
-        if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(it.hir_id)) {
+        if !cx.access_levels.is_exported(it.hir_id) {
             return;
         }
         match it.node {
@@ -146,8 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
         }
 
         // If the item being implemented is not exported, then we don't need #[inline]
-        let node_id = cx.tcx.hir().hir_to_node_id(impl_item.hir_id);
-        if !cx.access_levels.is_exported(node_id) {
+        if !cx.access_levels.is_exported(impl_item.hir_id) {
             return;
         }
 
@@ -163,12 +162,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
         };
 
         if let Some(trait_def_id) = trait_def_id {
-            if let Some(n) = cx.tcx.hir().as_local_node_id(trait_def_id) {
-                if !cx.access_levels.is_exported(n) {
-                    // If a trait is being implemented for an item, and the
-                    // trait is not exported, we don't need #[inline]
-                    return;
-                }
+            if cx.tcx.hir().as_local_node_id(trait_def_id).is_some() && !cx.access_levels.is_exported(impl_item.hir_id)
+            {
+                // If a trait is being implemented for an item, and the
+                // trait is not exported, we don't need #[inline]
+                return;
             }
         }
 
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index a07b8f4942b..2300456d4c3 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -324,7 +324,7 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool {
     attrs.iter().any(|attr| {
         ["proc_macro", "proc_macro_attribute", "proc_macro_derive"]
             .iter()
-            .any(|&allow| attr.name() == allow)
+            .any(|&allow| attr.check_name(allow))
     })
 }
 
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index fde4081ae8f..3bf0c22c322 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -111,7 +111,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
                     if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
                         let name = impl_item.ident.name;
                         let id = impl_item.hir_id;
-                        let node_id = cx.tcx.hir().hir_to_node_id(id);
                         if sig.header.constness == hir::Constness::Const {
                             // can't be implemented by default
                             return;
@@ -129,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
                             // impl of `Default`
                             return;
                         }
-                        if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(node_id) {
+                        if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
                             let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id));
                             let self_ty = cx.tcx.type_of(self_did);
                             if_chain! {
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index dae59bc84b9..74a9b353ea9 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -72,7 +72,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
             if let ExprKind::Path(ref qpath) = callee.node {
                 let def = cx.tables.qpath_def(qpath, callee.hir_id);
                 match def {
-                    Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
+                    Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) => {
                         !has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg))
                     },
                     _ => false,
@@ -166,9 +166,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec
             if let ExprKind::Path(ref qpath) = callee.node {
                 let def = cx.tables.qpath_def(qpath, callee.hir_id);
                 match def {
-                    Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
-                        if !has_drop(cx, cx.tables.expr_ty(expr)) =>
-                    {
+                    Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) if !has_drop(cx, cx.tables.expr_ty(expr)) => {
                         Some(args.iter().collect())
                     },
                     _ => None,
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 9c184e8c54b..8b7b6b6c42c 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -8,7 +8,7 @@ use rustc::hir::def::Def;
 use rustc::hir::*;
 use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
 use rustc::ty::adjustment::Adjust;
-use rustc::ty::{self, TypeFlags};
+use rustc::ty::{Ty, TypeFlags};
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
 use rustc_typeck::hir_ty_to_ty;
@@ -108,7 +108,7 @@ impl Source {
     }
 }
 
-fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) {
+fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: Source) {
     if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) {
         // An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which
         // is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze`
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index 7821ad56ccc..5c64cd1c15c 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -128,7 +128,7 @@ impl Pass {
             },
             ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
             ExprKind::Path(ref qp) => {
-                if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) {
+                if let Def::Ctor(def_id, def::CtorOf::Variant, _) = cx.tables.qpath_def(qp, expression.hir_id) {
                     return match_def_path(cx.tcx, def_id, &OPTION_NONE);
                 }
 
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 18dfb963230..84c9509844f 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -157,25 +157,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
             }) = higher::range(cx, expr);
             if let Some(y) = y_plus_one(end);
             then {
+                let span = expr.span
+                    .ctxt()
+                    .outer()
+                    .expn_info()
+                    .map_or(expr.span, |info| info.call_site);
                 span_lint_and_then(
                     cx,
                     RANGE_PLUS_ONE,
-                    expr.span,
+                    span,
                     "an inclusive range would be more readable",
                     |db| {
                         let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
                         let end = Sugg::hir(cx, y, "y");
-                        if let Some(is_wrapped) = &snippet_opt(cx, expr.span) {
+                        if let Some(is_wrapped) = &snippet_opt(cx, span) {
                             if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
                                 db.span_suggestion(
-                                    expr.span,
+                                    span,
                                     "use",
                                     format!("({}..={})", start, end),
                                     Applicability::MaybeIncorrect,
                                 );
                             } else {
                                 db.span_suggestion(
-                                    expr.span,
+                                    span,
                                     "use",
                                     format!("{}..={}", start, end),
                                     Applicability::MachineApplicable, // snippet
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 9a17e593fdf..c764e0ceb83 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -12,7 +12,7 @@ use rustc::mir::{
     visit::{MutatingUseContext, PlaceContext, Visitor},
     TerminatorKind,
 };
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
 use std::convert::TryFrom;
@@ -225,7 +225,7 @@ fn is_call_with_ref_arg<'tcx>(
     cx: &LateContext<'_, 'tcx>,
     mir: &'tcx mir::Mir<'tcx>,
     kind: &'tcx mir::TerminatorKind<'tcx>,
-) -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
+) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
     if_chain! {
         if let TerminatorKind::Call { func, args, destination, .. } = kind;
         if args.len() == 1;
@@ -299,7 +299,7 @@ fn base_local_and_movability<'tcx>(
                 place = &proj.base;
                 deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
                 if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
-                    field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).to_ty(cx.tcx));
+                    field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty);
                 }
             },
             _ => return None,
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 5458fa51c7c..3995d9f2819 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -263,7 +263,7 @@ impl EarlyLintPass for ReturnPass {
 }
 
 fn attr_is_cfg(attr: &ast::Attribute) -> bool {
-    attr.meta_item_list().is_some() && attr.name() == "cfg"
+    attr.meta_item_list().is_some() && attr.check_name("cfg")
 }
 
 // get the def site
diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs
index 2c4bfe7358d..e4eb1bb0b74 100644
--- a/clippy_lints/src/transmute.rs
+++ b/clippy_lints/src/transmute.rs
@@ -347,7 +347,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
                                     |db| {
                                         let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                         let arg = if let ty::Int(_) = from_ty.sty {
-                                            arg.as_ty(ty::Uint(ast::UintTy::U32))
+                                            arg.as_ty(ast::UintTy::U32)
                                         } else {
                                             arg
                                         };
diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs
index d246a791166..e0f19a14654 100644
--- a/clippy_lints/src/trivially_copy_pass_by_ref.rs
+++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs
@@ -176,7 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
                     return;
                 }
                 for a in attrs {
-                    if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
+                    if a.meta_item_list().is_some() && a.check_name("proc_macro_derive") {
                         return;
                     }
                 }
diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs
index 4ea34182294..95609d3f302 100644
--- a/clippy_lints/src/types.rs
+++ b/clippy_lints/src/types.rs
@@ -10,6 +10,7 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito
 use rustc::hir::*;
 use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
 use rustc::ty::layout::LayoutOf;
+use rustc::ty::print::Printer;
 use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables};
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
@@ -24,7 +25,7 @@ use crate::utils::paths;
 use crate::utils::{
     clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
     match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
-    span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer,
+    span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathPrinter,
 };
 
 /// Handles all the linting of funky types
@@ -1135,15 +1136,14 @@ impl LintPass for CastPass {
 
 // Check if the given type is either `core::ffi::c_void` or
 // one of the platform specific `libc::<platform>::c_void` of libc.
-fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool {
+fn is_c_void<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>) -> bool {
     if let ty::Adt(adt, _) = ty.sty {
-        let mut apb = AbsolutePathBuffer { names: vec![] };
-        tcx.push_item_path(&mut apb, adt.did, false);
+        let names = AbsolutePathPrinter { tcx }.print_def_path(adt.did, &[]).unwrap();
 
-        if apb.names.is_empty() {
+        if names.is_empty() {
             return false;
         }
-        if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" {
+        if names[0] == "libc" || names[0] == "core" && *names.last().unwrap() == "c_void" {
             return true;
         }
     }
@@ -1533,7 +1533,7 @@ impl LintPass for CharLitAsU8 {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
-        use syntax::ast::{LitKind, UintTy};
+        use syntax::ast::LitKind;
 
         if let ExprKind::Cast(ref e, _) = expr.node {
             if let ExprKind::Lit(ref l) = e.node {
@@ -1818,7 +1818,6 @@ impl Ord for FullInt {
 
 fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
     use std::*;
-    use syntax::ast::{IntTy, UintTy};
 
     if let ExprKind::Cast(ref cast_exp, _) = expr.node {
         let pre_cast_ty = cx.tables.expr_ty(cast_exp);
@@ -2075,7 +2074,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher {
             }
         }
 
-        if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(item.hir_id)) {
+        if !cx.access_levels.is_exported(item.hir_id) {
             return;
         }
 
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index 903e0a81b99..d3b011a3bd9 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -4,6 +4,7 @@ use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Vi
 use rustc::hir::*;
 use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
 use rustc::ty;
+use rustc::ty::DefIdTree;
 use rustc::{declare_tool_lint, lint_array};
 use rustc_errors::Applicability;
 use syntax_pos::symbol::keywords::SelfUpper;
@@ -232,8 +233,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
         if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() {
             if self.item_path.def == path.def {
                 span_use_self_lint(self.cx, path);
-            } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def {
-                if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) {
+            } else if let Def::Ctor(ctor_did, def::CtorOf::Struct, CtorKind::Fn) = path.def {
+                if self.item_path.def.opt_def_id() == self.cx.tcx.parent(ctor_did) {
                     span_use_self_lint(self.cx, path);
                 }
             }
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 64243203b7f..2c96d9a8b5a 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -11,11 +11,9 @@ use syntax::{ast, source_map};
 use toml;
 
 /// Gets the configuration file from arguments.
-pub fn file_from_args(
-    args: &[source_map::Spanned<ast::NestedMetaItemKind>],
-) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {
-    for arg in args.iter().filter_map(syntax::source_map::Spanned::meta_item) {
-        if arg.name() == "conf_file" {
+pub fn file_from_args(args: &[ast::NestedMetaItem]) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {
+    for arg in args.iter().filter_map(syntax::ast::NestedMetaItem::meta_item) {
+        if arg.check_name("conf_file") {
             return match arg.node {
                 ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => {
                     Err(("`conf_file` must be a named value", arg.span))
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index bf94c8a0868..3590b7ae9ee 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -24,8 +24,10 @@ use if_chain::if_chain;
 use matches::matches;
 use rustc::hir;
 use rustc::hir::def::Def;
+use rustc::hir::def_id::CrateNum;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::hir::Node;
 use rustc::hir::*;
 use rustc::lint::{LateContext, Level, Lint, LintContext};
@@ -41,8 +43,7 @@ use rustc_errors::Applicability;
 use syntax::ast::{self, LitKind};
 use syntax::attr;
 use syntax::source_map::{Span, DUMMY_SP};
-use syntax::symbol;
-use syntax::symbol::{keywords, Symbol};
+use syntax::symbol::{keywords, LocalInternedString, Symbol};
 
 use crate::reexport::*;
 
@@ -97,19 +98,102 @@ pub fn in_macro(span: Span) -> bool {
 /// Used to store the absolute path to a type.
 ///
 /// See `match_def_path` for usage.
-#[derive(Debug)]
-pub struct AbsolutePathBuffer {
-    pub names: Vec<symbol::LocalInternedString>,
+pub struct AbsolutePathPrinter<'a, 'tcx> {
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
-impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
-    fn root_mode(&self) -> &ty::item_path::RootMode {
-        const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
-        ABSOLUTE
+use rustc::ty::print::Printer;
+
+#[allow(clippy::diverging_sub_expression)]
+impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
+    type Error = !;
+
+    type Path = Vec<LocalInternedString>;
+    type Region = ();
+    type Type = ();
+    type DynExistential = ();
+
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+        self.tcx
+    }
+
+    fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+        Ok(())
+    }
+
+    fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+        Ok(())
+    }
+
+    fn print_dyn_existential(
+        self,
+        _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    ) -> Result<Self::DynExistential, Self::Error> {
+        Ok(())
+    }
+
+    fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+        Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
+    }
+
+    fn path_qualified(
+        self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        if trait_ref.is_none() {
+            if let ty::Adt(def, substs) = self_ty.sty {
+                return self.print_def_path(def.did, substs);
+            }
+        }
+
+        // This shouldn't ever be needed, but just in case:
+        Ok(vec![match trait_ref {
+            Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
+            None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
+        }])
+    }
+
+    fn path_append_impl(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _disambiguated_data: &DisambiguatedDefPathData,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<Self::Path, Self::Error> {
+        let mut path = print_prefix(self)?;
+
+        // This shouldn't ever be needed, but just in case:
+        path.push(match trait_ref {
+            Some(trait_ref) => Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str(),
+            None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
+        });
+
+        Ok(path)
     }
 
-    fn push(&mut self, text: &str) {
-        self.names.push(symbol::Symbol::intern(text).as_str());
+    fn path_append(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        disambiguated_data: &DisambiguatedDefPathData,
+    ) -> Result<Self::Path, Self::Error> {
+        let mut path = print_prefix(self)?;
+
+        // Skip `::{{constructor}}` on tuple/unit structs.
+        if let DefPathData::Ctor = disambiguated_data.data {
+            return Ok(path);
+        }
+
+        path.push(disambiguated_data.data.as_interned_str().as_str());
+        Ok(path)
+    }
+
+    fn path_generic_args(
+        self,
+        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _args: &[Kind<'tcx>],
+    ) -> Result<Self::Path, Self::Error> {
+        print_prefix(self)
     }
 }
 
@@ -121,12 +205,10 @@ impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
 /// ```
 ///
 /// See also the `paths` module.
-pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
-    let mut apb = AbsolutePathBuffer { names: vec![] };
-
-    tcx.push_item_path(&mut apb, def_id, false);
+pub fn match_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, path: &[&str]) -> bool {
+    let names = get_def_path(tcx, def_id);
 
-    apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
+    names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
 }
 
 /// Gets the absolute path of `def_id` as a vector of `&str`.
@@ -138,12 +220,12 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) ->
 ///     // The given `def_id` is that of an `Option` type
 /// };
 /// ```
-pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> {
-    let mut apb = AbsolutePathBuffer { names: vec![] };
-    tcx.push_item_path(&mut apb, def_id, false);
-    apb.names
+pub fn get_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Vec<&'static str> {
+    AbsolutePathPrinter { tcx }
+        .print_def_path(def_id, &[])
+        .unwrap()
         .iter()
-        .map(syntax_pos::symbol::LocalInternedString::get)
+        .map(LocalInternedString::get)
         .collect()
 }
 
@@ -787,7 +869,7 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool {
     fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool {
         matches!(
             cx.tables.qpath_def(qpath, id),
-            def::Def::Variant(..) | def::Def::VariantCtor(..)
+            def::Def::Variant(..) | def::Def::Ctor(_, def::CtorOf::Variant, _)
         )
     }
 
@@ -1010,7 +1092,7 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: HirId)
 }
 
 /// Returns true if ty has `iter` or `iter_mut` methods
-pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: ty::Ty<'_>) -> Option<&'static str> {
+pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> {
     // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
     // exists and has the desired signature. Unfortunately FnCtxt is not exported
     // so we can't use its `lookup_method` method.
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 51cedfef0f7..9b8b2372c53 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -63,6 +63,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                     .outer()
                     .expn_info()
                     .map(|info| info.call_site)
+                    .expect("unable to get call_site")
+                    .ctxt()
+                    .outer()
+                    .expn_info()
+                    .map(|info| info.call_site)
                     .expect("unable to get call_site");
                 check_vec_macro(cx, &vec_args, span);
             }
diff --git a/doc/adding_lints.md b/doc/adding_lints.md
index 53e671e17e0..a45551dbf9c 100644
--- a/doc/adding_lints.md
+++ b/doc/adding_lints.md
@@ -115,7 +115,7 @@ where all the lint code is. We are going to call the file
 `clippy_lints/src/foo_functions.rs` and import some initial things we need:
 
 ```rust
-use rustc::lint::{LintArray, LintPass};
+use rustc::lint::{LintArray, LintPass, EarlyLintPass};
 use rustc::{declare_tool_lint, lint_array};
 ```
 
@@ -161,6 +161,8 @@ impl LintPass for FooFunctionsPass {
         "FooFunctions"
     }
 }
+
+impl EarlyLintPass for FooFunctionsPass {}
 ```
 
 Don't worry about the `name` method here. As long as it includes the name of the
diff --git a/src/driver.rs b/src/driver.rs
index 01358f46dd7..834d11861c0 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -93,7 +93,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
             ls.register_early_pass(Some(sess), true, false, pass);
         }
         for pass in late_lint_passes {
-            ls.register_late_pass(Some(sess), true, pass);
+            ls.register_late_pass(Some(sess), true, false, false, pass);
         }
 
         for (name, (to, deprecated_name)) in lint_groups {
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index b6a4beff046..1a53b965908 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -1,7 +1,7 @@
 #![feature(test)]
 
 use compiletest_rs as compiletest;
-extern crate test;
+use libtest::TestDescAndFn;
 
 use std::env::{set_var, var};
 use std::ffi::OsStr;
@@ -74,15 +74,12 @@ fn run_mode(mode: &str, dir: PathBuf) {
     compiletest::run_tests(&cfg);
 }
 
-fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
+#[warn(clippy::identity_conversion)]
+fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<TestDescAndFn>) -> Result<bool, io::Error> {
     let mut result = true;
     let opts = compiletest::test_opts(config);
     for dir in fs::read_dir(&config.src_base)? {
-        let dir = dir?;
-        if !dir.file_type()?.is_dir() {
-            continue;
-        }
-        let dir_path = dir.path();
+        let dir_path = dir.unwrap().path();
         set_var("CARGO_MANIFEST_DIR", &dir_path);
         for file in fs::read_dir(&dir_path)? {
             let file = file?;
@@ -101,9 +98,25 @@ fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDesc
             let test_name = compiletest::make_test_name(&config, &paths);
             let index = tests
                 .iter()
-                .position(|test| test.desc.name == test_name)
+                .position(|test| test.desc.name.to_string() == test_name.to_string())
                 .expect("The test should be in there");
-            result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
+            let opts = libtest::TestOpts {
+                list: opts.list,
+                filter: opts.filter.clone(),
+                filter_exact: opts.filter_exact,
+                exclude_should_panic: Default::default(),
+                run_ignored: libtest::RunIgnored::No,
+                run_tests: opts.run_tests,
+                bench_benchmarks: opts.bench_benchmarks,
+                logfile: opts.logfile.clone(),
+                nocapture: opts.nocapture,
+                color: libtest::ColorConfig::AutoColor,
+                format: libtest::OutputFormat::Pretty,
+                test_threads: opts.test_threads,
+                skip: opts.skip.clone(),
+                options: libtest::Options::new(),
+            };
+            result &= libtest::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
         }
     }
     Ok(result)
@@ -114,6 +127,22 @@ fn run_ui_toml() {
     let config = config("ui", path);
     let tests = compiletest::make_tests(&config);
 
+    let tests = tests
+        .into_iter()
+        .map(|test| {
+            libtest::TestDescAndFn {
+                desc: libtest::TestDesc {
+                    name: libtest::TestName::DynTestName(test.desc.name.to_string()),
+                    ignore: test.desc.ignore,
+                    allow_fail: test.desc.allow_fail,
+                    should_panic: libtest::ShouldPanic::No,
+                },
+                // oli obk giving up
+                testfn: unsafe { std::mem::transmute(test.testfn) },
+            }
+        })
+        .collect();
+
     let res = run_ui_toml_tests(&config, tests);
     match res {
         Ok(true) => {},
diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr
index e8964c26796..c1ad2361484 100644
--- a/tests/ui/for_loop.stderr
+++ b/tests/ui/for_loop.stderr
@@ -198,7 +198,7 @@ error: it is more concise to loop over references to containers instead of using
   --> $DIR/for_loop.rs:170:15
    |
 LL |     for _v in vec.iter() {}
-   |               ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
+   |               ^^^^^^^^^^
    |
    = note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
 
@@ -206,13 +206,13 @@ error: it is more concise to loop over references to containers instead of using
   --> $DIR/for_loop.rs:172:15
    |
 LL |     for _v in vec.iter_mut() {}
-   |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
+   |               ^^^^^^^^^^^^^^
 
 error: it is more concise to loop over containers instead of using explicit iteration methods`
   --> $DIR/for_loop.rs:175:15
    |
 LL |     for _v in out_vec.into_iter() {}
-   |               ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
+   |               ^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
 
@@ -220,61 +220,61 @@ error: it is more concise to loop over references to containers instead of using
   --> $DIR/for_loop.rs:178:15
    |
 LL |     for _v in array.into_iter() {}
-   |               ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array`
+   |               ^^^^^^^^^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:183:15
    |
 LL |     for _v in [1, 2, 3].iter() {}
-   |               ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
+   |               ^^^^^^^^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:187:15
    |
 LL |     for _v in [0; 32].iter() {}
-   |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
+   |               ^^^^^^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:192:15
    |
 LL |     for _v in ll.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&ll`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:195:15
    |
 LL |     for _v in vd.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&vd`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:198:15
    |
 LL |     for _v in bh.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bh`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:201:15
    |
 LL |     for _v in hm.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&hm`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:204:15
    |
 LL |     for _v in bt.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bt`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:207:15
    |
 LL |     for _v in hs.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&hs`
+   |               ^^^^^^^^^
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
   --> $DIR/for_loop.rs:210:15
    |
 LL |     for _v in bs.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bs`
+   |               ^^^^^^^^^
 
 error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
   --> $DIR/for_loop.rs:212:15
diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed
index f5342be631b..659fd56f9a9 100644
--- a/tests/ui/into_iter_on_ref.fixed
+++ b/tests/ui/into_iter_on_ref.fixed
@@ -10,7 +10,7 @@ fn main() {
     for _ in &[1, 2, 3] {}
     for _ in vec![X, X] {}
     for _ in &vec![X, X] {}
-    for _ in [1, 2, 3].iter() {} //~ ERROR equivalent to .iter()
+    for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter()
 
     let _ = [1, 2, 3].iter(); //~ ERROR equivalent to .iter()
     let _ = vec![1, 2, 3].into_iter();
diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr
index 931e4880f93..c3e5c85618b 100644
--- a/tests/ui/into_iter_on_ref.stderr
+++ b/tests/ui/into_iter_on_ref.stderr
@@ -1,8 +1,8 @@
 error: this .into_iter() call is equivalent to .iter() and will not move the array
-  --> $DIR/into_iter_on_ref.rs:13:24
+  --> $DIR/into_iter_on_ref.rs:15:23
    |
-LL |     for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter()
-   |                        ^^^^^^^^^ help: call directly: `iter`
+LL |     let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter()
+   |                       ^^^^^^^^^ help: call directly: `iter`
    |
 note: lint level defined here
   --> $DIR/into_iter_on_ref.rs:4:9
@@ -10,12 +10,6 @@ note: lint level defined here
 LL | #![deny(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this .into_iter() call is equivalent to .iter() and will not move the array
-  --> $DIR/into_iter_on_ref.rs:15:23
-   |
-LL |     let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter()
-   |                       ^^^^^^^^^ help: call directly: `iter`
-
 error: this .into_iter() call is equivalent to .iter() and will not move the Vec
   --> $DIR/into_iter_on_ref.rs:17:30
    |
@@ -174,5 +168,5 @@ error: this .into_iter() call is equivalent to .iter() and will not move the Pat
 LL |     let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter()
    |                                               ^^^^^^^^^ help: call directly: `iter`
 
-error: aborting due to 28 previous errors
+error: aborting due to 27 previous errors
 
diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs
index ef86b5240eb..5f3f95bab98 100644
--- a/tests/ui/literals.rs
+++ b/tests/ui/literals.rs
@@ -37,27 +37,9 @@ fn main() {
     let ok16 = 0xFE_BAFE_ABAB_ABCD;
     let ok17 = 0x123_4567_8901_usize;
 
-    let fail9 = 0xabcdef;
-    let fail10 = 0xBAFEBAFE;
-    let fail11 = 0xabcdeff;
-    let fail12 = 0xabcabcabcabcabcabc;
     let fail13 = 0x1_23456_78901_usize;
 
-    let fail14 = 2_32;
-    let fail15 = 4_64;
-    let fail16 = 7_8;
-    let fail17 = 23_16;
-    let ok18 = 23_128;
     let fail19 = 12_3456_21;
-    let fail20 = 2__8;
-    let fail21 = 4___16;
     let fail22 = 3__4___23;
     let fail23 = 3__16___23;
-
-    let fail24 = 12.34_64;
-    let fail25 = 1E2_32;
-    let fail26 = 43E7_64;
-    let fail27 = 243E17_32;
-    let fail28 = 241251235E723_64;
-    let fail29 = 42279.911_32;
 }
diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr
index 2a461dba457..22692160d73 100644
--- a/tests/ui/literals.stderr
+++ b/tests/ui/literals.stderr
@@ -86,133 +86,33 @@ help: if you mean to use an octal constant, use `0o`
 LL |     let fail8 = 0o123;
    |                 ^^^^^
 
-error: long literal lacking separators
-  --> $DIR/literals.rs:40:17
-   |
-LL |     let fail9 = 0xabcdef;
-   |                 ^^^^^^^^ help: consider: `0x00ab_cdef`
-   |
-   = note: `-D clippy::unreadable-literal` implied by `-D warnings`
-
-error: long literal lacking separators
-  --> $DIR/literals.rs:41:18
-   |
-LL |     let fail10 = 0xBAFEBAFE;
-   |                  ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
-
-error: long literal lacking separators
-  --> $DIR/literals.rs:42:18
-   |
-LL |     let fail11 = 0xabcdeff;
-   |                  ^^^^^^^^^ help: consider: `0x0abc_deff`
-
-error: long literal lacking separators
-  --> $DIR/literals.rs:43:18
-   |
-LL |     let fail12 = 0xabcabcabcabcabcabc;
-   |                  ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
-
 error: digit groups should be smaller
-  --> $DIR/literals.rs:44:18
+  --> $DIR/literals.rs:40:18
    |
 LL |     let fail13 = 0x1_23456_78901_usize;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize`
    |
    = note: `-D clippy::large-digit-groups` implied by `-D warnings`
 
-error: mistyped literal suffix
-  --> $DIR/literals.rs:46:18
-   |
-LL |     let fail14 = 2_32;
-   |                  ^^^^ help: did you mean to write: `2_i32`
-   |
-   = note: #[deny(clippy::mistyped_literal_suffixes)] on by default
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:47:18
-   |
-LL |     let fail15 = 4_64;
-   |                  ^^^^ help: did you mean to write: `4_i64`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:48:18
-   |
-LL |     let fail16 = 7_8;
-   |                  ^^^ help: did you mean to write: `7_i8`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:49:18
-   |
-LL |     let fail17 = 23_16;
-   |                  ^^^^^ help: did you mean to write: `23_i16`
-
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:51:18
+  --> $DIR/literals.rs:42:18
    |
 LL |     let fail19 = 12_3456_21;
    |                  ^^^^^^^^^^ help: consider: `12_345_621`
    |
    = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
 
-error: mistyped literal suffix
-  --> $DIR/literals.rs:52:18
-   |
-LL |     let fail20 = 2__8;
-   |                  ^^^^ help: did you mean to write: `2_i8`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:53:18
-   |
-LL |     let fail21 = 4___16;
-   |                  ^^^^^^ help: did you mean to write: `4_i16`
-
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:54:18
+  --> $DIR/literals.rs:43:18
    |
 LL |     let fail22 = 3__4___23;
    |                  ^^^^^^^^^ help: consider: `3_423`
 
 error: digits grouped inconsistently by underscores
-  --> $DIR/literals.rs:55:18
+  --> $DIR/literals.rs:44:18
    |
 LL |     let fail23 = 3__16___23;
    |                  ^^^^^^^^^^ help: consider: `31_623`
 
-error: mistyped literal suffix
-  --> $DIR/literals.rs:57:18
-   |
-LL |     let fail24 = 12.34_64;
-   |                  ^^^^^^^^ help: did you mean to write: `12.34_f64`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:58:18
-   |
-LL |     let fail25 = 1E2_32;
-   |                  ^^^^^^ help: did you mean to write: `1E2_f32`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:59:18
-   |
-LL |     let fail26 = 43E7_64;
-   |                  ^^^^^^^ help: did you mean to write: `43E7_f64`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:60:18
-   |
-LL |     let fail27 = 243E17_32;
-   |                  ^^^^^^^^^ help: did you mean to write: `243E17_f32`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:61:18
-   |
-LL |     let fail28 = 241251235E723_64;
-   |                  ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64`
-
-error: mistyped literal suffix
-  --> $DIR/literals.rs:62:18
-   |
-LL |     let fail29 = 42279.911_32;
-   |                  ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32`
-
-error: aborting due to 31 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/missing-doc-crate-missing.rs b/tests/ui/missing-doc-crate-missing.rs
new file mode 100644
index 00000000000..51fd57df8df
--- /dev/null
+++ b/tests/ui/missing-doc-crate-missing.rs
@@ -0,0 +1,3 @@
+#![warn(clippy::missing_docs_in_private_items)]
+
+fn main() {}
diff --git a/tests/ui/missing-doc-crate-missing.stderr b/tests/ui/missing-doc-crate-missing.stderr
new file mode 100644
index 00000000000..da46f988636
--- /dev/null
+++ b/tests/ui/missing-doc-crate-missing.stderr
@@ -0,0 +1,12 @@
+error: missing documentation for crate
+  --> $DIR/missing-doc-crate-missing.rs:1:1
+   |
+LL | / #![warn(clippy::missing_docs_in_private_items)]
+LL | |
+LL | | fn main() {}
+   | |____________^
+   |
+   = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/missing-doc-crate.rs b/tests/ui/missing-doc-crate.rs
new file mode 100644
index 00000000000..04711f86488
--- /dev/null
+++ b/tests/ui/missing-doc-crate.rs
@@ -0,0 +1,5 @@
+#![warn(clippy::missing_docs_in_private_items)]
+#![feature(external_doc)]
+#![doc(include = "../../README.md")]
+
+fn main() {}
diff --git a/tests/ui/missing-doc-crate.stderr b/tests/ui/missing-doc-crate.stderr
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/ui/missing-doc-crate.stderr
diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed
new file mode 100644
index 00000000000..531e44a781c
--- /dev/null
+++ b/tests/ui/mistyped_literal_suffix.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables, clippy::excessive_precision)]
+
+fn main() {
+    let fail14 = 2_i32;
+    let fail15 = 4_i64;
+    let fail16 = 7_i8; //
+    let fail17 = 23_i16; //
+    let ok18 = 23_128;
+
+    let fail20 = 2_i8; //
+    let fail21 = 4_i16; //
+
+    let fail24 = 12.34_f64;
+    let fail25 = 1E2_f32;
+    let fail26 = 43E7_f64;
+    let fail27 = 243E17_f32;
+    #[allow(overflowing_literals)]
+    let fail28 = 241_251_235E723_f64;
+    let fail29 = 42_279.911_f32;
+}
diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs
new file mode 100644
index 00000000000..d67c842b4af
--- /dev/null
+++ b/tests/ui/mistyped_literal_suffix.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables, clippy::excessive_precision)]
+
+fn main() {
+    let fail14 = 2_32;
+    let fail15 = 4_64;
+    let fail16 = 7_8; //
+    let fail17 = 23_16; //
+    let ok18 = 23_128;
+
+    let fail20 = 2__8; //
+    let fail21 = 4___16; //
+
+    let fail24 = 12.34_64;
+    let fail25 = 1E2_32;
+    let fail26 = 43E7_64;
+    let fail27 = 243E17_32;
+    #[allow(overflowing_literals)]
+    let fail28 = 241251235E723_64;
+    let fail29 = 42279.911_32;
+}
diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr
new file mode 100644
index 00000000000..c3fed6ae8fd
--- /dev/null
+++ b/tests/ui/mistyped_literal_suffix.stderr
@@ -0,0 +1,76 @@
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:6:18
+   |
+LL |     let fail14 = 2_32;
+   |                  ^^^^ help: did you mean to write: `2_i32`
+   |
+   = note: #[deny(clippy::mistyped_literal_suffixes)] on by default
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:7:18
+   |
+LL |     let fail15 = 4_64;
+   |                  ^^^^ help: did you mean to write: `4_i64`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:8:18
+   |
+LL |     let fail16 = 7_8; //
+   |                  ^^^ help: did you mean to write: `7_i8`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:9:18
+   |
+LL |     let fail17 = 23_16; //
+   |                  ^^^^^ help: did you mean to write: `23_i16`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:12:18
+   |
+LL |     let fail20 = 2__8; //
+   |                  ^^^^ help: did you mean to write: `2_i8`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:13:18
+   |
+LL |     let fail21 = 4___16; //
+   |                  ^^^^^^ help: did you mean to write: `4_i16`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:15:18
+   |
+LL |     let fail24 = 12.34_64;
+   |                  ^^^^^^^^ help: did you mean to write: `12.34_f64`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:16:18
+   |
+LL |     let fail25 = 1E2_32;
+   |                  ^^^^^^ help: did you mean to write: `1E2_f32`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:17:18
+   |
+LL |     let fail26 = 43E7_64;
+   |                  ^^^^^^^ help: did you mean to write: `43E7_f64`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:18:18
+   |
+LL |     let fail27 = 243E17_32;
+   |                  ^^^^^^^^^ help: did you mean to write: `243E17_f32`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:20:18
+   |
+LL |     let fail28 = 241251235E723_64;
+   |                  ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64`
+
+error: mistyped literal suffix
+  --> $DIR/mistyped_literal_suffix.rs:21:18
+   |
+LL |     let fail29 = 42279.911_32;
+   |                  ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32`
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs
index 0d093adf8cd..f031dd105c2 100644
--- a/tests/ui/needless_pass_by_value.rs
+++ b/tests/ui/needless_pass_by_value.rs
@@ -95,7 +95,7 @@ impl<T: Serialize, U> S<T, U> {
         s.len() + t.capacity()
     }
 
-    fn bar(_t: T // Ok, since `&T: Serialize` too
+    fn bar(_t: T, // Ok, since `&T: Serialize` too
     ) {
     }
 
diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed
index eede10c771c..1fc93b9c3a8 100644
--- a/tests/ui/unreadable_literal.fixed
+++ b/tests/ui/unreadable_literal.fixed
@@ -17,4 +17,9 @@ fn main() {
     let bad = (0b11_0110_i64, 0x0123_4567_8901_usize, 123_456_f32, 1.234_567_f32);
     let good_sci = 1.1234e1;
     let bad_sci = 1.123_456e1;
+
+    let fail9 = 0x00ab_cdef;
+    let fail10: u32 = 0xBAFE_BAFE;
+    let fail11 = 0x0abc_deff;
+    let fail12: i128 = 0x00ab_cabc_abca_bcab_cabc;
 }
diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs
index 6523f70186f..ef0ef2b9b9e 100644
--- a/tests/ui/unreadable_literal.rs
+++ b/tests/ui/unreadable_literal.rs
@@ -17,4 +17,9 @@ fn main() {
     let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32);
     let good_sci = 1.1234e1;
     let bad_sci = 1.123456e1;
+
+    let fail9 = 0xabcdef;
+    let fail10: u32 = 0xBAFEBAFE;
+    let fail11 = 0xabcdeff;
+    let fail12: i128 = 0xabcabcabcabcabcabc;
 }
diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr
index 8334139120e..2ece5378287 100644
--- a/tests/ui/unreadable_literal.stderr
+++ b/tests/ui/unreadable_literal.stderr
@@ -30,5 +30,29 @@ error: long literal lacking separators
 LL |     let bad_sci = 1.123456e1;
    |                   ^^^^^^^^^^ help: consider: `1.123_456e1`
 
-error: aborting due to 5 previous errors
+error: long literal lacking separators
+  --> $DIR/unreadable_literal.rs:21:17
+   |
+LL |     let fail9 = 0xabcdef;
+   |                 ^^^^^^^^ help: consider: `0x00ab_cdef`
+
+error: long literal lacking separators
+  --> $DIR/unreadable_literal.rs:22:23
+   |
+LL |     let fail10: u32 = 0xBAFEBAFE;
+   |                       ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
+
+error: long literal lacking separators
+  --> $DIR/unreadable_literal.rs:23:18
+   |
+LL |     let fail11 = 0xabcdeff;
+   |                  ^^^^^^^^^ help: consider: `0x0abc_deff`
+
+error: long literal lacking separators
+  --> $DIR/unreadable_literal.rs:24:24
+   |
+LL |     let fail12: i128 = 0xabcabcabcabcabcabc;
+   |                        ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
+
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed
index 730d391848e..68af85030ab 100644
--- a/tests/ui/use_self.fixed
+++ b/tests/ui/use_self.fixed
@@ -239,6 +239,7 @@ mod nesting {
     struct Foo {}
     impl Foo {
         fn foo() {
+            #[allow(unused_imports)]
             use self::Foo; // Can't use Self here
             struct Bar {
                 foo: Foo, // Foo != Self
diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs
index 00824731512..7a6d415528a 100644
--- a/tests/ui/use_self.rs
+++ b/tests/ui/use_self.rs
@@ -239,6 +239,7 @@ mod nesting {
     struct Foo {}
     impl Foo {
         fn foo() {
+            #[allow(unused_imports)]
             use self::Foo; // Can't use Self here
             struct Bar {
                 foo: Foo, // Foo != Self
diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr
index 6e39a28012a..bf1f41fd64e 100644
--- a/tests/ui/use_self.stderr
+++ b/tests/ui/use_self.stderr
@@ -151,43 +151,43 @@ LL |         use_self_expand!(); // Should lint in local macros
    |         ------------------- in this macro invocation
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:260:21
+  --> $DIR/use_self.rs:261:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:261:13
+  --> $DIR/use_self.rs:262:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:248:29
+  --> $DIR/use_self.rs:249:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:249:21
+  --> $DIR/use_self.rs:250:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:303:13
+  --> $DIR/use_self.rs:304:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:304:13
+  --> $DIR/use_self.rs:305:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> $DIR/use_self.rs:306:13
+  --> $DIR/use_self.rs:307:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed
new file mode 100644
index 00000000000..c6fce5df210
--- /dev/null
+++ b/tests/ui/useless_asref.fixed
@@ -0,0 +1,136 @@
+// run-rustfix
+
+#![deny(clippy::useless_asref)]
+#![allow(clippy::trivially_copy_pass_by_ref)]
+
+use std::fmt::Debug;
+
+struct FakeAsRef;
+
+#[allow(clippy::should_implement_trait)]
+impl FakeAsRef {
+    fn as_ref(&self) -> &Self {
+        self
+    }
+}
+
+struct MoreRef;
+
+impl<'a, 'b, 'c> AsRef<&'a &'b &'c MoreRef> for MoreRef {
+    fn as_ref(&self) -> &&'a &'b &'c MoreRef {
+        &&&&MoreRef
+    }
+}
+
+fn foo_rstr(x: &str) {
+    println!("{:?}", x);
+}
+fn foo_rslice(x: &[i32]) {
+    println!("{:?}", x);
+}
+fn foo_mrslice(x: &mut [i32]) {
+    println!("{:?}", x);
+}
+fn foo_rrrrmr(_: &&&&MoreRef) {
+    println!("so many refs");
+}
+
+fn not_ok() {
+    let rstr: &str = "hello";
+    let mut mrslice: &mut [i32] = &mut [1, 2, 3];
+
+    {
+        let rslice: &[i32] = &*mrslice;
+        foo_rstr(rstr);
+        foo_rstr(rstr);
+        foo_rslice(rslice);
+        foo_rslice(rslice);
+    }
+    {
+        foo_mrslice(mrslice);
+        foo_mrslice(mrslice);
+        foo_rslice(mrslice);
+        foo_rslice(mrslice);
+    }
+
+    {
+        let rrrrrstr = &&&&rstr;
+        let rrrrrslice = &&&&&*mrslice;
+        foo_rslice(rrrrrslice);
+        foo_rslice(rrrrrslice);
+        foo_rstr(rrrrrstr);
+        foo_rstr(rrrrrstr);
+    }
+    {
+        let mrrrrrslice = &mut &mut &mut &mut mrslice;
+        foo_mrslice(mrrrrrslice);
+        foo_mrslice(mrrrrrslice);
+        foo_rslice(mrrrrrslice);
+        foo_rslice(mrrrrrslice);
+    }
+    #[allow(unused_parens, clippy::double_parens)]
+    foo_rrrrmr((&&&&MoreRef));
+
+    generic_not_ok(mrslice);
+    generic_ok(mrslice);
+}
+
+fn ok() {
+    let string = "hello".to_owned();
+    let mut arr = [1, 2, 3];
+    let mut vec = vec![1, 2, 3];
+
+    {
+        foo_rstr(string.as_ref());
+        foo_rslice(arr.as_ref());
+        foo_rslice(vec.as_ref());
+    }
+    {
+        foo_mrslice(arr.as_mut());
+        foo_mrslice(vec.as_mut());
+    }
+
+    {
+        let rrrrstring = &&&&string;
+        let rrrrarr = &&&&arr;
+        let rrrrvec = &&&&vec;
+        foo_rstr(rrrrstring.as_ref());
+        foo_rslice(rrrrarr.as_ref());
+        foo_rslice(rrrrvec.as_ref());
+    }
+    {
+        let mrrrrarr = &mut &mut &mut &mut arr;
+        let mrrrrvec = &mut &mut &mut &mut vec;
+        foo_mrslice(mrrrrarr.as_mut());
+        foo_mrslice(mrrrrvec.as_mut());
+    }
+    FakeAsRef.as_ref();
+    foo_rrrrmr(MoreRef.as_ref());
+
+    generic_not_ok(arr.as_mut());
+    generic_ok(&mut arr);
+}
+
+fn foo_mrt<T: Debug + ?Sized>(t: &mut T) {
+    println!("{:?}", t);
+}
+fn foo_rt<T: Debug + ?Sized>(t: &T) {
+    println!("{:?}", t);
+}
+
+fn generic_not_ok<T: AsMut<T> + AsRef<T> + Debug + ?Sized>(mrt: &mut T) {
+    foo_mrt(mrt);
+    foo_mrt(mrt);
+    foo_rt(mrt);
+    foo_rt(mrt);
+}
+
+fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
+    foo_mrt(mru.as_mut());
+    foo_rt(mru.as_ref());
+}
+
+fn main() {
+    not_ok();
+    ok();
+}
diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs
index fe3dae5fc4c..1d23760bd14 100644
--- a/tests/ui/useless_asref.rs
+++ b/tests/ui/useless_asref.rs
@@ -1,5 +1,8 @@
+// run-rustfix
+
 #![deny(clippy::useless_asref)]
 #![allow(clippy::trivially_copy_pass_by_ref)]
+
 use std::fmt::Debug;
 
 struct FakeAsRef;
@@ -65,6 +68,7 @@ fn not_ok() {
         foo_rslice(mrrrrrslice.as_ref());
         foo_rslice(mrrrrrslice);
     }
+    #[allow(unused_parens, clippy::double_parens)]
     foo_rrrrmr((&&&&MoreRef).as_ref());
 
     generic_not_ok(mrslice);
diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr
index cc594559032..dd0613fc767 100644
--- a/tests/ui/useless_asref.stderr
+++ b/tests/ui/useless_asref.stderr
@@ -1,71 +1,71 @@
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:41:18
+  --> $DIR/useless_asref.rs:44:18
    |
 LL |         foo_rstr(rstr.as_ref());
    |                  ^^^^^^^^^^^^^ help: try this: `rstr`
    |
 note: lint level defined here
-  --> $DIR/useless_asref.rs:1:9
+  --> $DIR/useless_asref.rs:3:9
    |
 LL | #![deny(clippy::useless_asref)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:43:20
+  --> $DIR/useless_asref.rs:46:20
    |
 LL |         foo_rslice(rslice.as_ref());
    |                    ^^^^^^^^^^^^^^^ help: try this: `rslice`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:47:21
+  --> $DIR/useless_asref.rs:50:21
    |
 LL |         foo_mrslice(mrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:49:20
+  --> $DIR/useless_asref.rs:52:20
    |
 LL |         foo_rslice(mrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:56:20
+  --> $DIR/useless_asref.rs:59:20
    |
 LL |         foo_rslice(rrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:58:18
+  --> $DIR/useless_asref.rs:61:18
    |
 LL |         foo_rstr(rrrrrstr.as_ref());
    |                  ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:63:21
+  --> $DIR/useless_asref.rs:66:21
    |
 LL |         foo_mrslice(mrrrrrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:65:20
+  --> $DIR/useless_asref.rs:68:20
    |
 LL |         foo_rslice(mrrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:68:16
+  --> $DIR/useless_asref.rs:72:16
    |
 LL |     foo_rrrrmr((&&&&MoreRef).as_ref());
    |                ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:118:13
+  --> $DIR/useless_asref.rs:122:13
    |
 LL |     foo_mrt(mrt.as_mut());
    |             ^^^^^^^^^^^^ help: try this: `mrt`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:120:12
+  --> $DIR/useless_asref.rs:124:12
    |
 LL |     foo_rt(mrt.as_ref());
    |            ^^^^^^^^^^^^ help: try this: `mrt`