Rollup merge of #73182 - Aaron1011:feature/call-fn-span, r=matthewjasper

Track span of function in method calls, and use this in #[track_caller]

Fixes #69977

When we parse a chain of method calls like `foo.a().b().c()`, each
`MethodCallExpr` gets assigned a span that starts at the beginning of
the call chain (`foo`). While this is useful for diagnostics, it means
that `Location::caller` will return the same location for every call
in a call chain.

This PR makes us separately record the span of the function name and
arguments for a method call (e.g. `b()` in `foo.a().b().c()`). This
`Span` is passed through HIR lowering and MIR building to
`TerminatorKind::Call`, where it is used in preference to
`Terminator.source_info.span` when determining `Location::caller`.

This new span is also useful for diagnostics where we want to emphasize
a particular method call - for an example, see
https://github.com/rust-lang/rust/pull/72389#discussion_r436035990
This commit is contained in:
Dylan DPC 2020-06-11 19:04:16 +02:00 committed by GitHub
commit 84b9145076
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 243 additions and 146 deletions

View File

@ -1174,7 +1174,9 @@ pub enum ExprKind {
/// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
MethodCall(PathSegment, Vec<P<Expr>>),
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
MethodCall(PathSegment, Vec<P<Expr>>, Span),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).

View File

@ -1111,11 +1111,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f);
visit_exprs(args, vis);
}
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs) => {
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
vis.visit_ident(ident);
vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
visit_exprs(exprs, vis);
vis.visit_span(span);
}
ExprKind::Binary(_binop, lhs, rhs) => {
vis.visit_expr(lhs);

View File

@ -394,7 +394,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x)
}
ast::ExprKind::MethodCall(.., ref exprs) => {
ast::ExprKind::MethodCall(.., ref exprs, _) => {
// X { y: 1 }.bar(...)
contains_exterior_struct_lit(&exprs[0])
}

View File

@ -726,7 +726,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::MethodCall(ref segment, ref arguments) => {
ExprKind::MethodCall(ref segment, ref arguments, _span) => {
visitor.visit_path_segment(expression.span, segment);
walk_list!(visitor, visit_expr, arguments);
}

View File

@ -39,7 +39,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let f = self.lower_expr(f);
hir::ExprKind::Call(f, self.lower_exprs(args))
}
ExprKind::MethodCall(ref seg, ref args) => {
ExprKind::MethodCall(ref seg, ref args, span) => {
let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span,
seg,
@ -50,7 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
None,
));
let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);

View File

