Skip to content

Commit

Permalink
clippy: support QPath::LangItem
Browse files Browse the repository at this point in the history
This commit updates clippy with the introduction of `QPath::LangItem` so
that it still compiles.

Signed-off-by: David Wood <david@davidtw.co>
  • Loading branch information
davidtwco committed Aug 17, 2020
1 parent dde93c9 commit f1ce294
Show file tree
Hide file tree
Showing 20 changed files with 117 additions and 130 deletions.
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/default_trait_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
);
}
},
QPath::TypeRelative(..) => {},
QPath::TypeRelative(..) | QPath::LangItem(..) => {},
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/indexing_slicing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/infinite_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/len_zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/tools/clippy/clippy_lints/src/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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() {
Expand Down
7 changes: 4 additions & 3 deletions src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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('_') &&
Expand Down
8 changes: 4 additions & 4 deletions src/tools/clippy/clippy_lints/src/ranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions src/tools/clippy/clippy_lints/src/try_err.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
11 changes: 6 additions & 5 deletions src/tools/clippy/clippy_lints/src/unused_io_amount.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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);
Expand Down
17 changes: 14 additions & 3 deletions src/tools/clippy/clippy_lints/src/utils/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!("]);");
},
}
}
}

Expand Down Expand Up @@ -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"),
}
}
98 changes: 23 additions & 75 deletions src/tools/clippy/clippy_lints/src/utils/higher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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<Range<'a>> {
pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
/// 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>> {
Expand All @@ -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,
Expand Down
Loading

0 comments on commit f1ce294

Please sign in to comment.