Skip to content

Commit

Permalink
Auto merge of rust-lang#7047 - camsteffen:lang-ctor, r=flip1995
Browse files Browse the repository at this point in the history
Introduce `is_lang_ctor`

changelog: none

Replaces `is_some_ctor` and `is_ok_ctor`. Removes many path usages.
  • Loading branch information
bors committed Apr 12, 2021
2 parents f0ceb28 + 7468542 commit aecccbc
Show file tree
Hide file tree
Showing 17 changed files with 121 additions and 157 deletions.
27 changes: 8 additions & 19 deletions clippy_lints/src/collapsible_match.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::visitors::LocalUsedVisitor;
use clippy_utils::{path_to_local, SpanlessEq};
use clippy_utils::{is_lang_ctor, path_to_local, SpanlessEq};
use if_chain::if_chain;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind, UnOp};
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{DefIdTree, TyCtxt, TypeckResults};
use rustc_middle::ty::TypeckResults;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{MultiSpan, Span};

Expand Down Expand Up @@ -52,7 +52,7 @@ declare_lint_pass!(CollapsibleMatch => [COLLAPSIBLE_MATCH]);
impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
if let ExprKind::Match(_expr, arms, _source) = expr.kind {
if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(arm, cx.tcx)) {
if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) {
for arm in arms {
check_arm(arm, wild_arm, cx);
}
Expand All @@ -75,7 +75,7 @@ fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext
// match <local> { .. }
if let Some(binding_id) = path_to_local(strip_ref_operators(expr_in, cx.typeck_results()));
// one of the branches must be "wild-like"
if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(arm_inner, cx.tcx));
if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(cx, arm_inner));
let (wild_inner_arm, non_wild_inner_arm) =
(&arms_inner[wild_inner_arm_idx], &arms_inner[1 - wild_inner_arm_idx]);
if !pat_contains_or(non_wild_inner_arm.pat);
Expand Down Expand Up @@ -126,13 +126,13 @@ fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir>
/// A "wild-like" pattern is wild ("_") or `None`.
/// For this lint to apply, both the outer and inner match expressions
/// must have "wild-like" branches that can be combined.
fn arm_is_wild_like(arm: &Arm<'_>, tcx: TyCtxt<'_>) -> bool {
fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
if arm.guard.is_some() {
return false;
}
match arm.pat.kind {
PatKind::Binding(..) | PatKind::Wild => true,
PatKind::Path(QPath::Resolved(None, path)) if is_none_ctor(path.res, tcx) => true,
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
_ => false,
}
}
Expand Down Expand Up @@ -164,17 +164,6 @@ fn pat_contains_or(pat: &Pat<'_>) -> bool {
result
}

fn is_none_ctor(res: Res, tcx: TyCtxt<'_>) -> bool {
if let Some(none_id) = tcx.lang_items().option_none_variant() {
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = res {
if let Some(variant_id) = tcx.parent(id) {
return variant_id == none_id;
}
}
}
false
}