@ -1818,7 +1818,7 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args[..]);
}
ast::ExprKind::MethodCall(ref segment, ref args) => {
ast::ExprKind::MethodCall(ref segment, ref args, _) => {
self.print_expr_method_call(segment, &args[..]);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {

View File

@ -530,6 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args: &Vec<mir::Operand<'tcx>>,
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>,
fn_span: Span,
) {
let span = terminator.source_info.span;
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
@ -634,7 +635,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if intrinsic == Some("caller_location") {
if let Some((_, target)) = destination.as_ref() {
let location = self.get_caller_location(&mut bx, span);
let location = self.get_caller_location(&mut bx, fn_span);
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
location.val.store(&mut bx, tmp);
@ -798,7 +799,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args.len() + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
);
let location = self.get_caller_location(&mut bx, span);
let location = self.get_caller_location(&mut bx, fn_span);
debug!(
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
terminator, location, fn_span
);
let last_arg = fn_abi.args.last().unwrap();
self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
}
@ -1016,6 +1022,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ref destination,
cleanup,
from_hir_call: _,
fn_span,
} => {
self.codegen_call_terminator(
helper,
@ -1025,6 +1032,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args,
destination,
cleanup,
fn_span,
);
}
mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {

View File

@ -272,7 +272,7 @@ impl<'a> ExtCtxt<'a> {
) -> P<ast::Expr> {
args.insert(0, expr);
let segment = ast::PathSegment::from_ident(ident.with_span_pos(span));
self.expr(span, ast::ExprKind::MethodCall(segment, args))
self.expr(span, ast::ExprKind::MethodCall(segment, args, span))
}
pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
self.expr(b.span, ast::ExprKind::Block(b, None))

View File

@ -1371,7 +1371,7 @@ pub struct Expr<'hir> {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Expr<'static>, 64);
rustc_data_structures::static_assert_size!(Expr<'static>, 72);
impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence {
@ -1568,12 +1568,14 @@ pub enum ExprKind<'hir> {
/// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
/// 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)`
///
/// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
/// the `hir_id` of the `MethodCall` node itself.
///
/// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>]),
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(&'hir [Expr<'hir>]),
/// A binary operation (e.g., `a + b`, `a * b`).

View File

@ -1090,7 +1090,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::MethodCall(ref segment, _, arguments) => {
ExprKind::MethodCall(ref segment, _, arguments, _) => {
visitor.visit_path_segment(expression.span, segment);
walk_list!(visitor, visit_expr, arguments);
}

View File

@ -1308,7 +1308,7 @@ impl<'a> State<'a> {
hir::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(&func, args);
}
hir::ExprKind::MethodCall(ref segment, _, ref args) => {
hir::ExprKind::MethodCall(ref segment, _, ref args, _) => {
self.print_expr_method_call(segment, args);
}
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
@ -2491,7 +2491,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
contains_exterior_struct_lit(&x)
}
hir::ExprKind::MethodCall(.., ref exprs) => {
hir::ExprKind::MethodCall(.., ref exprs, _) => {
// `X { y: 1 }.bar(...)`
contains_exterior_struct_lit(&exprs[0])
}

View File

@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::MethodCall(_, call_span, exprs) = expr.kind {
if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
if call_span == self.target_span
&& Some(self.target)
== self.infcx.in_progress_tables.and_then(|tables| {
@ -294,7 +294,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// 3 | let _ = x.sum() as f64;
// | ^^^ cannot infer type for `S`
span
} else if let Some(ExprKind::MethodCall(_, call_span, _)) =
} else if let Some(ExprKind::MethodCall(_, call_span, _, _)) =
local_visitor.found_method_call.map(|e| &e.kind)
{
// Point at the call instead of the whole expression:

View File

@ -24,7 +24,7 @@ declare_lint_pass!(
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) {
// We only care about method call expressions.
if let hir::ExprKind::MethodCall(call, span, args) = &expr.kind {
if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind {
if call.ident.name != sym::into_iter {
return;
}

View File

@ -1899,7 +1899,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
}
}
}
} else if let hir::ExprKind::MethodCall(_, _, ref args) = expr.kind {
} else if let hir::ExprKind::MethodCall(_, _, ref args, _) = expr.kind {
// Find problematic calls to `MaybeUninit::assume_init`.
let def_id = cx.tables.type_dependent_def_id(expr.hir_id)?;
if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {

View File

@ -526,7 +526,7 @@ trait UnusedDelimLint {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
// first "argument" is self (which sometimes needs delims)
MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg),
MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
// actual catch-all arm
_ => {
return;

View File

@ -1131,6 +1131,9 @@ pub enum TerminatorKind<'tcx> {
/// `true` if this is from a call in HIR rather than from an overloaded
/// operator. True for overloaded function call.
from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
},
/// Jump to the target if the condition has the expected value,

View File

@ -42,7 +42,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
resume_arg: resume_arg.fold_with(folder),
drop,
},
Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
let dest =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
@ -52,6 +52,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
destination: dest,
cleanup,
from_hir_call,
fn_span,
}
}
Assert { ref cond, expected, ref msg, target, cleanup } => {

View File

@ -492,6 +492,7 @@ macro_rules! make_mir_visitor {
destination,
cleanup: _,
from_hir_call: _,
fn_span: _
} => {
self.visit_operand(func, source_location);
for arg in args {

View File

@ -142,6 +142,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.consume_operand(location, func);
for arg in args {

View File

@ -699,6 +699,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
ref destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.consume_operand(loc, (func, span), flow_state);
for arg in args {

View File

@ -467,7 +467,7 @@ impl Direction for Forward {
propagate(target, exit_state);
}
Call { cleanup, destination, ref func, ref args, from_hir_call: _ } => {
Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => {
if let Some(unwind) = cleanup {
if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
propagate(unwind, exit_state);

View File

@ -41,6 +41,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None,
from_hir_call: false,
fn_span: DUMMY_SP,
},
);
block(3, mir::TerminatorKind::Return);
@ -53,6 +54,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None,
from_hir_call: false,
fn_span: DUMMY_SP,
},
);

View File

@ -401,6 +401,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ref destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.gather_operand(func);
for arg in args {

View File

@ -1,6 +1,7 @@
use std::convert::TryFrom;
use rustc_hir::lang_items::PanicLocationLangItem;
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::subst::Subst;
use rustc_span::{Span, Symbol};
use rustc_target::abi::LayoutOf;
@ -14,19 +15,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`.
crate fn find_closest_untracked_caller_location(&self) -> Span {
self.stack()
let frame = self
.stack()
.iter()
.rev()
// Find first non-`#[track_caller]` frame.
.find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
.find(|frame| {
debug!(
"find_closest_untracked_caller_location: checking frame {:?}",
frame.instance
);
!frame.instance.def.requires_caller_location(*self.tcx)
})
// Assert that there is always such a frame.
.unwrap()
.current_source_info()
// Assert that the frame we look at is actually executing code currently
// (`current_source_info` is None when we are unwinding and the frame does
// not require cleanup).
.unwrap()
.span
.unwrap();
let loc = frame.loc.unwrap();
let block = &frame.body.basic_blocks()[loc.block];
assert_eq!(block.statements.len(), loc.statement_index);
debug!(
"find_closest_untracked_caller_location:: got terminator {:?} ({:?})",
block.terminator(),
block.terminator().kind
);
if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
return fn_span;
}
unreachable!();
}
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.

View File

@ -56,6 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
destination,
ref cleanup,
from_hir_call: _from_hir_call,
fn_span: _,
} => {
let old_stack = self.frame_idx();
let old_loc = self.frame().loc;

View File

@ -460,6 +460,7 @@ impl CloneShimBuilder<'tcx> {
destination: Some((dest, next)),
cleanup: Some(cleanup),
from_hir_call: true,
fn_span: self.span,
},
false,
);
@ -788,6 +789,7 @@ fn build_call_shim<'tcx>(
None
},
from_hir_call: true,
fn_span: span,
},
false,
);

View File

@ -909,7 +909,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
};
match terminator.kind {
TerminatorKind::Call { mut func, mut args, from_hir_call, .. } => {
TerminatorKind::Call { mut func, mut args, from_hir_call, fn_span, .. } => {
self.visit_operand(&mut func, loc);
for arg in &mut args {
self.visit_operand(arg, loc);
@ -925,6 +925,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
cleanup: None,
destination: Some((Place::from(new_temp), new_target)),
from_hir_call,
fn_span,
},
..terminator
};

View File

@ -368,7 +368,14 @@ fn check_terminator(
Err((span, "const fn generators are unstable".into()))
}
TerminatorKind::Call { func, args, from_hir_call: _, destination: _, cleanup: _ } => {
TerminatorKind::Call {
func,
args,
from_hir_call: _,
destination: _,
cleanup: _,
fn_span: _,
} => {
let fn_ty = func.ty(body, tcx);
if let ty::FnDef(def_id, _) = fn_ty.kind {
if !crate::const_eval::is_min_const_fn(tcx, def_id) {

View File

@ -644,6 +644,7 @@ where
destination: Some((unit_temp, succ)),
cleanup: unwind.into_option(),
from_hir_call: true,
fn_span: self.source_info.span,
},
source_info: self.source_info,
}),
@ -988,6 +989,7 @@ where
destination: Some((unit_temp, target)),
cleanup: None,
from_hir_call: false,
fn_span: self.source_info.span,
}; // FIXME(#43234)
let free_block = self.new_block(unwind, call);

View File

@ -162,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
});
exit_block.unit()
}
ExprKind::Call { ty, fun, args, from_hir_call } => {
ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
let intrinsic = match ty.kind {
ty::FnDef(def_id, _) => {
let f = ty.fn_sig(this.hir.tcx());
@ -206,6 +206,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.record_operands_moved(&args);
debug!("into_expr: fn_span={:?}", fn_span);
this.cfg.terminate(
block,
source_info,
@ -222,6 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some((destination, success))
},
from_hir_call,
fn_span
},
);
success.unit()

View File

@ -443,6 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Some((eq_result, eq_block)),
cleanup: Some(cleanup),
from_hir_call: false,
fn_span: source_info.span
},
);

