Auto merge of #6586 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: FP fix: [`needless_return`] no longer triggers inside macros.
This commit is contained in:
commit
953f024793
@ -1,8 +1,7 @@
|
||||
use crate::consts::{constant, Constant};
|
||||
use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_hir::{Expr, ExprKind, PatKind, UnOp};
|
||||
use rustc_hir::{Expr, ExprKind, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
@ -102,31 +101,22 @@ enum AssertKind {
|
||||
/// Check if the expression matches
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// match { let _t = !c; _t } {
|
||||
/// true => {
|
||||
/// {
|
||||
/// ::std::rt::begin_panic(message, _)
|
||||
/// }
|
||||
/// }
|
||||
/// _ => { }
|
||||
/// };
|
||||
/// if !c {
|
||||
/// {
|
||||
/// ::std::rt::begin_panic(message, _)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// where `message` is any expression and `c` is a constant bool.
|
||||
fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> {
|
||||
if_chain! {
|
||||
if let ExprKind::Match(ref expr, ref arms, _) = expr.kind;
|
||||
// matches { let _t = expr; _t }
|
||||
if let ExprKind::DropTemps(ref expr) = expr.kind;
|
||||
if let ExprKind::Unary(UnOp::UnNot, ref expr) = expr.kind;
|
||||
if let ExprKind::If(ref cond, ref then, _) = expr.kind;
|
||||
if let ExprKind::Unary(UnOp::UnNot, ref expr) = cond.kind;
|
||||
// bind the first argument of the `assert!` macro
|
||||
if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr);
|
||||
// arm 1 pattern
|
||||
if let PatKind::Lit(ref lit_expr) = arms[0].pat.kind;
|
||||
if let ExprKind::Lit(ref lit) = lit_expr.kind;
|
||||
if let LitKind::Bool(true) = lit.node;
|
||||
// arm 1 block
|
||||
if let ExprKind::Block(ref block, _) = arms[0].body.kind;
|
||||
// block
|
||||
if let ExprKind::Block(ref block, _) = then.kind;
|
||||
if block.stmts.is_empty();
|
||||
if let Some(block_expr) = &block.expr;
|
||||
// inner block is optional. unwrap it if it exists, or use the expression as is otherwise.
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
|
||||
use crate::utils::{differing_macro_contexts, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{BlockCheckMode, Expr, ExprKind};
|
||||
@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
|
||||
if in_external_macro(cx.sess(), expr.span) {
|
||||
return;
|
||||
}
|
||||
if let Some((cond, _, _)) = higher::if_block(&expr) {
|
||||
if let ExprKind::If(cond, _, _) = &expr.kind {
|
||||
if let ExprKind::Block(block, _) = &cond.kind {
|
||||
if block.rules == BlockCheckMode::DefaultBlock {
|
||||
if block.stmts.is_empty() {
|
||||
|
@ -147,6 +147,9 @@ impl<'tcx> Visitor<'tcx> for CCHelper {
|
||||
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||
walk_expr(self, e);
|
||||
match e.kind {
|
||||
ExprKind::If(_, _, _) => {
|
||||
self.cc += 1;
|
||||
},
|
||||
ExprKind::Match(_, ref arms, _) => {
|
||||
if arms.len() > 1 {
|
||||
self.cc += 1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(clippy::float_cmp)]
|
||||
|
||||
use crate::utils::{clip, higher, sext, unsext};
|
||||
use crate::utils::{clip, sext, unsext};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
@ -228,9 +228,6 @@ pub struct ConstEvalLateContext<'a, 'tcx> {
|
||||
impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||
/// Simple constant folding: Insert an expression, get a constant or none.
|
||||
pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
|
||||
if let Some((ref cond, ref then, otherwise)) = higher::if_block(&e) {
|
||||
return self.ifthenelse(cond, then, otherwise);
|
||||
}
|
||||
match e.kind {
|
||||
ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
|
||||
ExprKind::Block(ref block, _) => self.block(block),
|
||||
@ -249,6 +246,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||
UnOp::UnNeg => self.constant_negate(&o, self.typeck_results.expr_ty(e)),
|
||||
UnOp::UnDeref => Some(if let Constant::Ref(r) = o { *r } else { o }),
|
||||
}),
|
||||
ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
|
||||
ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right),
|
||||
ExprKind::Call(ref callee, ref args) => {
|
||||
// We only handle a few const functions for now.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
|
||||
use crate::utils::{get_parent_expr, higher, if_sequence, span_lint_and_note};
|
||||
use rustc_hir::{Block, Expr};
|
||||
use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note};
|
||||
use rustc_hir::{Block, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
@ -109,11 +109,13 @@ impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if !expr.span.from_expansion() {
|
||||
// skip ifs directly in else, it will be checked in the parent if
|
||||
if let Some(expr) = get_parent_expr(cx, expr) {
|
||||
if let Some((_, _, Some(ref else_expr))) = higher::if_block(&expr) {
|
||||
if else_expr.hir_id == expr.hir_id {
|
||||
return;
|
||||
}
|
||||
if let Some(&Expr {
|
||||
kind: ExprKind::If(_, _, Some(ref else_expr)),
|
||||
..
|
||||
}) = get_parent_expr(cx, expr)
|
||||
{
|
||||
if else_expr.hir_id == expr.hir_id {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::utils::{is_copy, match_path, paths, span_lint_and_note};
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_hir::{Impl, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
@ -33,10 +33,10 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for CopyIterator {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(ref trait_ref),
|
||||
..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
|
||||
|
||||
|
@ -7,7 +7,7 @@ use if_chain::if_chain;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{
|
||||
BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
|
||||
BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::map::Map;
|
||||
@ -164,10 +164,10 @@ declare_lint_pass!(Derive => [
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Derive {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(ref trait_ref),
|
||||
..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
|
||||
let is_automatically_derived = is_automatically_derived(&*item.attrs);
|
||||
|
@ -182,11 +182,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
|
||||
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id));
|
||||
}
|
||||
},
|
||||
hir::ItemKind::Impl {
|
||||
of_trait: ref trait_ref,
|
||||
..
|
||||
} => {
|
||||
self.in_trait_impl = trait_ref.is_some();
|
||||
hir::ItemKind::Impl(ref impl_) => {
|
||||
self.in_trait_impl = impl_.of_trait.is_some();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::utils::SpanlessEq;
|
||||
use crate::utils::{get_item_name, higher, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
|
||||
use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
|
||||
use crate::utils::{snippet_with_applicability, span_lint_and_then};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
@ -54,7 +54,7 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for HashMapPass {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let Some((ref check, ref then_block, ref else_block)) = higher::if_block(&expr) {
|
||||
if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.kind {
|
||||
if let ExprKind::Unary(UnOp::UnNot, ref check) = check.kind {
|
||||
if let Some((ty, map, key)) = check_cond(cx, check) {
|
||||
// in case of `if !m.contains_key(&k) { m.insert(k, v); }`
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, ItemKind, Node};
|
||||
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, TraitRef, Ty};
|
||||
@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
|
||||
let mut trait_self_ty = None;
|
||||
if let Some(Node::Item(item)) = parent_node {
|
||||
// If the method is an impl for a trait, don't warn.
|
||||
if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = item.kind {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -181,7 +181,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
|
||||
self.set.insert(cmt.hir_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
|
||||
// check for `impl From<???> for ..`
|
||||
let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id);
|
||||
if_chain! {
|
||||
if let hir::ItemKind::Impl{ items: impl_items, .. } = item.kind;
|
||||
if let hir::ItemKind::Impl(impl_) = &item.kind;
|
||||
if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
|
||||
if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT);
|
||||
then {
|
||||
lint_impl_body(cx, item.span, impl_items);
|
||||
lint_impl_body(cx, item.span, impl_.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::consts::{
|
||||
constant, constant_simple, Constant,
|
||||
Constant::{Int, F32, F64},
|
||||
};
|
||||
use crate::utils::{eq_expr_value, get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg};
|
||||
use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
|
||||
@ -556,11 +556,11 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a
|
||||
|
||||
fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if let Some((cond, body, Some(else_body))) = higher::if_block(&expr);
|
||||
if let ExprKind::If(cond, body, else_body) = expr.kind;
|
||||
if let ExprKind::Block(block, _) = body.kind;
|
||||
if block.stmts.is_empty();
|
||||
if let Some(if_body_expr) = block.expr;
|
||||
if let ExprKind::Block(else_block, _) = else_body.kind;
|
||||
if let Some(ExprKind::Block(else_block, _)) = else_body.map(|el| &el.kind);
|
||||
if else_block.stmts.is_empty();
|
||||
if let Some(else_body_expr) = else_block.expr;
|
||||
if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr);
|
||||
|
@ -81,6 +81,13 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
lint(cx, expr.span, break_expr.span, LINT_BREAK);
|
||||
}
|
||||
},
|
||||
ExprKind::If(.., if_expr, else_expr) => {
|
||||
expr_match(cx, if_expr);
|
||||
|
||||
if let Some(else_expr) = else_expr {
|
||||
expr_match(cx, else_expr);
|
||||
}
|
||||
},
|
||||
ExprKind::Match(.., arms, source) => {
|
||||
let check_all_arms = match source {
|
||||
MatchSource::IfLetDesugar {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::utils::{higher, in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
|
||||
use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
@ -42,7 +42,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||
return;
|
||||
}
|
||||
if_chain! {
|
||||
if let Some((ref cond, ref then, None)) = higher::if_block(&expr);
|
||||
if let ExprKind::If(cond, then, None) = &expr.kind;
|
||||
|
||||
// Check if the conditional expression is a binary operation
|
||||
if let ExprKind::Binary(ref cond_op, ref cond_left, ref cond_right) = cond.kind;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::utils::{in_macro, span_lint_and_then};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::{def_id, Crate, Item, ItemKind};
|
||||
use rustc_hir::{def_id, Crate, Impl, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::Span;
|
||||
@ -49,11 +49,11 @@ impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
|
||||
fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl {
|
||||
if let ItemKind::Impl(Impl {
|
||||
ref generics,
|
||||
of_trait: None,
|
||||
..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
// Remember for each inherent implementation encountered its span and generics
|
||||
// but filter out implementations that have generic params (type or lifetime)
|
||||
|
@ -3,7 +3,7 @@ use rustc_ast::ast::LitKind;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef};
|
||||
use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, Impl, ImplItemRef, Item, ItemKind, TraitItemRef};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
@ -115,11 +115,11 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
||||
|
||||
match item.kind {
|
||||
ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
|
||||
ItemKind::Impl {
|
||||
ItemKind::Impl(Impl {
|
||||
of_trait: None,
|
||||
items: ref impl_items,
|
||||
..
|
||||
} => check_impl_items(cx, item, impl_items),
|
||||
}) => check_impl_items(cx, item, impl_items),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::utils::visitors::LocalUsedVisitor;
|
||||
use crate::utils::{higher, qpath_res, snippet, span_lint_and_then};
|
||||
use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
@ -64,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
|
||||
if let hir::StmtKind::Local(ref local) = stmt.kind;
|
||||
if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
|
||||
if let hir::StmtKind::Expr(ref if_) = expr.kind;
|
||||
if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_);
|
||||
if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.kind;
|
||||
if !LocalUsedVisitor::new(canonical_id).check_expr(cond);
|
||||
if let hir::ExprKind::Block(ref then, _) = then.kind;
|
||||
if let Some(value) = check_assign(cx, canonical_id, &*then);
|
||||
|
@ -742,6 +742,14 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
|
||||
// Break can come from the inner loop so remove them.
|
||||
absorb_break(&never_loop_block(b, main_loop_id))
|
||||
},
|
||||
ExprKind::If(ref e, ref e2, ref e3) => {
|
||||
let e1 = never_loop_expr(e, main_loop_id);
|
||||
let e2 = never_loop_expr(e2, main_loop_id);
|
||||
let e3 = e3
|
||||
.as_ref()
|
||||
.map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
|
||||
combine_seq(e1, combine_branches(e2, e3))
|
||||
},
|
||||
ExprKind::Match(ref e, ref arms, _) => {
|
||||
let e = never_loop_expr(e, main_loop_id);
|
||||
if arms.is_empty() {
|
||||
@ -2594,7 +2602,7 @@ fn is_loop(expr: &Expr<'_>) -> bool {
|
||||
}
|
||||
|
||||
fn is_conditional(expr: &Expr<'_>) -> bool {
|
||||
matches!(expr.kind, ExprKind::Match(..))
|
||||
matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..))
|
||||
}
|
||||
|
||||
fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool {
|
||||
|
@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if let Some((cond, then, _)) = higher::if_block(&expr);
|
||||
if let ExprKind::If(cond, then, _) = &expr.kind;
|
||||
if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
|
||||
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
|
||||
if let ExprKind::Path(target_path) = &target_arg.kind;
|
||||
|
@ -1626,7 +1626,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
||||
let self_ty = cx.tcx.type_of(def_id);
|
||||
|
||||
// if this impl block implements a trait, lint in trait definition instead
|
||||
if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
|
||||
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2048,6 +2048,7 @@ fn lint_expect_fun_call(
|
||||
hir::ExprKind::Call(..)
|
||||
| hir::ExprKind::MethodCall(..)
|
||||
// These variants are debatable or require further examination
|
||||
| hir::ExprKind::If(..)
|
||||
| hir::ExprKind::Match(..)
|
||||
| hir::ExprKind::Block{ .. } => true,
|
||||
_ => false,
|
||||
|
@ -90,6 +90,12 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
|
||||
}
|
||||
(found_mapping, found_filtering)
|
||||
},
|
||||
// There must be an else_arm or there will be a type error
|
||||
hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => {
|
||||
let if_check = check_expression(cx, arg_id, if_arm);
|
||||
let else_check = check_expression(cx, arg_id, else_arm);
|
||||
(if_check.0 | else_check.0, if_check.1 | else_check.1)
|
||||
},
|
||||
hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true),
|
||||
_ => (true, true),
|
||||
}
|
||||
|
@ -3,9 +3,7 @@
|
||||
//! This lint is **warn** by default
|
||||
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::utils::{
|
||||
higher, is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg,
|
||||
};
|
||||
use crate::utils::{is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg};
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
|
||||
@ -71,7 +69,7 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);
|
||||
impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
use self::Expression::{Bool, RetBool};
|
||||
if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) {
|
||||
if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.kind {
|
||||
let reduce = |ret, not| {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
|
||||
|
@ -8,7 +8,7 @@ use rustc_ast::ast::Attribute;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind};
|
||||
use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, TypeFoldable};
|
||||
@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]);
|
||||
impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
||||
if let hir::ItemKind::Impl {
|
||||
if let hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: None, items, ..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
for assoc_item in items {
|
||||
if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind {
|
||||
|
@ -7,7 +7,7 @@ use std::ptr;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{
|
||||
BodyId, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
|
||||
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
|
||||
};
|
||||
use rustc_infer::traits::specialization_graph;
|
||||
use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||
@ -275,10 +275,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
|
||||
let item = cx.tcx.hir().expect_item(item_hir_id);
|
||||
|
||||
match &item.kind {
|
||||
ItemKind::Impl {
|
||||
ItemKind::Impl(Impl {
|
||||
of_trait: Some(of_trait_ref),
|
||||
..
|
||||
} => {
|
||||
}) => {
|
||||
if_chain! {
|
||||
// Lint a trait impl item only when the definition is a generic type,
|
||||
// assuming a assoc const is not meant to be a interior mutable type.
|
||||
@ -317,7 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
|
||||
}
|
||||
}
|
||||
},
|
||||
ItemKind::Impl { of_trait: None, .. } => {
|
||||
ItemKind::Impl(Impl { of_trait: None, .. }) => {
|
||||
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
|
||||
// Normalize assoc types originated from generic params.
|
||||
let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
|
||||
|
@ -109,25 +109,30 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
|
||||
/// it in curly braces. Otherwise, we don't.
|
||||
fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
|
||||
let mut should_wrap = false;
|
||||
|
||||
if let Some(Expr {
|
||||
kind:
|
||||
ExprKind::Match(
|
||||
_,
|
||||
arms,
|
||||
MatchSource::IfDesugar {
|
||||
contains_else_clause: true,
|
||||
}
|
||||
| MatchSource::IfLetDesugar {
|
||||
MatchSource::IfLetDesugar {
|
||||
contains_else_clause: true,
|
||||
},
|
||||
),
|
||||
..
|
||||
}) = parent.expr
|
||||
{
|
||||
expr.hir_id == arms[1].body.hir_id
|
||||
} else {
|
||||
false
|
||||
should_wrap = expr.hir_id == arms[1].body.hir_id;
|
||||
} else if let Some(Expr {
|
||||
kind: ExprKind::If(_, _, Some(else_clause)),
|
||||
..
|
||||
}) = parent.expr
|
||||
{
|
||||
should_wrap = expr.hir_id == else_clause.hir_id;
|
||||
}
|
||||
|
||||
should_wrap
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::utils::{is_automatically_derived, span_lint_hir};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_hir::{Impl, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
@ -34,7 +34,7 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]);
|
||||
impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if_chain! {
|
||||
if let ItemKind::Impl{ of_trait: Some(ref trait_ref), items: impl_items, .. } = item.kind;
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
|
||||
if !is_automatically_derived(&*item.attrs);
|
||||
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
|
||||
if trait_ref.path.res.def_id() == eq_trait;
|
||||
|
@ -6,7 +6,7 @@ use rustc_ast::attr;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node, PatKind};
|
||||
use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ use crate::utils::{
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind,
|
||||
Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
|
||||
BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item,
|
||||
ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
@ -132,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
|
||||
if let ImplItemKind::Fn(ref sig, body_id) = item.kind {
|
||||
let parent_item = cx.tcx.hir().get_parent_item(item.hir_id);
|
||||
if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) {
|
||||
if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind {
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = it.kind {
|
||||
return; // ignore trait impls
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use rustc_span::sym;
|
||||
|
||||
use crate::utils::sugg::Sugg;
|
||||
use crate::utils::{
|
||||
eq_expr_value, higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
|
||||
eq_expr_value, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
|
||||
span_lint_and_sugg,
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ impl QuestionMark {
|
||||
/// If it matches, it will suggest to use the question mark operator instead
|
||||
fn check_is_none_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if let Some((if_expr, body, else_)) = higher::if_block(&expr);
|
||||
if let ExprKind::If(if_expr, body, else_) = &expr.kind;
|
||||
if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind;
|
||||
if segment.ident.name == sym!(is_none);
|
||||
if Self::expression_returns_none(cx, body);
|
||||
|
@ -184,6 +184,14 @@ fn check_final_expr<'tcx>(
|
||||
ExprKind::Block(ref block, _) => {
|
||||
check_block_return(cx, block);
|
||||
},
|
||||
ExprKind::If(_, then, else_clause_opt) => {
|
||||
if let ExprKind::Block(ref ifblock, _) = then.kind {
|
||||
check_block_return(cx, ifblock);
|
||||
}
|
||||
if let Some(else_clause) = else_clause_opt {
|
||||
check_final_expr(cx, else_clause, None, RetReplacement::Empty);
|
||||
}
|
||||
},
|
||||
// a match expr, check all arms
|
||||
// an if/if let expr, check both exprs
|
||||
// note, if without else is going to be a type checking error anyways
|
||||
@ -194,10 +202,7 @@ fn check_final_expr<'tcx>(
|
||||
check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block);
|
||||
}
|
||||
},
|
||||
MatchSource::IfDesugar {
|
||||
contains_else_clause: true,
|
||||
}
|
||||
| MatchSource::IfLetDesugar {
|
||||
MatchSource::IfLetDesugar {
|
||||
contains_else_clause: true,
|
||||
} => {
|
||||
if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind {
|
||||
@ -212,6 +217,9 @@ fn check_final_expr<'tcx>(
|
||||
}
|
||||
|
||||
fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) {
|
||||
if ret_span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
match inner_span {
|
||||
Some(inner_span) => {
|
||||
if in_external_macro(cx.tcx.sess, inner_span) || inner_span.from_expansion() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::utils::{get_trait_def_id, paths, span_lint};
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_hir::{Impl, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
@ -22,11 +22,11 @@ declare_lint_pass!(SerdeAPI => [SERDE_API_MISUSE]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for SerdeAPI {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(ref trait_ref),
|
||||
items,
|
||||
..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
let did = trait_ref.path.res.def_id();
|
||||
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
|
||||
|
@ -333,6 +333,13 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
|
||||
check_expr(cx, e, bindings)
|
||||
}
|
||||
},
|
||||
ExprKind::If(ref cond, ref then, ref otherwise) => {
|
||||
check_expr(cx, cond, bindings);
|
||||
check_expr(cx, &**then, bindings);
|
||||
if let Some(ref o) = *otherwise {
|
||||
check_expr(cx, o, bindings);
|
||||
}
|
||||
},
|
||||
ExprKind::Match(ref init, arms, _) => {
|
||||
check_expr(cx, init, bindings);
|
||||
let len = bindings.len();
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind};
|
||||
use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
||||
@ -111,7 +111,7 @@ impl LateLintPass<'_> for ToStringInDisplay {
|
||||
|
||||
fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
if_chain! {
|
||||
if let ItemKind::Impl { of_trait: Some(trait_ref), .. } = &item.kind;
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind;
|
||||
if let Some(did) = trait_ref.trait_def_id();
|
||||
then {
|
||||
match_def_path(cx, did, &paths::DISPLAY_TRAIT)
|
||||
|
@ -260,7 +260,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
||||
fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
|
||||
// Skip trait implementations; see issue #605.
|
||||
if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) {
|
||||
if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
|
||||
if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2572,21 +2572,16 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||
}
|
||||
|
||||
match item.kind {
|
||||
ItemKind::Impl {
|
||||
ref generics,
|
||||
self_ty: ref ty,
|
||||
ref items,
|
||||
..
|
||||
} => {
|
||||
ItemKind::Impl(ref impl_) => {
|
||||
let mut vis = ImplicitHasherTypeVisitor::new(cx);
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_ty(impl_.self_ty);
|
||||
|
||||
for target in &vis.found {
|
||||
if differing_macro_contexts(item.span, target.span()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let generics_suggestion_span = generics.span.substitute_dummy({
|
||||
let generics_suggestion_span = impl_.generics.span.substitute_dummy({
|
||||
let pos = snippet_opt(cx, item.span.until(target.span()))
|
||||
.and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
|
||||
if let Some(pos) = pos {
|
||||
@ -2597,7 +2592,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||
});
|
||||
|
||||
let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
|
||||
for item in items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
|
||||
for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
|
||||
ctr_vis.visit_impl_item(item);
|
||||
}
|
||||
|
||||
@ -2610,7 +2605,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||
target.type_name()
|
||||
),
|
||||
move |diag| {
|
||||
suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
|
||||
suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::utils::{
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, ExprKind, FnDecl, HirId, ItemKind, Node};
|
||||
use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl { of_trait: Some(_), .. } | ItemKind::Trait(..)
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{HirId, ImplItem, ImplItemKind, ItemKind, Path};
|
||||
use rustc_hir::{HirId, Impl, ImplItem, ImplItemKind, ItemKind, Path};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
||||
let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
|
||||
let assoc_item = cx.tcx.associated_item(def_id);
|
||||
if_chain! {
|
||||
if let ItemKind::Impl { of_trait: None, .. } = parent_item.kind;
|
||||
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
|
||||
if assoc_item.fn_has_self_parameter;
|
||||
if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
|
||||
let body = cx.tcx.hir().body(*body_id);
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::utils::{
|
||||
differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then,
|
||||
usage::is_potentially_mutated,
|
||||
differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
|
||||
@ -158,7 +157,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
|
||||
if in_external_macro(self.cx.tcx.sess, expr.span) {
|
||||
return;
|
||||
}
|
||||
if let Some((cond, then, els)) = if_block(&expr) {
|
||||
if let ExprKind::If(cond, then, els) = &expr.kind {
|
||||
walk_expr(self, cond);
|
||||
self.visit_branch(cond, then, false);
|
||||
if let Some(els) = els {
|
||||
|
@ -181,8 +181,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
||||
return;
|
||||
}
|
||||
if_chain! {
|
||||
if let ItemKind::Impl{ self_ty: ref item_type, items: refs, .. } = item.kind;
|
||||
if let TyKind::Path(QPath::Resolved(_, ref item_path)) = item_type.kind;
|
||||
if let ItemKind::Impl(impl_) = &item.kind;
|
||||
if let TyKind::Path(QPath::Resolved(_, ref item_path)) = impl_.self_ty.kind;
|
||||
then {
|
||||
let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
|
||||
let should_check = parameters.as_ref().map_or(
|
||||
@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
||||
let impl_trait_ref = cx.tcx.impl_trait_ref(impl_def_id);
|
||||
|
||||
if let Some(impl_trait_ref) = impl_trait_ref {
|
||||
for impl_item_ref in refs {
|
||||
for impl_item_ref in impl_.items {
|
||||
let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
|
||||
if let ImplItemKind::Fn(FnSig{ decl: impl_decl, .. }, impl_body_id)
|
||||
= &impl_item.kind {
|
||||
@ -213,7 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for impl_item_ref in refs {
|
||||
for impl_item_ref in impl_.items {
|
||||
let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
|
||||
visitor.visit_impl_item(impl_item);
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool {
|
||||
match (l, r) {
|
||||
(Empty, Empty) => true,
|
||||
(Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts),
|
||||
(Eq(_, lts), Eq(_, rts)) => lts.eq_unspanned(rts),
|
||||
(Eq(_, lt), Eq(_, rt)) => lt.kind == rt.kind,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! A group of attributes that can be attached to Rust code in order
|
||||
//! to generate a clippy lint detecting said code automatically.
|
||||
|
||||
use crate::utils::{get_attr, higher};
|
||||
use crate::utils::get_attr;
|
||||
use rustc_ast::ast::{Attribute, LitFloatType, LitKind};
|
||||
use rustc_ast::walk_list;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -201,32 +201,6 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn visit_expr(&mut self, expr: &Expr<'_>) {
|
||||
// handle if desugarings
|
||||
// TODO add more desugarings here
|
||||
if let Some((cond, then, opt_else)) = higher::if_block(&expr) {
|
||||
let cond_pat = self.next("cond");
|
||||
let then_pat = self.next("then");
|
||||
if let Some(else_) = opt_else {
|
||||
let else_pat = self.next("else_");
|
||||
println!(
|
||||
" if let Some((ref {}, ref {}, Some({}))) = higher::if_block(&{});",
|
||||
cond_pat, then_pat, else_pat, self.current
|
||||
);
|
||||
self.current = else_pat;
|
||||
self.visit_expr(else_);
|
||||
} else {
|
||||
println!(
|
||||
" if let Some((ref {}, ref {}, None)) = higher::if_block(&{});",
|
||||
cond_pat, then_pat, self.current
|
||||
);
|
||||
}
|
||||
self.current = cond_pat;
|
||||
self.visit_expr(cond);
|
||||
self.current = then_pat;
|
||||
self.visit_expr(then);
|
||||
return;
|
||||
}
|
||||
|
||||
print!(" if let ExprKind::");
|
||||
let current = format!("{}.kind", self.current);
|
||||
match expr.kind {
|
||||
@ -351,6 +325,25 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
self.current = body_pat;
|
||||
self.visit_block(body);
|
||||
},
|
||||
ExprKind::If(ref cond, ref then, ref opt_else) => {
|
||||
let cond_pat = self.next("cond");
|
||||
let then_pat = self.next("then");
|
||||
if let Some(ref else_) = *opt_else {
|
||||
let else_pat = self.next("else_");
|
||||
println!(
|
||||
"If(ref {}, ref {}, Some(ref {})) = {};",
|
||||
cond_pat, then_pat, else_pat, current
|
||||
);
|
||||
self.current = else_pat;
|
||||
self.visit_expr(else_);
|
||||
} else {
|
||||
println!("If(ref {}, ref {}, None) = {};", cond_pat, then_pat, current);
|
||||
}
|
||||
self.current = cond_pat;
|
||||
self.visit_expr(cond);
|
||||
self.current = then_pat;
|
||||
self.visit_expr(then);
|
||||
},
|
||||
ExprKind::Match(ref expr, ref arms, desugaring) => {
|
||||
let des = desugaring_name(desugaring);
|
||||
let expr_pat = self.next("expr");
|
||||
@ -743,10 +736,6 @@ fn desugaring_name(des: hir::MatchSource) -> String {
|
||||
contains_else_clause
|
||||
),
|
||||
hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(),
|
||||
hir::MatchSource::IfDesugar { contains_else_clause } => format!(
|
||||
"MatchSource::IfDesugar {{ contains_else_clause: {} }}",
|
||||
contains_else_clause
|
||||
),
|
||||
hir::MatchSource::AwaitDesugar => "MatchSource::AwaitDesugar".to_string(),
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ fn identify_some_pure_patterns(expr: &Expr<'_>) -> bool {
|
||||
| ExprKind::Type(..)
|
||||
| ExprKind::DropTemps(..)
|
||||
| ExprKind::Loop(..)
|
||||
| ExprKind::If(..)
|
||||
| ExprKind::Match(..)
|
||||
| ExprKind::Closure(..)
|
||||
| ExprKind::Block(..)
|
||||
|
@ -170,33 +170,6 @@ pub fn while_loop<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx hir::Expr<
|
||||
None
|
||||
}
|
||||
|
||||
/// Recover the essential nodes of a desugared if block
|
||||
/// `if cond { then } else { els }` becomes `(cond, then, Some(els))`
|
||||
pub fn if_block<'tcx>(
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Option<(
|
||||
&'tcx hir::Expr<'tcx>,
|
||||
&'tcx hir::Expr<'tcx>,
|
||||
Option<&'tcx hir::Expr<'tcx>>,
|
||||
)> {
|
||||
if let hir::ExprKind::Match(ref cond, ref arms, hir::MatchSource::IfDesugar { contains_else_clause }) = expr.kind {
|
||||
let cond = if let hir::ExprKind::DropTemps(ref cond) = cond.kind {
|
||||
cond
|
||||
} else {
|
||||
panic!("If block desugar must contain DropTemps");
|
||||
};
|
||||
let then = &arms[0].body;
|
||||
let els = if contains_else_clause {
|
||||
Some(&*arms[1].body)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some((cond, then, els))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Represent the pre-expansion arguments of a `vec!` invocation.
|
||||
pub enum VecArgs<'a> {
|
||||
/// `vec![elem; len]`
|
||||
@ -267,12 +240,11 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
|
||||
|
||||
if let ExprKind::Block(ref block, _) = e.kind {
|
||||
if block.stmts.len() == 1 {
|
||||
if let StmtKind::Semi(ref matchexpr) = block.stmts[0].kind {
|
||||
if let StmtKind::Semi(ref matchexpr) = block.stmts.get(0)?.kind {
|
||||
// macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
|
||||
if_chain! {
|
||||
if let ExprKind::Match(ref ifclause, _, _) = matchexpr.kind;
|
||||
if let ExprKind::DropTemps(ref droptmp) = ifclause.kind;
|
||||
if let ExprKind::Unary(UnOp::UnNot, condition) = droptmp.kind;
|
||||
if let ExprKind::If(ref clause, _, _) = matchexpr.kind;
|
||||
if let ExprKind::Unary(UnOp::UnNot, condition) = clause.kind;
|
||||
then {
|
||||
return Some(vec![condition]);
|
||||
}
|
||||
|
@ -119,6 +119,9 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
||||
(&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => {
|
||||
self.eq_expr(la, ra) && self.eq_expr(li, ri)
|
||||
},
|
||||
(&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => {
|
||||
self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
|
||||
},
|
||||
(&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
|
||||
(&ExprKind::Loop(ref lb, ref ll, ref lls), &ExprKind::Loop(ref rb, ref rl, ref rls)) => {
|
||||
lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name)
|
||||
@ -563,6 +566,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
self.hash_name(i.ident.name);
|
||||
}
|
||||
},
|
||||
ExprKind::If(ref cond, ref then, ref else_opt) => {
|
||||
let c: fn(_, _, _) -> _ = ExprKind::If;
|
||||
c.hash(&mut self.s);
|
||||
self.hash_expr(cond);
|
||||
self.hash_expr(&**then);
|
||||
if let Some(ref e) = *else_opt {
|
||||
self.hash_expr(e);
|
||||
}
|
||||
},
|
||||
ExprKind::Match(ref e, arms, ref s) => {
|
||||
self.hash_expr(e);
|
||||
|
||||
@ -743,7 +755,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
}
|
||||
for segment in path.segments {
|
||||
segment.ident.name.hash(&mut self.s);
|
||||
self.hash_generic_args(segment.generic_args().args);
|
||||
self.hash_generic_args(segment.args().args);
|
||||
}
|
||||
},
|
||||
QPath::TypeRelative(ref ty, ref segment) => {
|
||||
|
@ -213,6 +213,15 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
|
||||
hir::ExprKind::Loop(..) => {
|
||||
println!("{}Loop", ind);
|
||||
},
|
||||
hir::ExprKind::If(ref cond, _, ref else_opt) => {
|
||||
println!("{}If", ind);
|
||||
println!("{}condition:", ind);
|
||||
print_expr(cx, cond, indent + 1);
|
||||
if let Some(ref els) = *else_opt {
|
||||
println!("{}else:", ind);
|
||||
print_expr(cx, els, indent + 1);
|
||||
}
|
||||
},
|
||||
hir::ExprKind::Match(ref cond, _, ref source) => {
|
||||
println!("{}Match", ind);
|
||||
println!("{}condition:", ind);
|
||||
@ -423,13 +432,13 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
hir::ItemKind::TraitAlias(..) => {
|
||||
println!("trait alias");
|
||||
},
|
||||
hir::ItemKind::Impl {
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: Some(ref _trait_ref),
|
||||
..
|
||||
} => {
|
||||
}) => {
|
||||
println!("trait impl");
|
||||
},
|
||||
hir::ItemKind::Impl { of_trait: None, .. } => {
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) => {
|
||||
println!("impl");
|
||||
},
|
||||
}
|
||||
|
@ -377,11 +377,11 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
||||
} else if is_expn_of(item.span, "impl_lint_pass").is_some()
|
||||
|| is_expn_of(item.span, "declare_lint_pass").is_some()
|
||||
{
|
||||
if let hir::ItemKind::Impl {
|
||||
if let hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: None,
|
||||
items: ref impl_item_refs,
|
||||
..
|
||||
} = item.kind
|
||||
}) = item.kind
|
||||
{
|
||||
let mut collector = LintCollector {
|
||||
output: &mut self.registered_lints,
|
||||
|
@ -439,8 +439,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
|
||||
if_chain! {
|
||||
if parent_impl != hir::CRATE_HIR_ID;
|
||||
if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
|
||||
if let hir::ItemKind::Impl{ of_trait: trait_ref, .. } = &item.kind;
|
||||
then { return trait_ref.as_ref(); }
|
||||
if let hir::ItemKind::Impl(impl_) = &item.kind;
|
||||
then { return impl_.of_trait.as_ref(); }
|
||||
}
|
||||
None
|
||||
}
|
||||
@ -1405,7 +1405,7 @@ pub fn if_sequence<'tcx>(
|
||||
let mut conds = SmallVec::new();
|
||||
let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new();
|
||||
|
||||
while let Some((ref cond, ref then_expr, ref else_expr)) = higher::if_block(&expr) {
|
||||
while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind {
|
||||
conds.push(&**cond);
|
||||
if let ExprKind::Block(ref block, _) = then_expr.kind {
|
||||
blocks.push(block);
|
||||
@ -1434,12 +1434,13 @@ pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
|
||||
let map = cx.tcx.hir();
|
||||
let parent_id = map.get_parent_node(expr.hir_id);
|
||||
let parent_node = map.get(parent_id);
|
||||
|
||||
match parent_node {
|
||||
Node::Expr(e) => higher::if_block(&e).is_some(),
|
||||
Node::Arm(e) => higher::if_block(&e.body).is_some(),
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
parent_node,
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::If(_, _, _),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// Finds the attribute with the given name, if any
|
||||
@ -1530,7 +1531,7 @@ pub fn is_no_std_crate(krate: &Crate<'_>) -> bool {
|
||||
/// ```
|
||||
pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
|
||||
matches!(item.kind, ItemKind::Impl { of_trait: Some(_), .. })
|
||||
matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ impl<'a> Sugg<'a> {
|
||||
match expr.kind {
|
||||
hir::ExprKind::AddrOf(..)
|
||||
| hir::ExprKind::Box(..)
|
||||
| hir::ExprKind::If(..)
|
||||
| hir::ExprKind::Closure(..)
|
||||
| hir::ExprKind::Unary(..)
|
||||
| hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
|
||||
|
@ -101,6 +101,13 @@ where
|
||||
}
|
||||
} else {
|
||||
match expr.kind {
|
||||
hir::ExprKind::If(cond, then, else_opt) => {
|
||||
self.inside_stmt(true).visit_expr(cond);
|
||||
self.visit_expr(then);
|
||||
if let Some(el) = else_opt {
|
||||
self.visit_expr(el);
|
||||
}
|
||||
},
|
||||
hir::ExprKind::Match(cond, arms, _) => {
|
||||
self.inside_stmt(true).visit_expr(cond);
|
||||
for arm in arms {
|
||||
|
@ -62,7 +62,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
|
||||
fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
let parent_id = cx.tcx.hir().get_parent_item(hir_id);
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(parent_id)) {
|
||||
if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
|
||||
if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2021-01-02"
|
||||
channel = "nightly-2021-01-15"
|
||||
components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
if_chain! {
|
||||
if let StmtKind::Local(ref local) = stmt.kind;
|
||||
if let Some(ref init) = local.init;
|
||||
if let Some((ref cond, ref then, Some(else_))) = higher::if_block(&init);
|
||||
if let ExprKind::If(ref cond, ref then, Some(ref else_)) = init.kind;
|
||||
if let ExprKind::Block(ref block) = else_.kind;
|
||||
if let Some(trailing_expr) = &block.expr;
|
||||
if block.stmts.len() == 1;
|
||||
|
@ -86,6 +86,21 @@ fn borrows_but_not_last(value: bool) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! needed_return {
|
||||
($e:expr) => {
|
||||
if $e > 3 {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn test_return_in_macro() {
|
||||
// This will return and the macro below won't be executed. Removing the `return` from the macro
|
||||
// will change semantics.
|
||||
needed_return!(10);
|
||||
needed_return!(0);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = test_end_of_fn();
|
||||
let _ = test_no_semicolon();
|
||||
|
@ -86,6 +86,21 @@ fn borrows_but_not_last(value: bool) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! needed_return {
|
||||
($e:expr) => {
|
||||
if $e > 3 {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn test_return_in_macro() {
|
||||
// This will return and the macro below won't be executed. Removing the `return` from the macro
|
||||
// will change semantics.
|
||||
needed_return!(10);
|
||||
needed_return!(0);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = test_end_of_fn();
|
||||
let _ = test_no_semicolon();
|
||||
|
@ -14,7 +14,7 @@ note: return Err() instead of panicking
|
||||
--> $DIR/panic_in_result_fn_assertions.rs:9:9
|
||||
|
|
||||
LL | assert!(x == 5, "wrong argument");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
|
||||
|
@ -28,10 +28,11 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() {
|
||||
let clippy_minor = clippy_version.minor;
|
||||
let clippy_patch = clippy_version.patch;
|
||||
|
||||
// get the rustc version
|
||||
// this way the rust-toolchain file version is honored
|
||||
// get the rustc version either from the rustc installed with the toolchain file or from
|
||||
// `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
|
||||
let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
|
||||
let rustc_version = String::from_utf8(
|
||||
std::process::Command::new("rustc")
|
||||
std::process::Command::new(&rustc)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.expect("failed to run `rustc --version`")
|
||||
|
Loading…
Reference in New Issue
Block a user