Auto merge of #5922 - flip1995:rustup, r=flip1995
Rustup r? @ghost changelog: none
This commit is contained in:
commit
6220dff504
@ -5,8 +5,8 @@ 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::util::lev_distance::find_best_match_for_name;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -341,7 +341,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) => {
|
||||
|
@ -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 {
|
||||
@ -1197,7 +1197,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 {
|
||||
@ -1699,7 +1699,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::walk_ptrs_ty;
|
||||
use crate::utils::{is_type_diagnostic_item, is_type_lang_item, snippet, span_lint_and_sugg};
|
||||
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)
|
||||
}
|
||||
|
@ -2364,7 +2364,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,7 +433,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||
return;
|
||||
}
|
||||
let binding = match expr.kind {
|
||||
ExprKind::Path(ref qpath) => {
|
||||
ExprKind::Path(ref qpath) if !matches!(qpath, hir::QPath::LangItem(..)) => {
|
||||
let binding = last_path_segment(qpath).ident.as_str();
|
||||
if binding.starts_with('_') &&
|
||||
!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,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};
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -4,7 +4,7 @@ use crate::utils::{
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, MatchSource};
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
|
||||
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);
|
||||
|
@ -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};
|
||||
@ -486,6 +486,7 @@ impl Types {
|
||||
}
|
||||
}
|
||||
},
|
||||
QPath::LangItem(..) => {},
|
||||
}
|
||||
},
|
||||
TyKind::Rptr(ref lt, ref mut_ty) => self.check_ty_rptr(cx, hir_ty, is_local, lt, mut_ty),
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
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::mut_visit::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
|
@ -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);
|
||||
|
@ -5,8 +5,8 @@
|
||||
#![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)]
|
||||
|
||||
use crate::utils::{both, over};
|
||||
use rustc_ast::ast::{self, *};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_span::symbol::Ident;
|
||||
use std::mem;
|
||||
|
||||
|
@ -175,9 +175,16 @@ impl PrintVisitor {
|
||||
}
|
||||
|
||||
fn print_qpath(&mut self, path: &QPath<'_>) {
|
||||
print!(" if match_qpath({}, &[", self.current);
|
||||
print_path(path, &mut true);
|
||||
println!("]);");
|
||||
if let QPath::LangItem(lang_item, _) = *path {
|
||||
println!(
|
||||
" if matches!({}, QPath::LangItem(LangItem::{:?}, _));",
|
||||
self.current, lang_item,
|
||||
);
|
||||
} else {
|
||||
print!(" if match_qpath({}, &[", self.current);
|
||||
print_path(path, &mut true);
|
||||
println!("]);");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,5 +767,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,95 +55,46 @@ 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 {
|
||||
start: None,
|
||||
end: None,
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
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::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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
start: None,
|
||||
end: Some(get_field("end", fields)?),
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
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,
|
||||
}),
|
||||
hir::QPath::LangItem(hir::LangItem::RangeFrom, _) => Some(Range {
|
||||
start: Some(get_field("start", fields)?),
|
||||
end: None,
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
}),
|
||||
hir::QPath::LangItem(hir::LangItem::Range, _) => Some(Range {
|
||||
start: Some(get_field("start", fields)?),
|
||||
end: Some(get_field("end", fields)?),
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
}),
|
||||
hir::QPath::LangItem(hir::LangItem::RangeToInclusive, _) => Some(Range {
|
||||
start: None,
|
||||
end: Some(get_field("end", fields)?),
|
||||
limits: ast::RangeLimits::Closed,
|
||||
}),
|
||||
hir::QPath::LangItem(hir::LangItem::RangeTo, _) => Some(Range {
|
||||
start: None,
|
||||
end: Some(get_field("end", fields)?),
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
}),
|
||||
_ => 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;
|
||||
@ -184,10 +184,18 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
||||
left.name == right.name
|
||||
}
|
||||
|
||||
pub fn eq_fieldpat(&mut self, left: &FieldPat<'_>, right: &FieldPat<'_>) -> bool {
|
||||
let (FieldPat { ident: li, pat: lp, .. }, FieldPat { ident: ri, pat: rp, .. }) = (&left, &right);
|
||||
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
|
||||
},
|
||||
@ -222,6 +230,7 @@ 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,
|
||||
}
|
||||
}
|
||||
@ -605,6 +614,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);
|
||||
}
|
||||
@ -714,6 +726,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 {
|
||||
|
@ -85,19 +85,7 @@ 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 PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
|
||||
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"];
|
||||
@ -131,7 +119,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,
|
||||
|
@ -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! {
|
||||
|
@ -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