1
Fork 0

refactor: remove unnecessary variables

This commit is contained in:
Takayuki Maeda 2022-09-02 22:48:14 +09:00
parent 3955dc3480
commit fea1c5f5c8
17 changed files with 93 additions and 108 deletions

View file

@ -906,7 +906,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let hir::ExprKind::Closure(hir::Closure { if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref, capture_clause: hir::CaptureBy::Ref,
.. ..
}) = arg.kind { }) = arg.kind
{
closure_span = Some(arg.span.shrink_to_lo()); closure_span = Some(arg.span.shrink_to_lo());
break; break;
} }

View file

@ -1881,11 +1881,11 @@ pub enum ExprKind<'hir> {
/// ///
/// The `PathSegment` represents the method name and its generic arguments /// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets). /// (within the angle brackets).
/// The first element of the `&[Expr]` is the expression that evaluates /// The `&Expr` is the expression that evaluates
/// to the object on which the method is being called on (the receiver), /// to the object on which the method is being called on (the receiver),
/// and the remaining elements are the rest of the arguments. /// and the `&[Expr]` is the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d], span)`. /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d], span)`.
/// The final `Span` represents the span of the function and arguments /// The final `Span` represents the span of the function and arguments
/// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)` /// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
/// ///

View file

@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
} }
// We only care about method call expressions. // We only care about method call expressions.
if let hir::ExprKind::MethodCall(call, receiver, ..) = &expr.kind { if let hir::ExprKind::MethodCall(call, receiver_arg, ..) = &expr.kind {
if call.ident.name != sym::into_iter { if call.ident.name != sym::into_iter {
return; return;
} }
@ -75,7 +75,6 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
}; };
// As this is a method call expression, we have at least one argument. // As this is a method call expression, we have at least one argument.
let receiver_arg = receiver;
let receiver_ty = cx.typeck_results().expr_ty(receiver_arg); let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg); let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);

View file