View File

@ -139,11 +139,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
let kind = match expr.kind {
// Here comes the interesting stuff:
hir::ExprKind::MethodCall(_, method_span, ref args) => {
hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
// Rewrite a.b(c) into UFCS form like Trait::b(a, c)
let expr = method_callee(cx, expr, method_span, None);
let args = args.iter().map(|e| e.to_ref()).collect();
ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true }
ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true, fn_span }
}
hir::ExprKind::Call(ref fun, ref args) => {
@ -170,6 +170,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: method.to_ref(),
args: vec![fun.to_ref(), tupled_args.to_ref()],
from_hir_call: true,
fn_span: expr.span,
}
} else {
let adt_data =
@ -215,6 +216,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: fun.to_ref(),
args: args.to_ref(),
from_hir_call: true,
fn_span: expr.span,
}
}
}
@ -1024,7 +1026,7 @@ fn overloaded_operator<'a, 'tcx>(
args: Vec<ExprRef<'tcx>>,
) -> ExprKind<'tcx> {
let fun = method_callee(cx, expr, expr.span, None);
ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false }
ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false, fn_span: expr.span }
}
fn overloaded_place<'a, 'tcx>(
@ -1060,7 +1062,13 @@ fn overloaded_place<'a, 'tcx>(
temp_lifetime,
ty: ref_ty,
span: expr.span,
kind: ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false },
kind: ExprKind::Call {
ty: fun.ty,
fun: fun.to_ref(),
args,
from_hir_call: false,
fn_span: expr.span,
},
};
// construct and return a deref wrapper `*foo()`

View File

