Skip to content

Commit

Permalink
Auto merge of rust-lang#101261 - TaKO8Ki:separate-receiver-from-argum…
Browse files Browse the repository at this point in the history
…ents-in-hir, r=cjgillot

Separate the receiver from arguments in HIR

Related to rust-lang#100232

cc `@cjgillot`
  • Loading branch information
bors committed Sep 5, 2022
2 parents 5ea9977 + 8931da4 commit 2ccf843
Show file tree
Hide file tree
Showing 111 changed files with 677 additions and 586 deletions.
2 changes: 1 addition & 1 deletion book/src/development/common_tools_writing_lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Starting with an `expr`, you can check whether it is calling a specific method
impl<'tcx> LateLintPass<'tcx> for MyStructLint {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
// Check our expr is calling a method
if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind
if let hir::ExprKind::MethodCall(path, _, _self_arg, ..) = &expr.kind
// Check the name of this method is `some_method`
&& path.ident.name == sym!(some_method)
// Optionally, check the type of the self argument.
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/assertions_on_result_states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
&& matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro))
&& let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn)
&& matches!(panic_expn, PanicExpn::Empty)
&& let ExprKind::MethodCall(method_segment, [recv], _) = condition.kind
&& let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind
&& let result_type_with_refs = cx.typeck_results().expr_ty(recv)
&& let result_type = result_type_with_refs.peel_refs()
&& is_type_diagnostic_item(cx, result_type, sym::Result)
Expand Down
5 changes: 3 additions & 2 deletions clippy_lints/src/blocks_in_if_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
// do not lint if the closure is called using an iterator (see #1141)
if_chain! {
if let Some(parent) = get_parent_expr(self.cx, expr);
if let ExprKind::MethodCall(_, [self_arg, ..], _) = &parent.kind;
if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
let caller = self.cx.typeck_results().expr_ty(self_arg);
if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
if implements_trait(self.cx, caller, iter_id, &[]);
Expand Down Expand Up @@ -117,7 +117,8 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
);
}
} else {
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
let span =
block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
if span.from_expansion() || expr.span.from_expansion() {
return;
}
Expand Down
6 changes: 3 additions & 3 deletions clippy_lints/src/booleans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
))
})
},
ExprKind::MethodCall(path, args, _) if args.len() == 1 => {
let type_of_receiver = cx.typeck_results().expr_ty(&args[0]);
ExprKind::MethodCall(path, receiver, [], _) => {
let type_of_receiver = cx.typeck_results().expr_ty(receiver);
if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option)
&& !is_type_diagnostic_item(cx, type_of_receiver, sym::Result)
{
Expand All @@ -285,7 +285,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
let path: &str = path.ident.name.as_str();
a == path
})
.and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method)))
.and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method)))
},
_ => None,
}
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/casts/cast_abs_to_unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(super) fn check(
if meets_msrv(msrv, msrvs::UNSIGNED_ABS)
&& let ty::Int(from) = cast_from.kind()
&& let ty::Uint(to) = cast_to.kind()
&& let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind
&& let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind
&& method_path.ident.name.as_str() == "abs"
{
let span = if from.bit_width() == to.bit_width() {
Expand All @@ -37,7 +37,7 @@ pub(super) fn check(
span,
&format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
"replace with",
format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..").maybe_par()),
format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
Applicability::MachineApplicable,
);
}
Expand Down
6 changes: 3 additions & 3 deletions clippy_lints/src/casts/cast_possible_truncation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
.saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))),
_ => nbits,
},
ExprKind::MethodCall(method, [left, right], _) => {
ExprKind::MethodCall(method, left, [right], _) => {
if signed {
return nbits;
}
Expand All @@ -55,7 +55,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
};
apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
},
ExprKind::MethodCall(method, [_, lo, hi], _) => {
ExprKind::MethodCall(method, _, [lo, hi], _) => {
if method.ident.as_str() == "clamp" {
//FIXME: make this a diagnostic item
if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
Expand All @@ -64,7 +64,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
}
nbits
},
ExprKind::MethodCall(method, [_value], _) => {
ExprKind::MethodCall(method, _value, [], _) => {
if method.ident.name.as_str() == "signum" {
0 // do not lint if cast comes from a `signum` function
} else {
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/casts/cast_ptr_alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
cx.typeck_results().expr_ty(expr),
);
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
} else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind {
} else if let ExprKind::MethodCall(method_path, self_arg, ..) = &expr.kind {
if method_path.ident.name == sym!(cast)
&& let Some(generic_args) = method_path.args
&& let [GenericArg::Type(cast_to)] = generic_args.args
Expand Down Expand Up @@ -64,7 +64,7 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
return false;
};
match parent.kind {
ExprKind::MethodCall(name, [self_arg, ..], _) if self_arg.hir_id == e.hir_id => {
ExprKind::MethodCall(name, self_arg, ..) if self_arg.hir_id == e.hir_id => {
if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned")
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
&& let Some(def_id) = cx.tcx.impl_of_method(def_id)
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/casts/cast_sign_loss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
}

// Don't lint for the result of methods that always return non-negative values.
if let ExprKind::MethodCall(path, _, _) = cast_op.kind {
if let ExprKind::MethodCall(path, ..) = cast_op.kind {
let mut method_name = path.ident.name.as_str();
let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];

if_chain! {
if method_name == "unwrap";
if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]);
if let ExprKind::MethodCall(inner_path, _, _) = &arglist[0][0].kind;
if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind;
then {
method_name = inner_path.ident.name.as_str();
}
Expand Down
23 changes: 11 additions & 12 deletions clippy_lints/src/default_numeric_fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,7 @@ struct NumericFallbackVisitor<'a, 'tcx> {

impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
fn new(cx: &'a LateContext<'tcx>) -> Self {
Self {
ty_bounds: vec![TyBound::Nothing],
cx,
}
Self { ty_bounds: vec![TyBound::Nothing], cx }
}

/// Check whether a passed literal has potential to cause fallback or not.
Expand Down Expand Up @@ -129,19 +126,21 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
}
return;
}
},
}

ExprKind::MethodCall(_, args, _) => {
ExprKind::MethodCall(_, receiver, args, _) => {
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
for (expr, bound) in
iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs())
{
self.ty_bounds.push(TyBound::Ty(*bound));
self.visit_expr(expr);
self.ty_bounds.pop();
}
return;
}
},
}

