diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index ab3b7e471..0c12bab95 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/consts.rs b/clippy_lints/src/consts.rs index 8d71eb542..3d6fa273c 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -245,7 +245,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { let def = self.tables.qpath_def(qpath, callee.hir_id); if let Some(def_id) = def.opt_def_id(); let def_path = get_def_path(self.tcx, def_id); - if let &["core", "num", impl_ty, "max_value"] = &def_path[..]; + if let &["core", "num", impl_ty, "max_value"] = &def_path.iter().map(|s| s.as_str()).collect::>()[..]; then { let value = match impl_ty { "" => i8::max_value() as u128, diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index c59a5fc20..f8158bd16 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 4a7f23bc8..1943373eb 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/types.rs b/clippy_lints/src/types.rs index 4ea341822..d4c4756e4 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -12,6 +12,7 @@ use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintC use rustc::ty::layout::LayoutOf; use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; use rustc::{declare_tool_lint, lint_array}; +use rustc::ty::print::Printer; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; @@ -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 = AbsolutePathBuffer { 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/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bf94c8a08..c9c11ef44 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -24,6 +24,8 @@ use if_chain::if_chain; use matches::matches; use rustc::hir; use rustc::hir::def::Def; +use rustc::hir::map::DisambiguatedDefPathData; +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::Node; @@ -41,7 +43,6 @@ 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 crate::reexport::*; @@ -97,19 +98,97 @@ 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 AbsolutePathBuffer<'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; + +impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathBuffer<'_, 'tcx> { + type Error = !; + + type Path = Vec; + type Region = (); + type Type = (); + type DynExistential = (); + + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx } - fn push(&mut self, text: &str) { - self.names.push(symbol::Symbol::intern(text).as_str()); + 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 path_crate( + self, + cnum: CrateNum, + ) -> Result { + Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) + } + 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) => format!("{:?}", trait_ref), + None => format!("<{}>", self_ty), + }]) + } + + 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) => { + format!("", trait_ref, self_ty) + } + None => format!("", self_ty), + }); + + 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().to_string()); + Ok(path) + } + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, + _args: &[Kind<'tcx>], + ) -> Result { + print_prefix(self) } } @@ -121,12 +200,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![] }; +pub fn match_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, path: &[&str]) -> bool { + let names = AbsolutePathBuffer { tcx }.print_def_path(def_id, &[]).unwrap(); - tcx.push_item_path(&mut apb, def_id, false); - - 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,13 +215,8 @@ 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 - .iter() - .map(syntax_pos::symbol::LocalInternedString::get) - .collect() +pub fn get_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Vec { + AbsolutePathBuffer { tcx }.print_def_path(def_id, &[]).unwrap() } /// Checks if type is struct, enum or union type with the given def path.