@ -146,6 +146,9 @@ crate enum ExprKind<'tcx> {
// Whether this is from a call in HIR, rather than from an overloaded
// operator. True for overloaded function call.
from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
},
Deref {
arg: ExprRef<'tcx>,

View File

@ -639,7 +639,7 @@ impl<'a> Parser<'a> {
ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "?",
ExprKind::Field(_, _) => "a field access",
ExprKind::MethodCall(_, _) => "a method call",
ExprKind::MethodCall(_, _, _) => "a method call",
ExprKind::Call(_, _) => "a function call",
ExprKind::Await(_) => "`.await`",
ExprKind::Err => return Ok(with_postfix),
@ -865,6 +865,7 @@ impl<'a> Parser<'a> {
return self.mk_await_expr(self_arg, lo);
}
let fn_span_lo = self.token.span;
let segment = self.parse_path_segment(PathStyle::Expr)?;
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
@ -873,8 +874,9 @@ impl<'a> Parser<'a> {
let mut args = self.parse_paren_expr_seq()?;
args.insert(0, self_arg);
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new()))
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new()))
} else {
// Field access `expr.f`
if let Some(args) = segment.args {

View File

@ -1198,7 +1198,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&f, succ)
}
hir::ExprKind::MethodCall(.., ref args) => {
hir::ExprKind::MethodCall(.., ref args, _) => {
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
let succ = if self.ir.tcx.is_ty_uninhabited_from(
m,

View File

@ -1302,7 +1302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
return;
}
}
hir::ExprKind::MethodCall(_, span, _) => {
hir::ExprKind::MethodCall(_, span, _, _) => {
// Method calls have to be checked specially.
self.span = span;
if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {

View File

@ -2117,7 +2117,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprKind::MethodCall(ref segment, ref arguments) => {
ExprKind::MethodCall(ref segment, ref arguments, _) => {
let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {

View File

@ -1404,7 +1404,9 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base)
}
hir::ExprKind::MethodCall(ref seg, _, args) => self.process_method_call(ex, seg, args),
hir::ExprKind::MethodCall(ref seg, _, args, _) => {
self.process_method_call(ex, seg, args)
}
hir::ExprKind::Field(ref sub_ex, _) => {
self.visit_expr(&sub_ex);

View File

@ -307,7 +307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
(
Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::MethodCall(path, span, expr),
kind: hir::ExprKind::MethodCall(path, span, expr, _),
..
})),
1,
@ -457,7 +457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if self.can_coerce(ref_ty, expected) {
let mut sugg_sp = sp;
if let hir::ExprKind::MethodCall(ref segment, sp, ref args) = expr.kind {
if let hir::ExprKind::MethodCall(ref segment, sp, ref args, _) = expr.kind {
let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp));
if let ([arg], Some(true), sym::clone) = (
&args[..],

View File

@ -182,7 +182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Call(ref callee, _) => {
self.warn_if_unreachable(expr.hir_id, callee.span, "call")
}
ExprKind::MethodCall(_, ref span, _) => {
ExprKind::MethodCall(_, ref span, _, _) => {
self.warn_if_unreachable(expr.hir_id, *span, "call")
}
_ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
@ -262,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ExprKind::Block(ref body, _) => self.check_block_with_expected(&body, expected),
ExprKind::Call(ref callee, ref args) => self.check_call(expr, &callee, args, expected),
ExprKind::MethodCall(ref segment, span, ref args) => {
ExprKind::MethodCall(ref segment, span, ref args, _) => {
self.check_method_call(expr, segment, span, args, expected, needs)
}
ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr),

View File

@ -3912,7 +3912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg_unit: bool| {
let (span, start_span, args) = match &expr.kind {
hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
hir::ExprKind::MethodCall(path_segment, span, args) => (
hir::ExprKind::MethodCall(path_segment, span, args, _) => (
*span,
// `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
path_segment

View File

@ -185,7 +185,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_exprs(args);
}
hir::ExprKind::MethodCall(.., ref args) => {
hir::ExprKind::MethodCall(.., ref args, _) => {
// callee.m(args)
self.consume_exprs(args);
}

View File

@ -84,9 +84,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
2 => {
let seg = PathSegment::from_ident(Ident::from_str("x"));
iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
seg.clone(), vec![e, make_x()])));
seg.clone(), vec![e, make_x()], DUMMY_SP)));
iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
seg.clone(), vec![make_x(), e])));
seg.clone(), vec![make_x(), e], DUMMY_SP)));
},
3..=8 => {
let op = Spanned {

View File

@ -0,0 +1,28 @@
// run-pass
#![feature(track_caller)]
use std::panic::Location;
struct Foo;
impl Foo {
#[track_caller]
fn check_loc(&self, line: u32, col: u32) -> &Self {
let loc = Location::caller();
assert_eq!(loc.file(), file!(), "file mismatch");
assert_eq!(loc.line(), line, "line mismatch");
assert_eq!(loc.column(), col, "column mismatch");
self
}
}
fn main() {
// Tests that when `Location::caller` is used in a method chain,
// it points to the start of the correct call (the first character after the dot)
// instead of to the very first expression in the chain
let foo = Foo;
foo.
check_loc(line!(), 9).check_loc(line!(), 31)
.check_loc(line!(), 10);
}

View File

@ -70,7 +70,7 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! {
if let ExprKind::MethodCall(ref method_path, _, args) = &expr.kind;
if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind;
let method = method_path.ident.name.as_str();
if type_is_atomic(cx, &args[0]);
if method == "load" || method == "store";

View File

@ -247,7 +247,7 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> {
))
})
},
ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
ExprKind::MethodCall(path, _, args, _) if args.len() == 1 => {
let type_of_receiver = cx.tables.expr_ty(&args[0]);
if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
&& !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))

View File

