diff options
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(¤t_spans); doc.push_str(¤t); } - } 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` |
