mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-13 16:37:15 +00:00
Reimplement AbsolutePathBuffer
This commit is contained in:
parent
54e20519d2
commit
31435cd7f5
6 changed files with 107 additions and 34 deletions
|
@ -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 {
|
if let ItemKind::Fn(_, _, _, eid) = item.node {
|
||||||
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
|
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
|
||||||
} else {
|
} 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 {
|
match item.node {
|
||||||
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value),
|
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value),
|
||||||
_ => false,
|
_ => 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 {
|
match item.node {
|
||||||
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
|
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
|
||||||
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
|
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() {
|
if let Some(stmt) = block.stmts.first() {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Local(_) => true,
|
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 {
|
match &expr.node {
|
||||||
ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block),
|
ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block),
|
||||||
ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e),
|
ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e),
|
||||||
|
|
|
@ -245,7 +245,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||||
let def = self.tables.qpath_def(qpath, callee.hir_id);
|
let def = self.tables.qpath_def(qpath, callee.hir_id);
|
||||||
if let Some(def_id) = def.opt_def_id();
|
if let Some(def_id) = def.opt_def_id();
|
||||||
let def_path = get_def_path(self.tcx, 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::<Vec<_>>()[..];
|
||||||
then {
|
then {
|
||||||
let value = match impl_ty {
|
let value = match impl_ty {
|
||||||
"<impl i8>" => i8::max_value() as u128,
|
"<impl i8>" => i8::max_value() as u128,
|
||||||
|
|
|
@ -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 {
|
match ty.sty {
|
||||||
ty::Adt(adt, _) => match_def_path(tcx, adt.did, path),
|
ty::Adt(adt, _) => match_def_path(tcx, adt.did, path),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// error-pattern:cargo-clippy
|
// error-pattern:cargo-clippy
|
||||||
|
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
#![feature(never_type)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
|
@ -12,6 +12,7 @@ use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintC
|
||||||
use rustc::ty::layout::LayoutOf;
|
use rustc::ty::layout::LayoutOf;
|
||||||
use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables};
|
use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables};
|
||||||
use rustc::{declare_tool_lint, lint_array};
|
use rustc::{declare_tool_lint, lint_array};
|
||||||
|
use rustc::ty::print::Printer;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_typeck::hir_ty_to_ty;
|
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
|
// Check if the given type is either `core::ffi::c_void` or
|
||||||
// one of the platform specific `libc::<platform>::c_void` of libc.
|
// 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 {
|
if let ty::Adt(adt, _) = ty.sty {
|
||||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
let names = AbsolutePathBuffer { tcx }.print_def_path(adt.did, &[]).unwrap();
|
||||||
tcx.push_item_path(&mut apb, adt.did, false);
|
|
||||||
|
|
||||||
if apb.names.is_empty() {
|
if names.is_empty() {
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ use if_chain::if_chain;
|
||||||
use matches::matches;
|
use matches::matches;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def::Def;
|
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::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
||||||
use rustc::hir::Node;
|
use rustc::hir::Node;
|
||||||
|
@ -41,7 +43,6 @@ use rustc_errors::Applicability;
|
||||||
use syntax::ast::{self, LitKind};
|
use syntax::ast::{self, LitKind};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::source_map::{Span, DUMMY_SP};
|
use syntax::source_map::{Span, DUMMY_SP};
|
||||||
use syntax::symbol;
|
|
||||||
use syntax::symbol::{keywords, Symbol};
|
use syntax::symbol::{keywords, Symbol};
|
||||||
|
|
||||||
use crate::reexport::*;
|
use crate::reexport::*;
|
||||||
|
@ -97,19 +98,97 @@ pub fn in_macro(span: Span) -> bool {
|
||||||
/// Used to store the absolute path to a type.
|
/// Used to store the absolute path to a type.
|
||||||
///
|
///
|
||||||
/// See `match_def_path` for usage.
|
/// See `match_def_path` for usage.
|
||||||
#[derive(Debug)]
|
pub struct AbsolutePathBuffer<'a, 'tcx> {
|
||||||
pub struct AbsolutePathBuffer {
|
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
pub names: Vec<symbol::LocalInternedString>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
|
use rustc::ty::print::Printer;
|
||||||
fn root_mode(&self) -> &ty::item_path::RootMode {
|
|
||||||
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
|
impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathBuffer<'_, 'tcx> {
|
||||||
ABSOLUTE
|
type Error = !;
|
||||||
|
|
||||||
|
type Path = Vec<String>;
|
||||||
|
type Region = ();
|
||||||
|
type Type = ();
|
||||||
|
type DynExistential = ();
|
||||||
|
|
||||||
|
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, text: &str) {
|
fn print_region(
|
||||||
self.names.push(symbol::Symbol::intern(text).as_str());
|
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).to_string()])
|
||||||
|
}
|
||||||
|
fn path_qualified(
|
||||||
|
self,
|
||||||
|
self_ty: Ty<'tcx>,
|
||||||
|
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||||
|
) -> Result<Self::Path, Self::Error> {
|
||||||
|
// 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<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) => {
|
||||||
|
format!("<impl {} for {}>", trait_ref, self_ty)
|
||||||
|
}
|
||||||
|
None => format!("<impl {}>", self_ty),
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
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)?;
|
||||||
|
path.push(disambiguated_data.data.as_interned_str().to_string());
|
||||||
|
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 +200,10 @@ impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also the `paths` module.
|
/// See also the `paths` module.
|
||||||
pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
|
pub fn match_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, path: &[&str]) -> bool {
|
||||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
let names = AbsolutePathBuffer { tcx }.print_def_path(def_id, &[]).unwrap();
|
||||||
|
|
||||||
tcx.push_item_path(&mut apb, def_id, false);
|
names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
|
||||||
|
|
||||||
apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the absolute path of `def_id` as a vector of `&str`.
|
/// 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
|
/// // The given `def_id` is that of an `Option` type
|
||||||
/// };
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> {
|
pub fn get_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Vec<String> {
|
||||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
AbsolutePathBuffer { tcx }.print_def_path(def_id, &[]).unwrap()
|
||||||
tcx.push_item_path(&mut apb, def_id, false);
|
|
||||||
apb.names
|
|
||||||
.iter()
|
|
||||||
.map(syntax_pos::symbol::LocalInternedString::get)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if type is struct, enum or union type with the given def path.
|
/// Checks if type is struct, enum or union type with the given def path.
|
||||||
|
|
Loading…
Reference in a new issue