From f13d2bfd9be6e8f7c8930b5590a634d8807c139b Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 4 Aug 2020 14:24:13 +0100 Subject: [PATCH 1/2] clippy: support `QPath::LangItem` This commit updates clippy with the introduction of `QPath::LangItem` so that it still compiles. Signed-off-by: David Wood --- clippy_lints/src/default_trait_access.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/loops.rs | 6 +- clippy_lints/src/match_on_vec_items.rs | 7 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/misc.rs | 1 + clippy_lints/src/ranges.rs | 8 +- clippy_lints/src/try_err.rs | 8 +- clippy_lints/src/types.rs | 1 + clippy_lints/src/unused_io_amount.rs | 11 +-- clippy_lints/src/utils/author.rs | 17 +++- clippy_lints/src/utils/higher.rs | 98 ++++++------------------ clippy_lints/src/utils/hir_utils.rs | 24 +++++- clippy_lints/src/utils/inspector.rs | 6 ++ clippy_lints/src/utils/mod.rs | 13 +++- clippy_lints/src/utils/paths.rs | 13 ---- clippy_lints/src/utils/sugg.rs | 8 +- tests/ui/author/for_loop.stdout | 16 ++-- 20 files changed, 117 insertions(+), 130 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 874e19d9e9f..067ea903bdd 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess { ); } }, - QPath::TypeRelative(..) => {}, + QPath::TypeRelative(..) | QPath::LangItem(..) => {}, } } } diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index a1f58e54ae3..90b1a529be7 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Index(ref array, ref index) = &expr.kind { let ty = cx.typeck_results().expr_ty(array); - if let Some(range) = higher::range(cx, index) { + if let Some(range) = higher::range(index) { // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.kind { let size: u128 = if let Some(size) = s.try_eval_usize(cx.tcx, cx.param_env) { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index e511d3ea330..129abd7d897 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -171,7 +171,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { Finite } }, - ExprKind::Struct(..) => higher::range(cx, expr).map_or(false, |r| r.end.is_none()).into(), + ExprKind::Struct(..) => higher::range(expr).map_or(false, |r| r.end.is_none()).into(), _ => Finite, } } diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 00d0b8b4e5b..e5daa30f8ca 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -262,7 +262,7 @@ fn check_len( fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Special case ranges until `range_is_empty` is stabilized. See issue 3807. fn should_skip_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - higher::range(cx, expr).map_or(false, |_| { + higher::range(expr).map_or(false, |_| { !cx.tcx .features() .declared_lib_features diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8352a8a3d2c..8ffcd417d1d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1003,7 +1003,7 @@ fn detect_manual_memcpy<'tcx>( start: Some(start), end: Some(end), limits, - }) = higher::range(cx, arg) + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { @@ -1177,7 +1177,7 @@ fn check_for_loop_range<'tcx>( start: Some(start), ref end, limits, - }) = higher::range(cx, arg) + }) = higher::range(arg) { // the var must be a single name if let PatKind::Binding(_, canonical_id, ident, _) = pat.kind { @@ -1679,7 +1679,7 @@ fn check_for_mut_range_bound(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<' start: Some(start), end: Some(end), .. - }) = higher::range(cx, arg) + }) = higher::range(arg) { let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; if mut_ids[0].is_some() || mut_ids[1].is_some() { diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 4f8f2cb171d..faa20687ef6 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -1,7 +1,8 @@ -use crate::utils::{self, is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{is_type_diagnostic_item, is_type_lang_item, snippet, span_lint_and_sugg}; +use crate::utils::walk_ptrs_ty; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, MatchSource}; +use rustc_hir::{Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -96,5 +97,5 @@ fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); let ty = walk_ptrs_ty(ty); - match_type(cx, ty, &utils::paths::RANGE_FULL) + is_type_lang_item(cx, ty, LangItem::RangeFull) } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 570ae66d595..2265a188855 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2271,7 +2271,7 @@ fn lint_iter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_ if_chain! { if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind; if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen }) - = higher::range(cx, index_expr); + = higher::range(index_expr); if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind; if let ast::LitKind::Int(start_idx, _) = start_lit.node; then { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 26a1c32b6b3..482a563572d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -433,6 +433,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { return; } let binding = match expr.kind { + ExprKind::Path(hir::QPath::LangItem(..)) => None, ExprKind::Path(ref qpath) => { let binding = last_path_segment(qpath).ident.as_str(); if binding.starts_with('_') && diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index f88075798ca..7a75fc125d0 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for Ranges { if let ExprKind::MethodCall(ref iter_path, _, ref iter_args , _) = *iter; if iter_path.ident.name == sym!(iter); // range expression in `.zip()` call: `0..x.len()` - if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); + if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg); if is_integer_const(cx, start, 0); // `.len()` call if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind; @@ -180,7 +180,7 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { start, end: Some(end), limits: RangeLimits::HalfOpen - }) = higher::range(cx, expr); + }) = higher::range(expr); if let Some(y) = y_plus_one(cx, end); then { let span = if expr.span.from_expansion() { @@ -225,7 +225,7 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { // inclusive range minus one: `x..=(y-1)` fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr); + if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr); if let Some(y) = y_minus_one(cx, end); then { span_lint_and_then( @@ -279,7 +279,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) { } if_chain! { - if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(cx, expr); + if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(expr); let ty = cx.typeck_results().expr_ty(start); if let ty::Int(_) | ty::Uint(_) = ty.kind; if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start); diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index 3bd73d9f21a..a74104e9282 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -1,10 +1,10 @@ use crate::utils::{ - is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, snippet_with_macro_callsite, - span_lint_and_sugg, + is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, + snippet_with_macro_callsite, span_lint_and_sugg, }; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, MatchSource}; +use rustc_hir::{Expr, ExprKind, QPath, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { if let ExprKind::Match(ref match_arg, _, MatchSource::TryDesugar) = expr.kind; if let ExprKind::Call(ref match_fun, ref try_args) = match_arg.kind; if let ExprKind::Path(ref match_fun_path) = match_fun.kind; - if match_qpath(match_fun_path, &paths::TRY_INTO_RESULT); + if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _)); if let Some(ref try_arg) = try_args.get(0); if let ExprKind::Call(ref err_fun, ref err_args) = try_arg.kind; if let Some(ref err_arg) = err_args.get(0); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c3dea447521..d1a7886a47e 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -475,6 +475,7 @@ impl Types { } } }, + QPath::LangItem(..) => {}, } }, TyKind::Rptr(ref lt, ref mut_ty) => self.check_ty_rptr(cx, hir_ty, is_local, lt, mut_ty), diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1580f657d77..43166d26787 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint}; +use crate::utils::{is_try, match_trait_method, paths, span_lint}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -42,10 +42,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { match expr.kind { hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => { if let hir::ExprKind::Call(ref func, ref args) = res.kind { - if let hir::ExprKind::Path(ref path) = func.kind { - if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { - check_method_call(cx, &args[0], expr); - } + if matches!( + func.kind, + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _)) + ) { + check_method_call(cx, &args[0], expr); } } else { check_method_call(cx, res, expr); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 128fa87a162..9b7a268c628 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -175,9 +175,19 @@ impl PrintVisitor { } fn print_qpath(&mut self, path: &QPath<'_>) { - print!(" if match_qpath({}, &[", self.current); - print_path(path, &mut true); - println!("]);"); + match *path { + QPath::LangItem(lang_item, _) => { + println!( + " if matches!({}, QPath::LangItem(LangItem::{:?}, _));", + self.current, lang_item, + ); + }, + _ => { + print!(" if match_qpath({}, &[", self.current); + print_path(path, &mut true); + println!("]);"); + }, + } } } @@ -760,5 +770,6 @@ fn print_path(path: &QPath<'_>, first: &mut bool) { }, ref other => print!("/* unimplemented: {:?}*/", other), }, + QPath::LangItem(..) => panic!("print_path: called for lang item qpath"), } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index f81a132c7e7..ba15456014d 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -3,12 +3,11 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::utils::{is_expn_of, match_def_path, match_qpath, paths}; +use crate::utils::{is_expn_of, match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_middle::ty; /// Converts a hir binary operator to the corresponding `ast` type. #[must_use] @@ -47,7 +46,7 @@ pub struct Range<'a> { } /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. -pub fn range<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a hir::Expr<'_>) -> Option> { +pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option> { /// Finds the field named `name` in the field. Always return `Some` for /// convenience. fn get_field<'c>(name: &str, fields: &'c [hir::Field<'_>]) -> Option<&'c hir::Expr<'c>> { @@ -56,94 +55,43 @@ pub fn range<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a hir::Expr<'_>) -> Optio Some(expr) } - let def_path = match cx.typeck_results().expr_ty(expr).kind { - ty::Adt(def, _) => cx.tcx.def_path(def.did), - _ => return None, - }; - - // sanity checks for std::ops::RangeXXXX - if def_path.data.len() != 3 { - return None; - } - if def_path.data.get(0)?.data.as_symbol() != sym!(ops) { - return None; - } - if def_path.data.get(1)?.data.as_symbol() != sym!(range) { - return None; - } - let type_name = def_path.data.get(2)?.data.as_symbol(); - let range_types = [ - "RangeFrom", - "RangeFull", - "RangeInclusive", - "Range", - "RangeTo", - "RangeToInclusive", - ]; - if !range_types.contains(&&*type_name.as_str()) { - return None; - } - - // The range syntax is expanded to literal paths starting with `core` or `std` - // depending on - // `#[no_std]`. Testing both instead of resolving the paths. - match expr.kind { - hir::ExprKind::Path(ref path) => { - if match_qpath(path, &paths::RANGE_FULL_STD) || match_qpath(path, &paths::RANGE_FULL) { - Some(Range { + hir::ExprKind::Call(ref path, ref args) if matches!( + path.kind, + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, _)) + ) => Some(Range { + start: Some(&args[0]), + end: Some(&args[1]), + limits: ast::RangeLimits::Closed, + }), + hir::ExprKind::Struct(ref path, ref fields, None) => { + match path { + hir::QPath::LangItem(hir::LangItem::RangeFull, _) => Some(Range { start: None, end: None, limits: ast::RangeLimits::HalfOpen, - }) - } else { - None - } - }, - hir::ExprKind::Call(ref path, ref args) => { - if let hir::ExprKind::Path(ref path) = path.kind { - if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) - { - Some(Range { - start: Some(&args[0]), - end: Some(&args[1]), - limits: ast::RangeLimits::Closed, - }) - } else { - None - } - } else { - None - } - }, - hir::ExprKind::Struct(ref path, ref fields, None) => { - if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) { - Some(Range { + }), + hir::QPath::LangItem(hir::LangItem::RangeFrom, _) => Some(Range { start: Some(get_field("start", fields)?), end: None, limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) { - Some(Range { + }), + hir::QPath::LangItem(hir::LangItem::Range, _) => Some(Range { start: Some(get_field("start", fields)?), end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, - }) - } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) - { - Some(Range { + }), + hir::QPath::LangItem(hir::LangItem::RangeToInclusive, _) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, - }) - } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) { - Some(Range { + }), + hir::QPath::LangItem(hir::LangItem::RangeTo, _) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, - }) - } else { - None + }), + _ => None, } }, _ => None, diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 28fb6ed12a0..2eefd4a38a6 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,9 +3,9 @@ use crate::utils::differing_macro_contexts; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{ - BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg, - GenericArgs, Guard, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, PathSegment, QPath, - Stmt, StmtKind, Ty, TyKind, TypeBinding, + BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FieldPat, + FnRetTy, GenericArg, GenericArgs, Guard, InlineAsmOperand, Lifetime, LifetimeName, ParamName, + Pat, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lint::LateContext; use rustc_middle::ich::StableHashingContextProvider; @@ -185,10 +185,20 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { left.name == right.name } + pub fn eq_fieldpat(&mut self, left: &FieldPat<'_>, right: &FieldPat<'_>) -> bool { + match (&left, &right) { + (FieldPat { ident: li, pat: lp, .. }, FieldPat { ident: ri, pat: rp, .. }) => + li.name.as_str() == ri.name.as_str() && self.eq_pat(lp, rp), + } + } + /// Checks whether two patterns are the same. pub fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool { match (&left.kind, &right.kind) { (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), + (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => { + self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_fieldpat(l, r)) + }, (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs }, @@ -223,6 +233,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { (&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => { self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) }, + (&QPath::LangItem(llang_item, _), &QPath::LangItem(rlang_item, _)) => + llang_item == rlang_item, _ => false, } } @@ -601,6 +613,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { QPath::TypeRelative(_, ref path) => { self.hash_name(path.ident.name); }, + QPath::LangItem(lang_item, ..) => { + lang_item.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + } } // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); } @@ -710,6 +725,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); segment.ident.name.hash(&mut self.s); }, + QPath::LangItem(lang_item, ..) => { + lang_item.hash(&mut self.s); + } }, TyKind::OpaqueDef(_, arg_list) => { self.hash_generic_args(arg_list); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index d8fa1fa278e..4701a3f26e6 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -266,6 +266,9 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}Relative Path, {:?}", ind, ty); println!("{}seg: {:?}", ind, seg); }, + hir::ExprKind::Path(hir::QPath::LangItem(lang_item, ..)) => { + println!("{}Lang Item Path, {:?}", ind, lang_item.name()); + }, hir::ExprKind::AddrOf(kind, ref muta, ref e) => { println!("{}AddrOf", ind); println!("kind: {:?}", kind); @@ -488,6 +491,9 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { println!("{}Relative Path, {:?}", ind, ty); println!("{}seg: {:?}", ind, seg); }, + hir::PatKind::Path(hir::QPath::LangItem(lang_item, ..)) => { + println!("{}Lang Item Path, {:?}", ind, lang_item.name()); + }, hir::PatKind::Tuple(pats, opt_dots_position) => { println!("{}Tuple", ind); if let Some(dot_position) = opt_dots_position { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 223628cc610..a56b8203513 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -142,6 +142,14 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb } } +/// Checks if the type is equal to a lang item +pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool { + match ty.kind { + ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did, + _ => false, + } +} + /// Checks if the method call given in `expr` belongs to the given trait. pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); @@ -163,6 +171,7 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> { match *path { QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"), QPath::TypeRelative(_, ref seg) => seg, + QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"), } } @@ -170,6 +179,7 @@ pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment match *path { QPath::Resolved(_, ref path) => path.segments.get(0), QPath::TypeRelative(_, ref seg) => Some(seg), + QPath::LangItem(..) => None, } } @@ -196,6 +206,7 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { }, _ => false, }, + QPath::LangItem(..) => false, } } @@ -277,7 +288,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option { pub fn qpath_res(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match qpath { hir::QPath::Resolved(_, path) => path.res, - hir::QPath::TypeRelative(..) => { + hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { if cx.tcx.has_typeck_results(id.owner.to_def_id()) { cx.tcx.typeck(id.owner.to_def_id().expect_local()).qpath_res(qpath, id) } else { diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 923b319d777..9c28d63d414 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -84,19 +84,7 @@ pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; 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"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; -pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; -pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&str; 4] = ["core", "ops", "range", "RangeFull"]; -pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; -pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"]; -pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"]; -pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"]; -pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"]; -pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"]; -pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"]; -pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"]; @@ -130,7 +118,6 @@ pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"]; pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; -pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 0ac7714fbeb..2955f8d8e59 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -42,7 +42,7 @@ impl<'a> Sugg<'a> { pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); - Self::hir_from_snippet(cx, expr, snippet) + Self::hir_from_snippet(expr, snippet) }) } @@ -80,13 +80,13 @@ impl<'a> Sugg<'a> { pub fn hir_with_macro_callsite(cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str) -> Self { let snippet = snippet_with_macro_callsite(cx, expr.span, default); - Self::hir_from_snippet(cx, expr, snippet) + Self::hir_from_snippet(expr, snippet) } /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*` /// function variants of `Sugg`, since these use different snippet functions. - fn hir_from_snippet(cx: &LateContext<'_>, expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self { - if let Some(range) = higher::range(cx, expr) { + fn hir_from_snippet(expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self { + if let Some(range) = higher::range(expr) { let op = match range.limits { ast::RangeLimits::HalfOpen => AssocOp::DotDot, ast::RangeLimits::Closed => AssocOp::DotDotEq, diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index 81ede955347..3bf7607c62f 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -3,10 +3,10 @@ if_chain! { if let ExprKind::Match(ref expr1, ref arms, MatchSource::ForLoopDesugar) = expr.kind; if let ExprKind::Call(ref func, ref args) = expr1.kind; if let ExprKind::Path(ref path) = func.kind; - if match_qpath(path, &["{{root}}", "std", "iter", "IntoIterator", "into_iter"]); + if matches!(path, QPath::LangItem(LangItem::IntoIterIntoIter, _)); if args.len() == 1; if let ExprKind::Struct(ref path1, ref fields, None) = args[0].kind; - if match_qpath(path1, &["{{root}}", "std", "ops", "Range"]); + if matches!(path1, QPath::LangItem(LangItem::Range, _)); if fields.len() == 2; // unimplemented: field checks if arms.len() == 1; @@ -20,7 +20,7 @@ if_chain! { if let ExprKind::Match(ref expr2, ref arms1, MatchSource::ForLoopDesugar) = e.kind; if let ExprKind::Call(ref func1, ref args1) = expr2.kind; if let ExprKind::Path(ref path2) = func1.kind; - if match_qpath(path2, &["{{root}}", "std", "iter", "Iterator", "next"]); + if matches!(path2, QPath::LangItem(LangItem::IteratorNext, _)); if args1.len() == 1; if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, ref inner) = args1[0].kind; if let ExprKind::Path(ref path3) = inner.kind; @@ -31,13 +31,15 @@ if_chain! { if match_qpath(path4, &["__next"]); if let ExprKind::Path(ref path5) = value.kind; if match_qpath(path5, &["val"]); - if let PatKind::TupleStruct(ref path6, ref fields1, None) = arms1[0].pat.kind; - if match_qpath(path6, &["{{root}}", "std", "option", "Option", "Some"]); + if let PatKind::Struct(ref path6, ref fields1, false) = arms1[0].pat.kind; + if matches!(path6, QPath::LangItem(LangItem::OptionSome, _)); if fields1.len() == 1; // unimplemented: field checks if let ExprKind::Break(ref destination, None) = arms1[1].body.kind; - if let PatKind::Path(ref path7) = arms1[1].pat.kind; - if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); + if let PatKind::Struct(ref path7, ref fields2, false) = arms1[1].pat.kind; + if matches!(path7, QPath::LangItem(LangItem::OptionNone, _)); + if fields2.len() == 0; + // unimplemented: field checks if let StmtKind::Local(ref local1) = body.stmts[2].kind; if let Some(ref init) = local1.init; if let ExprKind::Path(ref path8) = init.kind; From ae0eb390b09587bc6b2d6c503f5cb9c276b06c13 Mon Sep 17 00:00:00 2001 From: Ujjwal Sharma Date: Mon, 27 Apr 2020 23:26:11 +0530 Subject: [PATCH 2/2] rust_ast::ast => rustc_ast --- clippy_lints/src/attrs.rs | 6 +++--- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/single_component_path_imports.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/transmuting_null.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/unnested_or_patterns.rs | 2 +- clippy_lints/src/utils/ast_utils.rs | 2 +- clippy_lints/src/vec_resize_to_zero.rs | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 376ac55f9c9..76ccf2e4bb9 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -5,7 +5,7 @@ use crate::utils::{ span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; -use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; +use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_errors::Applicability; use rustc_hir::{ @@ -570,7 +570,7 @@ declare_lint_pass!(EarlyAttributes => [ ]); impl EarlyLintPass for EarlyAttributes { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { check_empty_line_after_outer_attr(cx, item); } @@ -580,7 +580,7 @@ impl EarlyLintPass for EarlyAttributes { } } -fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) { +fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { for attr in &item.attrs { let attr_item = if let AttrKind::Normal(ref attr) = attr.kind { attr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ad525d7620..aa100263640 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -339,7 +339,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) { } #[doc(hidden)] -pub fn read_conf(args: &[rustc_ast::ast::NestedMetaItem], sess: &Session) -> Conf { +pub fn read_conf(args: &[rustc_ast::NestedMetaItem], sess: &Session) -> Conf { use std::path::Path; match utils::conf::file_from_args(args) { Ok(file_name) => { diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index 2e853e8301d..58bfd0bc553 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; -use rustc_ast::ast::{Item, ItemKind, UseTreeKind}; +use rustc_ast::{Item, ItemKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index bada6fa7c52..7a659bf779c 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -161,7 +161,7 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use crate::utils::{snippet, snippet_with_applicability}; - use rustc_ast::ast::LitKind; + use rustc_ast::LitKind; if_chain! { if let ExprKind::MethodCall(path, _, args, _) = &e.kind; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 7b5e92eb5ee..28fd55f6ff0 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -3,7 +3,7 @@ use crate::utils::{ span_lint_and_then, sugg, }; use if_chain::if_chain; -use rustc_ast::ast; +use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs index fbf7f0b2517..d60306336c6 100644 --- a/clippy_lints/src/transmuting_null.rs +++ b/clippy_lints/src/transmuting_null.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_context, Constant}; use crate::utils::{match_qpath, paths, span_lint}; use if_chain::if_chain; -use rustc_ast::ast::LitKind; +use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index c3dea447521..a6911da1bb1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -5,7 +5,7 @@ use std::cmp::Ordering; use std::collections::BTreeMap; use if_chain::if_chain; -use rustc_ast::ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; +use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 502bf0c4279..b7e2eba0a81 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -2,7 +2,7 @@ use crate::utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path}; use crate::utils::{over, span_lint_and_then}; -use rustc_ast::ast::{self, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; +use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast_pretty::pprust; diff --git a/clippy_lints/src/utils/ast_utils.rs b/clippy_lints/src/utils/ast_utils.rs index ad02bc5fd8e..c32c80dcd3c 100644 --- a/clippy_lints/src/utils/ast_utils.rs +++ b/clippy_lints/src/utils/ast_utils.rs @@ -5,7 +5,7 @@ #![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)] use crate::utils::{both, over}; -use rustc_ast::ast::{self, *}; +use rustc_ast::{self as ast, *}; use rustc_ast::ptr::P; use rustc_span::symbol::Ident; use std::mem; diff --git a/clippy_lints/src/vec_resize_to_zero.rs b/clippy_lints/src/vec_resize_to_zero.rs index 58e7c354b27..d2494b321ef 100644 --- a/clippy_lints/src/vec_resize_to_zero.rs +++ b/clippy_lints/src/vec_resize_to_zero.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; use crate::utils::{match_def_path, paths}; -use rustc_ast::ast::LitKind; +use rustc_ast::LitKind; use rustc_hir as hir; declare_clippy_lint! {