ExprKind::Struct(_, fields, base) => {
let ty = self.cx.typeck_results().expr_ty(expr);
Expand Down Expand Up @@ -176,15 +175,15 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
return;
}
}
},
}

ExprKind::Lit(lit) => {
let ty = self.cx.typeck_results().expr_ty(expr);
self.check_lit(lit, ty, expr.hir_id);
return;
},
}

_ => {},
_ => {}
}

walk_expr(self, expr);
Expand All @@ -198,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
} else {
self.ty_bounds.push(TyBound::Nothing);
}
},
}

_ => self.ty_bounds.push(TyBound::Nothing),
}
Expand Down
83 changes: 42 additions & 41 deletions clippy_lints/src/dereference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ fn try_parse_ref_op<'tcx>(
expr: &'tcx Expr<'_>,
) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
let (def_id, arg) = match expr.kind {
ExprKind::MethodCall(_, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
ExprKind::MethodCall(_, arg, [], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
ExprKind::Call(
Expr {
kind: ExprKind::Path(path),
Expand Down Expand Up @@ -796,58 +796,59 @@ fn walk_parents<'tcx>(
},
})
}),
ExprKind::MethodCall(_, args, _) => {
ExprKind::MethodCall(_, receiver, args, _) => {
let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
if i == 0 {
// 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 {
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()
)
if receiver.hir_id == child_id {
// 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..))
{
Position::MethodReceiverRefImpl
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 {
Position::MethodReceiver
}
// 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 {
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
return Some(Position::MethodReceiver)
}
}
args.iter()
.position(|arg| arg.hir_id == child_id)
.map(|i| {
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
if let ty::Param(param_ty) = ty.kind() {
needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv)
needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv)
} else {
ty_auto_deref_stability(
cx,
cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)),
cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
precedence,
)
.position_for_arg()
}
}
})
})
},
ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {

// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
{
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
match expr.kind {
ExprKind::MethodCall(
_,
map,
[
map,
Expr {
kind: ExprKind::AddrOf(_, _, key),
span: key_span,
Expand Down Expand Up @@ -280,7 +280,7 @@ struct InsertExpr<'tcx> {
value: &'tcx Expr<'tcx>,
}
fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
if let ExprKind::MethodCall(_, [map, key, value], _) = expr.kind {
if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
Some(InsertExpr { map, key, value })
Expand Down
Loading

0 comments on commit 2ccf843

Please sign in to comment.