@ -63,15 +63,13 @@ impl<'tcx> LateLintPass<'tcx> for TemporaryCStringAsPtr {
} }
match first_method_call(expr) { match first_method_call(expr) {
Some((path, receiver)) if path.ident.name == sym::as_ptr => { Some((path, unwrap_arg)) if path.ident.name == sym::as_ptr => {
let unwrap_arg = receiver;
let as_ptr_span = path.ident.span; let as_ptr_span = path.ident.span;
match first_method_call(unwrap_arg) { match first_method_call(unwrap_arg) {
Some((path, receiver)) Some((path, receiver))
if path.ident.name == sym::unwrap || path.ident.name == sym::expect => if path.ident.name == sym::unwrap || path.ident.name == sym::expect =>
{ {
let source_arg = receiver; lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg);
lint_cstring_as_ptr(cx, as_ptr_span, source_arg, unwrap_arg);
} }
_ => return, _ => return,
} }

View file

@ -267,7 +267,8 @@ impl<'tcx> Cx<'tcx> {
// When we apply adjustments to the receiver, use the span of // When we apply adjustments to the receiver, use the span of
// the overall method call for better diagnostics. args[0] // the overall method call for better diagnostics. args[0]
// is guaranteed to exist, since a method call always has a receiver. // is guaranteed to exist, since a method call always has a receiver.
let old_adjustment_span = self.adjustment_span.replace((receiver.hir_id, expr_span)); let old_adjustment_span =
self.adjustment_span.replace((receiver.hir_id, expr_span));
info!("Using method span: {:?}", expr.span); info!("Using method span: {:?}", expr.span);
let args = std::iter::once(receiver) let args = std::iter::once(receiver)
.chain(args.iter()) .chain(args.iter())

View file

@ -1041,10 +1041,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::MethodCall(.., receiver, ref args, _) => { hir::ExprKind::MethodCall(.., receiver, ref args, _) => {
let succ = self.check_is_ty_uninhabited(expr, succ); let succ = self.check_is_ty_uninhabited(expr, succ);
std::iter::once(receiver) let succ = args
.chain(args.iter()) .iter()
.rev() .rev()
.fold(succ, |succ, expr| self.propagate_through_expr(expr, succ)) .fold(succ, |succ, expr| self.propagate_through_expr(expr, succ));
self.propagate_through_expr(receiver, succ)
} }
hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ), hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ),

View file

@ -770,16 +770,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind { if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
let clone_trait = let clone_trait =
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span)); self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
if let (true, Some(true), sym::clone) = ( if args.is_empty()
args.is_empty(), && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
|did| { |did| {
let ai = self.tcx.associated_item(did); let ai = self.tcx.associated_item(did);
ai.trait_container(self.tcx) == Some(clone_trait) ai.trait_container(self.tcx) == Some(clone_trait)
}, },
), ) == Some(true)
segment.ident.name, && segment.ident.name == sym::clone
) { {
// If this expression had a clone call when suggesting borrowing // If this expression had a clone call when suggesting borrowing
// we want to suggest removing it because it'd now be unnecessary. // we want to suggest removing it because it'd now be unnecessary.
sugg_sp = receiver.span; sugg_sp = receiver.span;

View file

@ -1195,14 +1195,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
expr: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>,
segment: &hir::PathSegment<'_>, segment: &hir::PathSegment<'_>,
receiver: &'tcx hir::Expr<'tcx>, rcvr: &'tcx hir::Expr<'tcx>,
args: &'tcx [hir::Expr<'tcx>], args: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let rcvr = &receiver;
let rcvr_t = self.check_expr(&rcvr); let rcvr_t = self.check_expr(&rcvr);
// no need to check for bot/err -- callee does that // no need to check for bot/err -- callee does that
let rcvr_t = self.structurally_resolved_type(receiver.span, rcvr_t); let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t);
let span = segment.ident.span; let span = segment.ident.span;
let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
@ -1219,9 +1218,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span, span,
rcvr_t, rcvr_t,
segment.ident, segment.ident,
SelfSource::MethodCall(receiver), SelfSource::MethodCall(rcvr),
error, error,
Some((receiver, args)), Some((rcvr, args)),
) { ) {
err.emit(); err.emit();
} }

View file

@ -1913,14 +1913,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.enumerate() .enumerate()
.filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at)) .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
.collect(); .collect();
let args: Vec<&'tcx hir::Expr<'tcx>> = if let Some(receiver) = receiver {
std::iter::once(receiver).chain(args.iter()).collect()
} else {
args.iter().collect()
};
// If there's one field that references the given generic, great! // If there's one field that references the given generic, great!
if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) { if let [(idx, _)] = args_referencing_param.as_slice()
&& let Some(arg) = receiver
.map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span); error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
error.obligation.cause.map_code(|parent_code| { error.obligation.cause.map_code(|parent_code| {
ObligationCauseCode::FunctionArgumentObligation { ObligationCauseCode::FunctionArgumentObligation {

View file

@ -798,57 +798,55 @@ fn walk_parents<'tcx>(
}), }),
ExprKind::MethodCall(_, receiver, args, _) => { ExprKind::MethodCall(_, receiver, args, _) => {
let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(); let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
std::iter::once(receiver) if receiver.hir_id == child_id {
.chain(args.iter()) // Check for calls to trait methods where the trait is implemented on a reference.
// Two cases need to be handled:
// * `self` methods on `&T` will never have auto-borrow
// * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
// priority.
if e.hir_id != child_id {
return Some(Position::ReborrowStable(precedence))
} else if let Some(trait_id) = cx.tcx.trait_of_item(id)
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let subs = match cx
.typeck_results()
.node_substs_opt(parent.hir_id)
.and_then(|subs| subs.get(1..))
{
Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
} && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
// Trait methods taking `&self`
sub_ty
} else {
// Trait methods taking `self`
arg_ty
} && impl_ty.is_ref()
&& cx.tcx.infer_ctxt().enter(|infcx|
infcx
.type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
.must_apply_modulo_regions()
)
{
return Some(Position::MethodReceiverRefImpl)
} else {
return Some(Position::MethodReceiver)
}
}
args.iter()
.position(|arg| arg.hir_id == child_id) .position(|arg| arg.hir_id == child_id)
.map(|i| { .map(|i| {
if i == 0 { let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
// Check for calls to trait methods where the trait is implemented on a reference. if let ty::Param(param_ty) = ty.kind() {
// Two cases need to be handled: needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv)
// * `self` methods on `&T` will never have auto-borrow } else {
// * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take ty_auto_deref_stability(
// priority. cx,
if e.hir_id != child_id { cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
Position::ReborrowStable(precedence) precedence,
} else if let Some(trait_id) = cx.tcx.trait_of_item(id)
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let subs = match cx
.typeck_results()
.node_substs_opt(parent.hir_id)
.and_then(|subs| subs.get(1..))
{
Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
} && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
// Trait methods taking `&self`
sub_ty
} else {
// Trait methods taking `self`
arg_ty
} && impl_ty.is_ref()
&& cx.tcx.infer_ctxt().enter(|infcx|
infcx
.type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
.must_apply_modulo_regions()
) )
{ .position_for_arg()
Position::MethodReceiverRefImpl
} else {
Position::MethodReceiver
}
} else {
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
if let ty::Param(param_ty) = ty.kind() {
needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv)
} else {
ty_auto_deref_stability(
cx,
cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)),
precedence,
)
.position_for_arg()
}
} }
}) })
}, },