/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
fn strip_ref_operators<'hir>(mut expr: &'hir Expr<'hir>, typeck_results: &TypeckResults<'_>) -> &'hir Expr<'hir> {
Expand Down
9 changes: 5 additions & 4 deletions clippy_lints/src/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{match_qpath, meets_msrv, parent_node_is_if_expr};
use clippy_utils::{is_lang_ctor, meets_msrv, parent_node_is_if_expr};
use if_chain::if_chain;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
Expand Down Expand Up @@ -77,12 +78,12 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
if let Some(then_expr) = then_block.expr;
if let ExprKind::Call(then_call, [then_arg]) = then_expr.kind;
if let ExprKind::Path(ref then_call_qpath) = then_call.kind;
if match_qpath(then_call_qpath, &clippy_utils::paths::OPTION_SOME);
if is_lang_ctor(cx, then_call_qpath, OptionSome);
if let ExprKind::Block(els_block, _) = els.kind;
if els_block.stmts.is_empty();
if let Some(els_expr) = els_block.expr;
if let ExprKind::Path(ref els_call_qpath) = els_expr.kind;
if match_qpath(els_call_qpath, &clippy_utils::paths::OPTION_NONE);
if let ExprKind::Path(ref qpath) = els_expr.kind;
if is_lang_ctor(cx, qpath, OptionNone);
then {
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
Expand Down
11 changes: 6 additions & 5 deletions clippy_lints/src/loops/manual_flatten.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use super::utils::make_iterator_snippet;
use super::MANUAL_FLATTEN;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_ok_ctor, is_some_ctor, path_to_local_id};
use clippy_utils::{is_lang_ctor, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, StmtKind};
use rustc_hir::LangItem::{OptionSome, ResultOk};
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, StmtKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::source_map::Span;
Expand Down Expand Up @@ -42,9 +43,9 @@ pub(super) fn check<'tcx>(
if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind;
if path_to_local_id(match_expr, pat_hir_id);
// Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
if let PatKind::TupleStruct(QPath::Resolved(None, path), _, _) = match_arms[0].pat.kind;
let some_ctor = is_some_ctor(cx, path.res);
let ok_ctor = is_ok_ctor(cx, path.res);
if let PatKind::TupleStruct(ref qpath, _, _) = match_arms[0].pat.kind;
let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
if some_ctor || ok_ctor;
then {
let if_let_type = if some_ctor { "Some" } else { "Ok" };
Expand Down
35 changes: 8 additions & 27 deletions clippy_lints/src/manual_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::ty::{can_partially_move_ty, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
use clippy_utils::{in_constant, is_allowed, is_else_clause, match_def_path, match_var, paths, peel_hir_expr_refs};
use clippy_utils::{in_constant, is_allowed, is_else_clause, is_lang_ctor, match_var, peel_hir_expr_refs};
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{
def::Res,
intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
Expand Down Expand Up @@ -269,20 +270,9 @@ fn try_parse_pattern(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: SyntaxCon
match pat.kind {
PatKind::Wild => Some(OptionPat::Wild),
PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
PatKind::Path(QPath::Resolved(None, path))
if path
.res
.opt_def_id()
.map_or(false, |id| match_def_path(cx, id, &paths::OPTION_NONE)) =>
{
Some(OptionPat::None)
},
PatKind::TupleStruct(QPath::Resolved(None, path), [pattern], _)
if path
.res
.opt_def_id()
.map_or(false, |id| match_def_path(cx, id, &paths::OPTION_SOME))
&& pat.span.ctxt() == ctxt =>
PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None),
PatKind::TupleStruct(ref qpath, [pattern], _)
if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt =>
{
Some(OptionPat::Some { pattern, ref_count })
},
Expand All @@ -298,17 +288,11 @@ fn get_some_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ctxt: SyntaxConte
match expr.kind {
ExprKind::Call(
Expr {
kind: ExprKind::Path(QPath::Resolved(None, path)),
kind: ExprKind::Path(ref qpath),
..
},
[arg],
) if ctxt == expr.span.ctxt() => {
if match_def_path(cx, path.res.opt_def_id()?, &paths::OPTION_SOME) {
Some(arg)
} else {
None
}
},
) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(arg),
ExprKind::Block(
Block {
stmts: [],
Expand All @@ -324,10 +308,7 @@ fn get_some_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ctxt: SyntaxConte
// Checks for the `None` value.
fn is_none_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
match expr.kind {
ExprKind::Path(QPath::Resolved(None, path)) => path
.res
.opt_def_id()
.map_or(false, |id| match_def_path(cx, id, &paths::OPTION_NONE)),
ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
ExprKind::Block(
Block {
stmts: [],
Expand Down
9 changes: 5 additions & 4 deletions clippy_lints/src/manual_ok_or.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{match_qpath, path_to_local_id, paths};
use clippy_utils::{is_lang_ctor, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{ResultErr, ResultOk};
use rustc_hir::{Expr, ExprKind, PatKind};
use rustc_lint::LintContext;
use rustc_lint::{LateContext, LateLintPass};
Expand Down Expand Up @@ -54,7 +55,7 @@ impl LateLintPass<'_> for ManualOkOr {
let or_expr = &args[1];
if is_ok_wrapping(cx, &args[2]);
if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, &[ref err_arg]) = or_expr.kind;
if match_qpath(err_path, &paths::RESULT_ERR);
if is_lang_ctor(cx, err_path, ResultErr);
if let Some(method_receiver_snippet) = snippet_opt(cx, method_receiver.span);
if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span);
if let Some(indent) = indent_of(cx, scrutinee.span);
Expand All @@ -81,7 +82,7 @@ impl LateLintPass<'_> for ManualOkOr {

fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
if let ExprKind::Path(ref qpath) = map_expr.kind {
if match_qpath(qpath, &paths::RESULT_OK) {
if is_lang_ctor(cx, qpath, ResultOk) {
return true;
}
}
Expand All @@ -90,7 +91,7 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
let body = cx.tcx.hir().body(body_id);
if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;
if match_qpath(ok_path, &paths::RESULT_OK);
if is_lang_ctor(cx, ok_path, ResultOk);
then { path_to_local_id(ok_arg, param_id) } else { false }
}
}
25 changes: 12 additions & 13 deletions clippy_lints/src/manual_unwrap_or.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{in_constant, match_qpath, path_to_local_id, paths, sugg};
use clippy_utils::{in_constant, is_lang_ctor, path_to_local_id, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Arm, Expr, ExprKind, Pat, PatKind};
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::{Arm, Expr, ExprKind, PatKind};
use rustc_lint::LintContext;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
Expand Down Expand Up @@ -68,23 +69,21 @@ impl Case {
}

fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
fn applicable_or_arm<'a>(arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> {
fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> {
if_chain! {
if arms.len() == 2;
if arms.iter().all(|arm| arm.guard.is_none());
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)|
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
match arm.pat.kind {
PatKind::Path(ref some_qpath) =>
match_qpath(some_qpath, &paths::OPTION_NONE),
PatKind::TupleStruct(ref err_qpath, &[Pat { kind: PatKind::Wild, .. }], _) =>
match_qpath(err_qpath, &paths::RESULT_ERR),
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
PatKind::TupleStruct(ref qpath, &[pat], _) =>
matches!(pat.kind, PatKind::Wild) && is_lang_ctor(cx, qpath, ResultErr),
_ => false,
}
);
});
let unwrap_arm = &arms[1 - idx];
if let PatKind::TupleStruct(ref unwrap_qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind;
if match_qpath(unwrap_qpath, &paths::OPTION_SOME)
|| match_qpath(unwrap_qpath, &paths::RESULT_OK);
if let PatKind::TupleStruct(ref qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind;
if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
if path_to_local_id(unwrap_arm.body, binding_hir_id);
if !contains_return_break_continue_macro(or_arm.body);
Expand All @@ -106,7 +105,7 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
} else {
None
};
if let Some(or_arm) = applicable_or_arm(match_arms);
if let Some(or_arm) = applicable_or_arm(cx, match_arms);
if let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span);
if let Some(indent) = indent_of(cx, expr.span);
if constant_simple(cx, cx.typeck_results(), or_arm.body).is_some();
Expand Down
38 changes: 20 additions & 18 deletions clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
use clippy_utils::visitors::LocalUsedVisitor;
use clippy_utils::{
get_parent_expr, in_macro, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, meets_msrv, path_to_local,
get_parent_expr, in_macro, is_allowed, is_expn_of, is_lang_ctor, is_refutable, is_wild, meets_msrv, path_to_local,
path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks, strip_pat_refs,
};
use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{
self as hir, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource,
Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind,
Expand Down Expand Up @@ -1189,10 +1190,10 @@ fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], e

fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
let arm_ref: Option<BindingAnnotation> = if is_none_arm(&arms[0]) {
is_ref_some_arm(&arms[1])
} else if is_none_arm(&arms[1]) {
is_ref_some_arm(&arms[0])
let arm_ref: Option<BindingAnnotation> = if is_none_arm(cx, &arms[0]) {
is_ref_some_arm(cx, &arms[1])
} else if is_none_arm(cx, &arms[1]) {
is_ref_some_arm(cx, &arms[0])
} else {
None
};
Expand Down Expand Up @@ -1575,20 +1576,20 @@ fn is_unit_expr(expr: &Expr<'_>) -> bool {
}

// Checks if arm has the form `None => None`
fn is_none_arm(arm: &Arm<'_>) -> bool {
matches!(arm.pat.kind, PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE))
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
}

// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
fn is_ref_some_arm(arm: &Arm<'_>) -> Option<BindingAnnotation> {
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotation> {
if_chain! {
if let PatKind::TupleStruct(ref path, pats, _) = arm.pat.kind;
if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME);
if let PatKind::TupleStruct(ref qpath, pats, _) = arm.pat.kind;
if is_lang_ctor(cx, qpath, OptionSome);
if let PatKind::Binding(rb, .., ident, _) = pats[0].kind;
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
if let ExprKind::Call(e, args) = remove_blocks(arm.body).kind;
if let ExprKind::Path(ref some_path) = e.kind;
if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1;
if is_lang_ctor(cx, some_path, OptionSome) && args.len() == 1;
if let ExprKind::Path(QPath::Resolved(_, path2)) = args[0].kind;
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
then {
Expand Down Expand Up @@ -1700,10 +1701,11 @@ mod redundant_pattern_match {
use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::{is_trait_method, match_qpath, paths};
use clippy_utils::{is_lang_ctor, is_trait_method, match_qpath, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath};
use rustc_lint::LateContext;
use rustc_span::sym;
Expand Down Expand Up @@ -1735,13 +1737,13 @@ mod redundant_pattern_match {
let good_method = match kind {
PatKind::TupleStruct(ref path, patterns, _) if patterns.len() == 1 => {
if let PatKind::Wild = patterns[0].kind {
if match_qpath(path, &paths::RESULT_OK) {
if is_lang_ctor(cx, path, ResultOk) {
"is_ok()"
} else if match_qpath(path, &paths::RESULT_ERR) {
} else if is_lang_ctor(cx, path, ResultErr) {
"is_err()"
} else if match_qpath(path, &paths::OPTION_SOME) {
} else if is_lang_ctor(cx, path, OptionSome) {
"is_some()"
} else if match_qpath(path, &paths::POLL_READY) {
} else if is_lang_ctor(cx, path, PollReady) {
"is_ready()"
} else if match_qpath(path, &paths::IPADDR_V4) {
"is_ipv4()"
Expand All @@ -1755,9 +1757,9 @@ mod redundant_pattern_match {
}
},
PatKind::Path(ref path) => {
if match_qpath(path, &paths::OPTION_NONE) {
if is_lang_ctor(cx, path, OptionNone) {
"is_none()"
} else if match_qpath(path, &paths::POLL_PENDING) {
} else if is_lang_ctor(cx, path, PollPending) {
"is_pending()"
} else {
return;
Expand Down
Loading

0 comments on commit aecccbc

Please sign in to comment.