@ -38,10 +38,10 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! {
if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.kind;
if let ExprKind::MethodCall(ref count, _, ref count_args, _) = expr.kind;
if count.ident.name == sym!(count);
if count_args.len() == 1;
if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].kind;
if let ExprKind::MethodCall(ref filter, _, ref filter_args, _) = count_args[0].kind;
if filter.ident.name == sym!(filter);
if filter_args.len() == 2;
if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind {
return;
}
let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
let haystack = if let ExprKind::MethodCall(ref path, _, ref args, _) =
filter_args[0].kind {
let p = path.ident.name;
if (p == sym!(iter) || p == sym!(iter_mut)) && args.len() == 1 {

View File

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if !expr.span.from_expansion();
if let ExprKind::MethodCall(ref method_name, _, ref args) = &expr.kind;
if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind;
if args.len() == 1;
then {

View File

@ -70,7 +70,7 @@ impl EarlyLintPass for DoubleParens {
}
}
},
ExprKind::MethodCall(_, ref params) => {
ExprKind::MethodCall(_, ref params, _) => {
if params.len() == 2 {
let param = &params[1];
if let ExprKind::Paren(_) = param.kind {

View File

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind;
if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.kind;
if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION);
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
then {

View File

@ -103,7 +103,7 @@ fn check_cond<'a, 'tcx, 'b>(
check: &'b Expr<'b>,
) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = check.kind;
if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind;
if params.len() >= 2;
if path.ident.name == sym!(contains_key);
if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind;
@ -140,7 +140,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref params, _) = expr.kind;
if params.len() == 3;
if path.ident.name == sym!(insert);
if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);

View File

@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction {
}
match expr.kind {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
for arg in args {
check_closure(cx, arg)
}
@ -120,7 +120,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
);
if_chain!(
if let ExprKind::MethodCall(ref path, _, ref args) = ex.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = ex.kind;
// Not the same number of arguments, there is no way the closure is the same as the function return;
if args.len() == decl.inputs.len();

View File

@ -32,11 +32,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
// match call to unwrap
if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.kind;
if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind;
if unwrap_fun.ident.name == sym!(unwrap);
// match call to write_fmt
if !unwrap_args.is_empty();
if let ExprKind::MethodCall(ref write_fun, _, write_args) =
if let ExprKind::MethodCall(ref write_fun, _, write_args, _) =
unwrap_args[0].kind;
if write_fun.ident.name == sym!(write_fmt);
// match calls to std::io::stdout() / std::io::stderr ()

View File

@ -301,7 +301,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if cx.tables.expr_ty(lhs).is_floating_point();
if let Some((value, _)) = constant(cx, cx.tables, rhs);
if F32(1.0) == value || F64(1.0) == value;
if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
if let ExprKind::MethodCall(ref path, _, ref method_args, _) = lhs.kind;
if cx.tables.expr_ty(&method_args[0]).is_floating_point();
if path.ident.name.as_str() == "exp";
then {
@ -481,7 +481,7 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
let recv_ty = cx.tables.expr_ty(&args[0]);
if recv_ty.is_floating_point() {

View File

@ -104,7 +104,7 @@ fn on_argumentv1_new<'a, 'tcx>(
}
} else {
let snip = snippet(cx, format_args.span, "<arg>");
if let ExprKind::MethodCall(ref path, _, _) = format_args.kind {
if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
if path.ident.name == sym!(to_string) {
return Some(format!("{}", snip));
}

View File

@ -556,7 +556,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
}
}
},
hir::ExprKind::MethodCall(_, _, args) => {
hir::ExprKind::MethodCall(_, _, args, _) => {
let def_id = self.tables.type_dependent_def_id(expr.hir_id).unwrap();
let base_type = self.cx.tcx.type_of(def_id);
@ -610,7 +610,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
return;
}
match expr.kind {
Call(_, args) | MethodCall(_, _, args) => {
Call(_, args) | MethodCall(_, _, args, _) => {
let mut tys = FxHashSet::default();
for arg in args {
let def_id = arg.hir_id.owner.to_def_id();

View File

@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
// Is a method call
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
// Method name is "get"
if path.ident.name == sym!(get);
@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
) = &get_index_arg.kind;
// LHS of subtraction is "x.len()"
if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind;
if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind;
if arg_lhs_path.ident.name == sym!(len);
if let Some(arg_lhs_struct) = lhs_args.get(0);

View File

@ -147,7 +147,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> {
if_chain! {
if let ExprKind::MethodCall(path, _span, args) = &expr.kind;
if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind;
if path.ident.to_string() == "lock";
let ty = cx.tables.expr_ty(&args[0]);
if is_type_diagnostic_item(cx, ty, sym!(mutex_type));

View File

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
if_chain! { //begin checking variables
if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match
if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let
if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok()
if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type));

View File

@ -142,7 +142,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len, heuristic, cap) in &HEURISTICS {
if method.ident.name.as_str() == name && args.len() == len {
return (match heuristic {
@ -218,7 +218,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len) in &COMPLETING_METHODS {
if method.ident.name.as_str() == name && args.len() == len {
return is_infinite(cx, &args[0]);

View File

@ -211,7 +211,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[Imp
}
fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" {

View File

@ -526,7 +526,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
let pat = &arms[0].pat.kind;
if let (
&PatKind::TupleStruct(ref qpath, ref pat_args, _),
&ExprKind::MethodCall(ref method_path, _, ref method_args),
&ExprKind::MethodCall(ref method_path, _, ref method_args, _),
) = (pat, &match_expr.kind)
{
let iter_expr = &method_args[0];
@ -654,7 +654,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
| ExprKind::Struct(_, _, Some(ref e))
| ExprKind::Repeat(ref e, _)
| ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id),
ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => {
ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es, _) | ExprKind::Tup(ref es) => {
never_loop_expr_all(&mut es.iter(), main_loop_id)
},
ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
@ -806,7 +806,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
if_chain! {
if let ExprKind::MethodCall(method, _, args) = expr.kind;
if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
if method.ident.name == sym!(clone);
if args.len() == 1;
if let Some(arg) = args.get(0);
@ -915,7 +915,7 @@ fn build_manual_memcpy_suggestion<'a, 'tcx>(
let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| {
if_chain! {
if let ExprKind::MethodCall(method, _, len_args) = end.kind;
if let ExprKind::MethodCall(method, _, len_args, _) = end.kind;
if method.ident.name == sym!(len);
if len_args.len() == 1;
if let Some(arg) = len_args.get(0);
@ -1190,7 +1190,7 @@ fn check_for_loop_range<'a, 'tcx>(
fn is_len_call(expr: &Expr<'_>, var: Name) -> bool {
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.kind;
if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind;
if len_args.len() == 1;
if method.ident.name == sym!(len);
if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind;
@ -1244,7 +1244,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>,
fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
if let ExprKind::MethodCall(ref method, _, ref args) = arg.kind {
if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind {
// just the receiver, no arguments
if args.len() == 1 {
let method_name = &*method.ident.as_str();
@ -1718,7 +1718,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
// a range index op
if let ExprKind::MethodCall(ref meth, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref meth, _, ref args, _) = expr.kind;
if (meth.ident.name == sym!(index) && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(&args[1], &args[0], expr);
@ -1776,7 +1776,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
self.visit_expr(expr);
}
},
ExprKind::MethodCall(_, _, args) => {
ExprKind::MethodCall(_, _, args, _) => {
let def_id = self.cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
self.prefer_mutable = false;
@ -2369,8 +2369,8 @@ const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) {
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].kind;
if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind;
if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR);
if let Some(ref generic_args) = chain_method.args;
if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
@ -2437,7 +2437,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, '
fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span {
let mut current_expr = expr;
while let ExprKind::MethodCall(ref path, ref span, ref args) = current_expr.kind {
while let ExprKind::MethodCall(ref path, ref span, ref args, _) = current_expr.kind {
if path.ident.name == target_fn_name {
return expr.span.with_lo(span.lo());
}

View File

@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
}
if_chain! {
if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.kind;
if let hir::ExprKind::MethodCall(ref method, _, ref args, _) = e.kind;
if args.len() == 2;
if method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]);
@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
}
}
},
hir::ExprKind::MethodCall(ref method, _, ref obj) => {
hir::ExprKind::MethodCall(ref method, _, ref obj, _) => {
if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
&& match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {

View File

@ -125,7 +125,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>)
}
match expr.kind {
hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => {
hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _, _) => {
// Calls can't be reduced any more
Some(expr.span)
},

View File

@ -1429,7 +1429,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
}
match expr.kind {
hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => {
hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => {
lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
@ -1677,7 +1677,7 @@ fn lint_or_fun_call<'a, 'tcx>(
or_has_args: bool,
span: Span,
) {
if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.kind {
if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind {
if path.ident.as_str() == "len" {
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
@ -1751,7 +1751,7 @@ fn lint_or_fun_call<'a, 'tcx>(
);
}
},
hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case(
hir::ExprKind::MethodCall(_, span, ref or_args, _) => check_general_case(
cx,
name,
method_span,
@ -1782,7 +1782,7 @@ fn lint_expect_fun_call(
loop {
arg_root = match &arg_root.kind {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
hir::ExprKind::MethodCall(method_name, _, call_args) => {
hir::ExprKind::MethodCall(method_name, _, call_args, _) => {
if call_args.len() == 1
&& (method_name.ident.name == sym!(as_str) || method_name.ident.name == sym!(as_ref))
&& {
@ -2002,7 +2002,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir:
// &*x is a nop, &x.clone() is not
hir::ExprKind::AddrOf(..) => return,
// (*x).func() is useless, x.clone().func() can work in case func borrows mutably
hir::ExprKind::MethodCall(_, _, parent_args) if expr.hir_id == parent_args[0].hir_id => return,
hir::ExprKind::MethodCall(_, _, parent_args, _) if expr.hir_id == parent_args[0].hir_id => return,
_ => {},
},
@ -2478,7 +2478,7 @@ fn derefs_to_slice<'a, 'tcx>(
}
}
if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
if path.ident.name == sym!(iter) && may_slice(cx, cx.tables.expr_ty(&args[0])) {
Some(&args[0])
} else {
@ -3182,7 +3182,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, call_name: &str, a
// allow the `as_ref` or `as_mut` if it is followed by another method call
if_chain! {
if let Some(parent) = get_parent_expr(cx, expr);
if let hir::ExprKind::MethodCall(_, ref span, _) = parent.kind;
if let hir::ExprKind::MethodCall(_, ref span, _, _) = parent.kind;
if span != &expr.span;
then {
return;
@ -3310,7 +3310,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
let closure_expr = remove_blocks(&closure_body.value);
match &closure_expr.kind {
hir::ExprKind::MethodCall(_, _, args) => {
hir::ExprKind::MethodCall(_, _, args, _) => {
if_chain! {
if args.len() == 1;
if let hir::ExprKind::Path(qpath) = &args[0].kind;

View File

@ -545,7 +545,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
}
if_chain! {
if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.kind;
if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind;
if sym!(signum) == method_name.ident.name;
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
// the method call)
@ -572,7 +572,7 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
let (arg_ty, snip) = match expr.kind {
ExprKind::MethodCall(.., ref args) if args.len() == 1 => {
ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
(cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
} else {

View File

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
);
}
},
ExprKind::MethodCall(ref path, _, ref arguments) => {
ExprKind::MethodCall(ref path, _, ref arguments, _) => {
let def_id = cx.tables.type_dependent_def_id(e.hir_id).unwrap();
let substs = cx.tables.node_substs(e.hir_id);
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);

View File

@ -29,7 +29,7 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = e.kind {
if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new();
@ -57,7 +57,7 @@ enum OpenOption {
}
fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.kind {
if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions

View File

@ -35,7 +35,7 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! {
if let ExprKind::MethodCall(path_segment, args) = &expr.kind;
if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
let method_name = path_segment.ident.as_str();
if method_name == "expect" || method_name == "unwrap";
if let ExprKind::Call(caller, _) = &args[0].kind;

View File

@ -43,7 +43,7 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if path.ident.name == sym!(push);
if args.len() == 2;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF);

View File

@ -103,7 +103,7 @@ impl EarlyLintPass for Precedence {
}
if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind {
if let ExprKind::MethodCall(ref path_segment, ref args) = rhs.kind {
if let ExprKind::MethodCall(ref path_segment, ref args, _) = rhs.kind {
let path_segment_str = path_segment.ident.name.as_str();
if let Some(slf) = args.first() {
if let ExprKind::Lit(ref lit) = slf.kind {

View File

@ -90,7 +90,7 @@ fn expr_as_ptr_offset_call<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
expr: &'tcx Expr<'_>,
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
if let ExprKind::MethodCall(ref path_segment, _, ref args) = expr.kind {
if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind {
if is_expr_ty_raw_ptr(cx, &args[0]) {
if path_segment.ident.name == sym!(offset) {
return Some((&args[0], &args[1], Method::Offset));

View File

@ -50,7 +50,7 @@ impl QuestionMark {
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::MethodCall(segment, _, args) = &if_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);
if let Some(subject) = args.get(0);

View File

@ -129,20 +129,20 @@ declare_lint_pass!(Ranges => [
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
let name = path.ident.as_str();
if name == "zip" && args.len() == 2 {
let iter = &args[0].kind;
let zip_arg = &args[1];
if_chain! {
// `.iter()` call
if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
if let ExprKind::MethodCall(ref iter_path, _, ref iter_args , _) = *iter;
if iter_path.ident.name == sym!(iter);
// range expression in `.zip()` call: `0..x.len()`
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
if is_integer_const(cx, start, 0);
// `.len()` call
if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.kind;
if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;
if len_path.ident.name == sym!(len) && len_args.len() == 1;
// `.iter()` and `.len()` called on same `Path`
if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;

View File

@ -89,7 +89,7 @@ fn find_sugg_for_if_let<'a, 'tcx>(
// check that `while_let_on_iterator` lint does not trigger
if_chain! {
if keyword == "while";
if let ExprKind::MethodCall(method_path, _, _) = op.kind;
if let ExprKind::MethodCall(method_path, _, _, _) = op.kind;
if method_path.ident.name == sym!(next);
if match_trait_method(cx, op, &paths::ITERATOR);
then {

View File

@ -207,7 +207,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
if self.initialization_found;
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if let ExprKind::Path(ref qpath_subj) = args[0].kind;
if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
if path.ident.name == sym!(extend);
@ -224,7 +224,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
if self.initialization_found;
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if let ExprKind::Path(ref qpath_subj) = args[0].kind;
if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
if path.ident.name == sym!(resize);
@ -246,7 +246,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
/// Returns `true` if give expression is `repeat(0).take(...)`
fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
if_chain! {
if let ExprKind::MethodCall(ref take_path, _, ref take_args) = expr.kind;
if let ExprKind::MethodCall(ref take_path, _, ref take_args, _) = expr.kind;
if take_path.ident.name == sym!(take);
// Check that take is applied to `repeat(0)`

View File

@ -164,7 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
use rustc_ast::ast::LitKind;
if_chain! {
if let ExprKind::MethodCall(path, _, args) = &e.kind;
if let ExprKind::MethodCall(path, _, args, _) = &e.kind;
if path.ident.name == sym!(as_bytes);
if let ExprKind::Lit(lit) = &args[0].kind;
if let LitKind::Str(lit_content, _) = &lit.node;

View File

@ -34,12 +34,12 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ToDigitIsSome {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
if_chain! {
if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args) = &expr.kind;
if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args, _) = &expr.kind;
if is_some_path.ident.name.as_str() == "is_some";
if let [to_digit_expr] = &**is_some_args;
then {
let match_result = match &to_digit_expr.kind {
hir::ExprKind::MethodCall(to_digits_path, _, to_digit_args) => {
hir::ExprKind::MethodCall(to_digits_path, _, to_digit_args, _) => {
if_chain! {
if let [char_arg, radix_arg] = &**to_digit_args;
if to_digits_path.ident.name.as_str() == "to_digit";

View File

@ -778,7 +778,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg {
}
match expr.kind {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
let args_to_recover = args
.iter()
.filter(|arg| {
@ -1262,14 +1262,14 @@ fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>,
}
// don't lint for the result of methods that always return non-negative values
if let ExprKind::MethodCall(ref path, _, _) = op.kind {
if let ExprKind::MethodCall(ref path, _, _, _) = op.kind {
let mut method_name = path.ident.name.as_str();
let whitelisted_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
if_chain! {
if method_name == "unwrap";
if let Some(arglist) = method_chain_args(op, &["unwrap"]);
if let ExprKind::MethodCall(ref inner_path, _, _) = &arglist[0][0].kind;
if let ExprKind::MethodCall(ref inner_path, _, _, _) = &arglist[0][0].kind;
then {
method_name = inner_path.ident.name.as_str();
}

View File

@ -95,7 +95,7 @@ fn mirrored_exprs(
// The two exprs are method calls.
// Check to see that the function is the same and the arguments are mirrored
// This is enough because the receiver of the method is listed in the arguments
(ExprKind::MethodCall(left_segment, _, left_args), ExprKind::MethodCall(right_segment, _, right_args)) => {
(ExprKind::MethodCall(left_segment, _, left_args, _), ExprKind::MethodCall(right_segment, _, right_args, _)) => {
left_segment.ident == right_segment.ident
&& left_args
.iter()
@ -170,7 +170,7 @@ fn mirrored_exprs(
fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> {
if_chain! {
if let ExprKind::MethodCall(name_ident, _, args) = &expr.kind;
if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
if let name = name_ident.ident.name.to_ident_string();
if name == "sort_by" || name == "sort_unstable_by";
if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
@ -180,7 +180,7 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
] = &closure_body.params;
if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr]) = &closure_body.value.kind;
if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr], _) = &closure_body.value.kind;
if method_path.ident.name.to_ident_string() == "cmp";
then {
let (closure_body, closure_arg, reverse) = if mirrored_exprs(

View File

@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
}
},
hir::ExprKind::MethodCall(ref path, _, ref args) => match &*path.ident.as_str() {
hir::ExprKind::MethodCall(ref path, _, ref args, _) => match &*path.ident.as_str() {
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
check_method_call(cx, &args[0], expr);
},
@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
}
fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
if let hir::ExprKind::MethodCall(ref path, _, _) = call.kind {
if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind {
let symbol = &*path.ident.as_str();
let read_trait = match_trait_method(cx, call, &paths::IO_READ);
let write_trait = match_trait_method(cx, call, &paths::IO_WRITE);

View File

@ -112,7 +112,7 @@ fn collect_unwrap_info<'a, 'tcx>(
return collect_unwrap_info(cx, expr, branch, !invert);
} else {
if_chain! {
if let ExprKind::MethodCall(method_name, _, args) = &expr.kind;
if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind;
let ty = cx.tables.expr_ty(&args[0]);
let name = method_name.ident.as_str();
@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
} else {
// find `unwrap[_err]()` calls:
if_chain! {
if let ExprKind::MethodCall(ref method_name, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref method_name, _, ref args, _) = expr.kind;
if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].kind;
if [sym!(unwrap), sym!(unwrap_err)].contains(&method_name.ident.name);
let call_to_unwrap = method_name.ident.name == sym!(unwrap);

View File

@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
}
},
ExprKind::MethodCall(ref name, .., ref args) => {
ExprKind::MethodCall(ref name, .., ref args, _) => {
if match_trait_method(cx, e, &paths::INTO) && &*name.ident.as_str() == "into" {
let a = cx.tables.expr_ty(e);
let b = cx.tables.expr_ty(&args[0]);

View File

@ -120,7 +120,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
(Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
(MethodCall(lc, la), MethodCall(rc, ra)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
(MethodCall(lc, la, _), MethodCall(rc, ra, _)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
(Lit(l), Lit(r)) => l.kind == r.kind,

View File

@ -250,8 +250,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
self.visit_expr(arg);
}
},
ExprKind::MethodCall(ref _method_name, ref _generics, ref _args) => {
println!("MethodCall(ref method_name, ref generics, ref args) = {};", current);
ExprKind::MethodCall(ref _method_name, ref _generics, ref _args, ref _fn_span) => {
println!("MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};", current);
println!(" // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment");
},
ExprKind::Tup(ref elements) => {

View File

@ -132,7 +132,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
&& self.eq_pat(&l.pat, &r.pat)
})
},
(&ExprKind::MethodCall(l_path, _, l_args), &ExprKind::MethodCall(r_path, _, r_args)) => {
(&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
!self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
},
(&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => {
@ -542,7 +542,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
s.hash(&mut self.s);
},
ExprKind::MethodCall(ref path, ref _tys, args) => {
ExprKind::MethodCall(ref path, ref _tys, args, ref _fn_span) => {
self.hash_name(path.ident.name);
self.hash_exprs(args);
},

View File

@ -167,7 +167,7 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) {
print_expr(cx, arg, indent + 1);
}
},
hir::ExprKind::MethodCall(ref path, _, args) => {
hir::ExprKind::MethodCall(ref path, _, args, _) => {
println!("{}MethodCall", ind);
println!("{}method name: {}", ind, path.ident.name);
for arg in args {

View File

@ -402,7 +402,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
}
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
let fn_name = path.ident;
if let Some(sugg) = self.map.get(&*fn_name.as_str());
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
@ -491,7 +491,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls {
let stmts = &block.stmts;
if stmts.len() == 1 && block.expr.is_none();
if let StmtKind::Semi(only_expr) = &stmts[0].kind;
if let ExprKind::MethodCall(ref ps, _, ref span_call_args) = &only_expr.kind;
if let ExprKind::MethodCall(ref ps, _, ref span_call_args, _) = &only_expr.kind;
let and_then_snippets = get_and_then_snippets(cx, and_then_args);
let mut sle = SpanlessEq::new(cx).ignore_fn();
then {

View File

@ -379,7 +379,7 @@ pub fn method_calls<'tcx>(
let mut current = expr;
for _ in 0..max_depth {
if let ExprKind::MethodCall(path, span, args) = &current.kind {
if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
if args.iter().any(|e| e.span.from_expansion()) {
break;
}
@ -406,7 +406,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
let mut matched = Vec::with_capacity(methods.len());
for method_name in methods.iter().rev() {
// method chains are stored last -> first
if let ExprKind::MethodCall(ref path, _, ref args) = current.kind {
if let ExprKind::MethodCall(ref path, _, ref args, _) = current.kind {
if path.ident.name.as_str() == *method_name {
if args.iter().any(|e| e.span.from_expansion()) {
return None;
@ -1324,7 +1324,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool
None
}
},
ExprKind::MethodCall(_, _, _) => cx.tables.type_dependent_def_id(expr.hir_id),
ExprKind::MethodCall(_, _, _, _) => cx.tables.type_dependent_def_id(expr.hir_id),
_ => None,
};

View File

@ -58,7 +58,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
if self.abort {
return;
}
if let ExprKind::MethodCall(ref seg, _, ref args) = expr.kind {
if let ExprKind::MethodCall(ref seg, _, ref args, _) = expr.kind {
if args.len() == 1 && match_var(&args[0], self.name) {
if seg.ident.name.as_str() == "capacity" {
self.abort = true;

View File

@ -31,7 +31,7 @@ declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VecResizeToZero {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let hir::ExprKind::MethodCall(path_segment, _, ref args) = expr.kind;
if let hir::ExprKind::MethodCall(path_segment, _, ref args, _) = expr.kind;
if let Some(method_def_id) = cx.tables.type_dependent_def_id(expr.hir_id);
if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3;
if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind;

View File

@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads {
fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
if_chain! {
if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind;
if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
if method_name.ident.as_str() == "read_to_end";
if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
let ty = cx.tables.expr_ty(&exprs[0]);
@ -73,7 +73,7 @@ fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'t
fn is_file_read_to_string<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
if_chain! {
if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind;
if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
if method_name.ident.as_str() == "read_to_string";
if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
let ty = cx.tables.expr_ty(&exprs[0]);