View file

@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for InfiniteIter {
MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"), MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"),
Finite => { Finite => {
return; return;
}, }
}; };
span_lint(cx, lint, expr.span, msg); span_lint(cx, lint, expr.span, msg);
} }
@ -229,11 +229,9 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
return MaybeInfinite.and(is_infinite(cx, receiver)); return MaybeInfinite.and(is_infinite(cx, receiver));
} }
} }
if method.ident.name == sym!(last) { if method.ident.name == sym!(last) && args.is_empty() {
let not_double_ended = cx let not_double_ended =
.tcx cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator).map_or(false, |id| {
.get_diagnostic_item(sym::DoubleEndedIterator)
.map_or(false, |id| {
!implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[]) !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])
}); });
if not_double_ended { if not_double_ended {

View file

@ -370,7 +370,7 @@ fn check_for_is_empty<'tcx>(
} }
fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
if let (&ExprKind::MethodCall(method_path, receiver, ..), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
// check if we are in an is_empty() method // check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) { if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" { if name.as_str() == "is_empty" {
@ -378,7 +378,7 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
} }
} }
check_len(cx, span, method_path.ident.name, receiver, &lit.node, op, compare_to); check_len(cx, span, method_path.ident.name, receiver, args, &lit.node, op, compare_to);
} else { } else {
check_empty_expr(cx, span, method, lit, op); check_empty_expr(cx, span, method, lit, op);
} }
@ -389,6 +389,7 @@ fn check_len(
span: Span, span: Span,
method_name: Symbol, method_name: Symbol,
receiver: &Expr<'_>, receiver: &Expr<'_>,
args: &[Expr<'_>],
lit: &LitKind, lit: &LitKind,
op: &str, op: &str,
compare_to: u32, compare_to: u32,
@ -399,7 +400,7 @@ fn check_len(
return; return;
} }
if method_name == sym::len && has_is_empty(cx, receiver) { if method_name == sym::len && args.is_empty() && has_is_empty(cx, receiver) {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,

View file

@ -21,10 +21,7 @@ pub(super) fn check(
receiver: &Expr<'_>, receiver: &Expr<'_>,
args: &[Expr<'_>], args: &[Expr<'_>],
) { ) {
let arg = match args { let arg = if method_name == sym::clone && args.is_empty() { receiver } else { return };
[] if method_name == sym::clone => receiver,
_ => return,
};
if cx if cx
.typeck_results() .typeck_results()
.type_dependent_def_id(expr.hir_id) .type_dependent_def_id(expr.hir_id)

View file

@ -20,8 +20,7 @@ pub(super) fn check(
if !(args.is_empty() && method_name == sym::clone) { if !(args.is_empty() && method_name == sym::clone) {
return; return;
} }
let arg = receiver; let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs();
if let ty::Adt(_, subst) = obj_ty.kind() { if let ty::Adt(_, subst) = obj_ty.kind() {
let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) { let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
@ -34,7 +33,7 @@ pub(super) fn check(
return; return;
}; };
let snippet = snippet_with_macro_callsite(cx, arg.span, ".."); let snippet = snippet_with_macro_callsite(cx, receiver.span, "..");
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,

View file

@ -3381,7 +3381,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
impl Methods { impl Methods {
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let Some((name, recv, [args @ ..], span)) = method_call(expr) { if let Some((name, recv, args, span)) = method_call(expr) {
match (name, args) { match (name, args) {
("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => { ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
zst_offset::check(cx, expr, recv); zst_offset::check(cx, expr, recv);
@ -3485,7 +3485,7 @@ impl Methods {
} }
}, },
("last", []) | ("skip", [_]) => { ("last", []) | ("skip", [_]) => {
if let Some((name2, recv2, [args2 @ ..], _span2)) = method_call(recv) { if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
if let ("cloned", []) = (name2, args2) { if let ("cloned", []) = (name2, args2) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false); iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
} }
@ -3500,7 +3500,7 @@ impl Methods {
} else { } else {
map_err_ignore::check(cx, expr, m_arg); map_err_ignore::check(cx, expr, m_arg);
} }
if let Some((name, recv2, [args @ ..], span2)) = method_call(recv) { if let Some((name, recv2, args, span2)) = method_call(recv) {
match (name, args) { match (name, args) {
("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv), ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv),
("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv), ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv),
@ -3520,7 +3520,7 @@ impl Methods {
manual_ok_or::check(cx, expr, recv, def, map); manual_ok_or::check(cx, expr, recv, def, map);
}, },
("next", []) => { ("next", []) => {
if let Some((name2, recv2, [args2 @ ..], _)) = method_call(recv) { if let Some((name2, recv2, args2, _)) = method_call(recv) {
match (name2, args2) { match (name2, args2) {
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false), ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
("filter", [arg]) => filter_next::check(cx, expr, recv2, arg), ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
@ -3593,7 +3593,7 @@ impl Methods {
}, },
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
("take", [_arg]) => { ("take", [_arg]) => {
if let Some((name2, recv2, [args2 @ ..], _span2)) = method_call(recv) { if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
if let ("cloned", []) = (name2, args2) { if let ("cloned", []) = (name2, args2) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false); iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
} }

View file

@ -109,14 +109,12 @@ fn fetch_const<'a>(
args: &'a [Expr<'a>], args: &'a [Expr<'a>],
m: MinMax, m: MinMax,
) -> Option<(MinMax, Constant, &'a Expr<'a>)> { ) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
if (receiver.is_some() && args.len() != 1) || (receiver.is_none() && args.len() != 2) { let mut args = receiver.into_iter().chain(args.into_iter());
let arg0 = args.next()?;
let arg1 = args.next()?;
if args.next().is_some() {
return None; return None;
} }
let (arg0, arg1) = if let Some(receiver) = receiver {
(receiver, &args[0])
} else {
(&args[0], &args[1])
};
constant_simple(cx, cx.typeck_results(), arg0).map_or_else( constant_simple(cx, cx.typeck_results(), arg0).map_or_else(
|| constant_simple(cx, cx.typeck_results(), arg1).map(|c| (m, c, arg0)), || constant_simple(cx, cx.typeck_results(), arg1).map(|c| (m, c, arg0)),
|c| { |c| {

View file

@ -150,7 +150,7 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
.. ..
}, },
self_arg, self_arg,
[remaining_args @ ..], remaining_args,
_, _,
) => { ) => {
let method_name = method_name_ident.name.as_str(); let method_name = method_name_ident.name.as_str();