clippy: support QPath::LangItem
This commit updates clippy with the introduction of `QPath::LangItem` so that it still compiles. Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
dde93c9ba6
commit
f1ce2948db
@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
|
||||
);
|
||||
}
|
||||
},
|
||||
QPath::TypeRelative(..) => {},
|
||||
QPath::TypeRelative(..) | QPath::LangItem(..) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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('_') &&
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
@ -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<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>> {
|
||||
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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<def::Res> {
|
||||
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 {
|
||||
|
@ -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"];
|
||||
|
@ -42,7 +42,7 @@ impl<'a> Sugg<'a> {
|
||||
pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> {
|
||||
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,
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user