diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index ab3b7e471ac0..0c12bab957c3 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -352,7 +352,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 +360,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 +377,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 +389,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), diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 1329e945b370..30436716ff95 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -129,27 +129,27 @@ fn get_ufcs_type_name( method_def_id: def_id::DefId, self_arg: &Expr, ) -> std::option::Option { - 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::Ty<'_>, rhs: ty::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::Ty<'_>, rhs: ty::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::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 c59a5fc20a67..f8158bd16f73 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -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::Ty<'_>, path: &[&str]) -> bool { match ty.sty { ty::Adt(adt, _) => match_def_path(tcx, adt.did, path), _ => false, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4a7f23bc8587..1943373eb4a3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,6 +1,7 @@ // error-pattern:cargo-clippy #![feature(box_syntax)] +#![feature(never_type)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 7bd3fd7f4c41..74a85f1f8174 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -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.did), suffix) }) .collect(); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2c4bfe7358d6..e4eb1bb0b740 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/types.rs b/clippy_lints/src/types.rs index 4ea341822945..2e50222c8a9f 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::::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; } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 903e0a81b993..ac901ab062f3 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; @@ -233,7 +234,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { 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) { + 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/mod.rs b/clippy_lints/src/utils/mod.rs index bf94c8a08681..c91065e5c1c8 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::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,90 @@ 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, +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; + 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 { + Ok(()) + } + + fn print_type(self, _ty: Ty<'tcx>) -> Result { + Ok(()) + } + + fn print_dyn_existential( + self, + _predicates: &'tcx ty::List>, + ) -> Result { + Ok(()) } - fn push(&mut self, text: &str) { - self.names.push(symbol::Symbol::intern(text).as_str()); + fn path_crate(self, cnum: CrateNum) -> Result { + Ok(vec![self.tcx.original_crate_name(cnum).as_str()]) + } + + fn path_qualified( + self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + // 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, + _disambiguated_data: &DisambiguatedDefPathData, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + 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!("", trait_ref, self_ty)).as_str(), + None => Symbol::intern(&format!("", self_ty)).as_str(), + }); + + Ok(path) + } + + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + ) -> Result { + let mut path = print_prefix(self)?; + path.push(disambiguated_data.data.as_interned_str().as_str()); + Ok(path) + } + + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, + _args: &[Kind<'tcx>], + ) -> Result { + print_prefix(self) } } @@ -121,12 +193,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 +208,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() } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 9ee25aaea5ea..34796fa20f48 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -17,7 +17,7 @@ pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; -pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; +pub const CSTRING_NEW: [&str; 2] = ["", "new"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; @@ -27,8 +27,8 @@ pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; -pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; -pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; +pub const FMT_ARGUMENTS_NEWV1: [&str; 2] = [">", "new_v1"]; +pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 2] = [">", "new_v1_formatted"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; @@ -60,11 +60,11 @@ pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"]; pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"]; -pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; +pub const OS_STR_TO_OS_STRING: [&str; 2] = ["", "to_os_string"]; pub const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; pub const PATH: [&str; 3] = ["std", "path", "Path"]; pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; -pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; +pub const PATH_TO_PATH_BUF: [&str; 2] = ["", "to_path_buf"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; @@ -83,12 +83,12 @@ pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"]; pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"]; -pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; -pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; -pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; -pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; -pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; +pub const REGEX_BUILDER_NEW: [&str; 2] = ["", "new"]; +pub const REGEX_BYTES_BUILDER_NEW: [&str; 2] = ["", "new"]; +pub const REGEX_BYTES_NEW: [&str; 2] = ["", "new"]; +pub const REGEX_BYTES_SET_NEW: [&str; 2] = ["", "new"]; +pub const REGEX_NEW: [&str; 2] = ["", "new"]; +pub const REGEX_SET_NEW: [&str; 2] = ["", "new"]; pub const REPEAT: [&str; 3] = ["core", "iter", "repeat"]; pub const RESULT: [&str; 3] = ["core", "result", "Result"]; pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];