diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7df3520422c..8a45cd22953 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -68,10 +68,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); - let args = self.arena.alloc_from_iter( - [&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)), - ); - hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) + let receiver = self.lower_expr(receiver); + let args = + self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x))); + hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span)) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index dd9590016b9..f168a44c043 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -711,8 +711,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); self.suggested = true; - } else if let hir::ExprKind::MethodCall(_path, args @ [_, ..], sp) = expr.kind - && let hir::ExprKind::Index(val, index) = args[0].kind + } else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind + && let hir::ExprKind::Index(val, index) = receiver.kind && expr.span == self.assign_span { // val[index].path(args..); @@ -724,7 +724,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ".get_mut(".to_string(), ), ( - index.span.shrink_to_hi().with_hi(args[0].span.hi()), + index.span.shrink_to_hi().with_hi(receiver.span.hi()), ").map(|val| val".to_string(), ), (sp.shrink_to_hi(), ")".to_string()), @@ -911,11 +911,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { [ Expr { kind: - MethodCall( - path_segment, - _args, - span, - ), + MethodCall(path_segment, _, _, span), hir_id, .. }, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 082dd869023..31233062e9b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -901,13 +901,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match expr.kind { hir::ExprKind::MethodCall(.., args, _) => { // only the first closre parameter of the method. args[0] is MethodCall PathSegment - for i in 1..args.len() { + + for arg in args { if let hir::ExprKind::Closure(hir::Closure { capture_clause: hir::CaptureBy::Ref, .. - }) = args[i].kind - { - closure_span = Some(args[i].span.shrink_to_lo()); + }) = arg.kind { + closure_span = Some(arg.span.shrink_to_lo()); break; } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 08282f13897..3367df56a29 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1893,7 +1893,7 @@ pub enum ExprKind<'hir> { /// the `hir_id` of the `MethodCall` node itself. /// /// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id - MethodCall(&'hir PathSegment<'hir>, &'hir [Expr<'hir>], Span), + MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'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`). @@ -3497,7 +3497,7 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Block<'_>, 48); static_assert_size!(Body<'_>, 32); - static_assert_size!(Expr<'_>, 56); + static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3d5e22add71..2f9b92bfb9f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1094,8 +1094,9 @@ 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, receiver, arguments, _) => { visitor.visit_path_segment(expression.span, segment); + visitor.visit_expr(receiver); walk_list!(visitor, visit_expr, arguments); } ExprKind::Binary(_, ref left_expression, ref right_expression) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 42663da8a3f..bb694bacfd7 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1181,9 +1181,14 @@ impl<'a> State<'a> { self.print_call_post(args) } - fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) { - let base_args = &args[1..]; - self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); + fn print_expr_method_call( + &mut self, + segment: &hir::PathSegment<'_>, + receiver: &hir::Expr<'_>, + args: &[hir::Expr<'_>], + ) { + let base_args = args; + self.print_expr_maybe_paren(&receiver, parser::PREC_POSTFIX); self.word("."); self.print_ident(segment.ident); @@ -1394,8 +1399,8 @@ impl<'a> State<'a> { hir::ExprKind::Call(func, args) => { self.print_expr_call(func, args); } - hir::ExprKind::MethodCall(segment, args, _) => { - self.print_expr_method_call(segment, args); + hir::ExprKind::MethodCall(segment, receiver, args, _) => { + self.print_expr_method_call(segment, receiver, args); } hir::ExprKind::Binary(op, lhs, rhs) => { self.print_expr_binary(op, lhs, rhs); @@ -2413,9 +2418,9 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool { contains_exterior_struct_lit(x) } - hir::ExprKind::MethodCall(.., exprs, _) => { + hir::ExprKind::MethodCall(_, receiver, ..) => { // `X { y: 1 }.bar(...)` - contains_exterior_struct_lit(&exprs[0]) + contains_exterior_struct_lit(receiver) } _ => false, diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 91a05367eee..9efd909f05b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -901,7 +901,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } } - hir::ExprKind::MethodCall(segment, _, _) => { + hir::ExprKind::MethodCall(segment, ..) => { if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) { let generics = tcx.generics_of(def_id); let insertable: Option<_> = try { @@ -1132,7 +1132,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { let generic_args = &generics.own_substs_no_defaults(tcx, substs) [generics.own_counts().lifetimes..]; let span = match expr.kind { - ExprKind::MethodCall(path, _, _) => path.ident.span, + ExprKind::MethodCall(path, ..) => path.ident.span, _ => expr.span, }; @@ -1181,7 +1181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { }) .any(|generics| generics.has_impl_trait()) }; - if let ExprKind::MethodCall(path, args, span) = expr.kind + if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind && let Some(substs) = self.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) @@ -1189,12 +1189,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { && !has_impl_trait(def_id) { let successor = - args.get(1).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); + args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); let substs = self.infcx.resolve_vars_if_possible(substs); self.update_infer_source(InferSource { span: path.ident.span, kind: InferSourceKind::FullyQualifiedMethodCall { - receiver: args.first().unwrap(), + receiver, successor, substs, def_id, diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 121fefdc620..fb79daf29ee 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { } // We only care about method call expressions. - if let hir::ExprKind::MethodCall(call, args, _) = &expr.kind { + if let hir::ExprKind::MethodCall(call, receiver, ..) = &expr.kind { if call.ident.name != sym::into_iter { return; } @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { }; // As this is a method call expression, we have at least one argument. - let receiver_arg = &args[0]; + let receiver_arg = receiver; let receiver_ty = cx.typeck_results().expr_ty(receiver_arg); let adjustments = cx.typeck_results().expr_adjustments(receiver_arg); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 48942211eba..7d62d5ac98d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2412,13 +2412,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { _ => {} } } - } else if let hir::ExprKind::MethodCall(_, ref args, _) = expr.kind { + } else if let hir::ExprKind::MethodCall(_, receiver, ..) = expr.kind { // Find problematic calls to `MaybeUninit::assume_init`. let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) { // This is a call to *some* method named `assume_init`. // See if the `self` parameter is one of the dangerous constructors. - if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind { + if let hir::ExprKind::Call(ref path_expr, _) = receiver.kind { if let hir::ExprKind::Path(ref qpath) = path_expr.kind { let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; match cx.tcx.get_diagnostic_name(def_id) { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 16b7d2cbbae..23e7f21adf8 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -51,7 +51,7 @@ fn typeck_results_of_method_fn<'tcx>( expr: &Expr<'_>, ) -> Option<(Span, DefId, ty::subst::SubstsRef<'tcx>)> { match expr.kind { - ExprKind::MethodCall(segment, _, _) + ExprKind::MethodCall(segment, ..) if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => { Some((segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id))) diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index ff5a01749c1..646812589e3 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -44,9 +44,13 @@ fn in_macro(span: Span) -> bool { fn first_method_call<'tcx>( expr: &'tcx Expr<'tcx>, -) -> Option<(&'tcx PathSegment<'tcx>, &'tcx [Expr<'tcx>])> { - if let ExprKind::MethodCall(path, args, _) = &expr.kind { - if args.iter().any(|e| e.span.from_expansion()) { None } else { Some((path, *args)) } +) -> Option<(&'tcx PathSegment<'tcx>, &'tcx Expr<'tcx>)> { + if let ExprKind::MethodCall(path, receiver, args, ..) = &expr.kind { + if args.iter().any(|e| e.span.from_expansion()) || receiver.span.from_expansion() { + None + } else { + Some((path, *receiver)) + } } else { None } @@ -59,14 +63,14 @@ impl<'tcx> LateLintPass<'tcx> for TemporaryCStringAsPtr { } match first_method_call(expr) { - Some((path, args)) if path.ident.name == sym::as_ptr => { - let unwrap_arg = &args[0]; + Some((path, receiver)) if path.ident.name == sym::as_ptr => { + let unwrap_arg = receiver; let as_ptr_span = path.ident.span; match first_method_call(unwrap_arg) { - Some((path, args)) + Some((path, receiver)) if path.ident.name == sym::unwrap || path.ident.name == sym::expect => { - let source_arg = &args[0]; + let source_arg = receiver; lint_cstring_as_ptr(cx, as_ptr_span, source_arg, unwrap_arg); } _ => return, diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 11a752ff097..d1449496d33 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -41,7 +41,7 @@ declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]); impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // We only care about method calls. - let ExprKind::MethodCall(call, elements, _) = &expr.kind else { + let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else { return }; // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow` @@ -81,7 +81,6 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { ) { return; } - let receiver = &elements[0]; let receiver_ty = cx.typeck_results().expr_ty(receiver); let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); if receiver_ty != expr_ty { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 03166519981..9736b555703 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1458,7 +1458,7 @@ impl InvalidAtomicOrdering { sym::AtomicI64, sym::AtomicI128, ]; - if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind + if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind && recognized_names.contains(&method_path.ident.name) && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && let Some(impl_did) = cx.tcx.impl_of_method(m_def_id) @@ -1494,8 +1494,8 @@ impl InvalidAtomicOrdering { fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store]) && let Some((ordering_arg, invalid_ordering)) = match method { - sym::load => Some((&args[1], sym::Release)), - sym::store => Some((&args[2], sym::Acquire)), + sym::load => Some((&args[0], sym::Release)), + sym::store => Some((&args[1], sym::Acquire)), _ => None, } && let Some(ordering) = Self::match_ordering(cx, ordering_arg) @@ -1536,8 +1536,8 @@ impl InvalidAtomicOrdering { else {return }; let fail_order_arg = match method { - sym::fetch_update => &args[2], - sym::compare_exchange | sym::compare_exchange_weak => &args[4], + sym::fetch_update => &args[1], + sym::compare_exchange | sym::compare_exchange_weak => &args[3], _ => return, }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 9ed1c064d2b..b4b5a9d868d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -261,15 +261,18 @@ impl<'tcx> Cx<'tcx> { let kind = match expr.kind { // Here comes the interesting stuff: - hir::ExprKind::MethodCall(segment, ref args, fn_span) => { + hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => { // Rewrite a.b(c) into UFCS form like Trait::b(a, c) let expr = self.method_callee(expr, segment.ident.span, None); // When we apply adjustments to the receiver, use the span of // the overall method call for better diagnostics. args[0] // is guaranteed to exist, since a method call always has a receiver. - let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span)); + let old_adjustment_span = self.adjustment_span.replace((receiver.hir_id, expr_span)); info!("Using method span: {:?}", expr.span); - let args = self.mirror_exprs(args); + let args = std::iter::once(receiver) + .chain(args.iter()) + .map(|expr| self.mirror_expr(expr)) + .collect(); self.adjustment_span = old_adjustment_span; ExprKind::Call { ty: expr.ty, diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 2a6889af7c2..214d357cae0 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1039,9 +1039,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&f, succ) } - hir::ExprKind::MethodCall(.., ref args, _) => { + hir::ExprKind::MethodCall(.., receiver, ref args, _) => { let succ = self.check_is_ty_uninhabited(expr, succ); - self.propagate_through_exprs(args, succ) + std::iter::once(receiver) + .chain(args.iter()) + .rev() + .fold(succ, |succ, expr| self.propagate_through_expr(expr, succ)) } hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ), diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index c9fc6b9e47a..1bd6b857e06 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -803,6 +803,7 @@ impl<'tcx> DumpVisitor<'tcx> { &mut self, ex: &'tcx hir::Expr<'tcx>, seg: &'tcx hir::PathSegment<'tcx>, + receiver: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], ) { debug!("process_method_call {:?} {:?}", ex, ex.span); @@ -823,6 +824,7 @@ impl<'tcx> DumpVisitor<'tcx> { } // walk receiver and args + self.visit_expr(receiver); walk_list!(self, visit_expr, args); } @@ -1340,7 +1342,9 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'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), *rest) } - hir::ExprKind::MethodCall(ref seg, args, _) => self.process_method_call(ex, seg, args), + hir::ExprKind::MethodCall(ref seg, receiver, args, _) => { + self.process_method_call(ex, seg, receiver, args) + } hir::ExprKind::Field(ref sub_ex, _) => { self.visit_expr(&sub_ex); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 4a3d69f5b6c..7ea3ed06e61 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -590,7 +590,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_params_len = closure_fn_decl.inputs.len(); let ( Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(method_path, method_expr, _), + kind: hir::ExprKind::MethodCall(method_path, receiver, ..), .. })), 1, @@ -598,7 +598,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let self_ty = self.typeck_results.borrow().expr_ty(&method_expr[0]); + let self_ty = self.typeck_results.borrow().expr_ty(receiver); let name = method_path.ident.name; let is_as_ref_able = match self_ty.peel_refs().kind() { ty::Adt(def, _) => { @@ -767,11 +767,11 @@ 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, ref args, _) = expr.kind { + if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind { let clone_trait = self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span)); - if let ([arg], Some(true), sym::clone) = ( - &args[..], + if let (true, Some(true), sym::clone) = ( + args.is_empty(), self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map( |did| { let ai = self.tcx.associated_item(did); @@ -782,7 +782,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // If this expression had a clone call when suggesting borrowing // we want to suggest removing it because it'd now be unnecessary. - sugg_sp = arg.span; + sugg_sp = receiver.span; } } if let Ok(src) = sm.span_to_snippet(sugg_sp) { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 17ec8afc737..5c7b8121a61 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -324,8 +324,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected), ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected), - ExprKind::MethodCall(segment, args, _) => { - self.check_method_call(expr, segment, args, expected) + ExprKind::MethodCall(segment, receiver, args, _) => { + self.check_method_call(expr, segment, receiver, args, expected) } ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr), ExprKind::Type(e, t) => { @@ -1195,13 +1195,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &'tcx hir::Expr<'tcx>, segment: &hir::PathSegment<'_>, + receiver: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let rcvr = &args[0]; + let rcvr = &receiver; let rcvr_t = self.check_expr(&rcvr); // no need to check for bot/err -- callee does that - let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); + let rcvr_t = self.structurally_resolved_type(receiver.span, rcvr_t); let span = segment.ident.span; let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { @@ -1218,9 +1219,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_t, segment.ident, - SelfSource::MethodCall(&args[0]), + SelfSource::MethodCall(receiver), error, - Some(args), + Some((receiver, args)), ) { err.emit(); } @@ -1230,14 +1231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types( - span, - expr, - method, - &args[1..], - DontTupleArguments, - expected, - ) + self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected) } fn check_expr_cast( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 7e746b7387a..c59638f5d6f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -987,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if found != self.tcx.types.unit { return; } - if let ExprKind::MethodCall(path_segment, [rcvr, ..], _) = expr.kind { + if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind { if self .typeck_results .borrow() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d1d27db9131..3805de3cd4d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -478,7 +478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false), - hir::ExprKind::MethodCall(path_segment, _, span) => { + hir::ExprKind::MethodCall(path_segment, _, _, span) => { let ident_span = path_segment.ident.span; let ident_span = if let Some(args) = path_segment.args { ident_span.with_hi(args.span_ext.hi()) @@ -530,13 +530,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); let callee_expr = match &call_expr.peel_blocks().kind { hir::ExprKind::Call(callee, _) => Some(*callee), - hir::ExprKind::MethodCall(_, callee, _) => { + hir::ExprKind::MethodCall(_, receiver, ..) => { if let Some((DefKind::AssocFn, def_id)) = self.typeck_results.borrow().type_dependent_def(call_expr.hir_id) && let Some(assoc) = tcx.opt_associated_item(def_id) && assoc.fn_has_self_parameter { - Some(&callee[0]) + Some(*receiver) } else { None } @@ -1805,6 +1805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param, *call_hir_id, callee.span, + None, args, ) { @@ -1823,7 +1824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - hir::ExprKind::MethodCall(segment, args, ..) => { + hir::ExprKind::MethodCall(segment, receiver, args, ..) => { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() .flatten() @@ -1834,6 +1835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param, hir_id, segment.ident.span, + Some(receiver), args, ) { return true; @@ -1901,7 +1903,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_to_point_at: ty::GenericArg<'tcx>, call_hir_id: hir::HirId, callee_span: Span, - args: &[hir::Expr<'tcx>], + receiver: Option<&'tcx hir::Expr<'tcx>>, + args: &'tcx [hir::Expr<'tcx>], ) -> bool { let sig = self.tcx.fn_sig(def_id).skip_binder(); let args_referencing_param: Vec<_> = sig @@ -1910,6 +1913,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at)) .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 let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index d8527b9267e..3d9677ecf75 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -1049,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found_ty: Ty<'tcx>, expr: &hir::Expr<'_>, ) { - let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; }; + let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; }; let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; }; let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return }; let results = self.typeck_results.borrow(); diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs index 3e96b3ffb09..016f4056bd9 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs @@ -434,7 +434,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> { self.handle_uninhabited_return(expr); } - ExprKind::MethodCall(_, exprs, _) => { + ExprKind::MethodCall(_, receiver, exprs, _) => { + self.visit_expr(receiver); for expr in exprs { self.visit_expr(expr); } diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index 7c68d930405..392695cca68 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -160,7 +160,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if precise { let args = args .iter() - .skip(1) .map(|arg| { let span = arg.span.find_ancestor_inside(sp).unwrap_or_default(); format!( diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 998405bcbe1..124ac5c24fa 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, - args: Option<&'tcx [hir::Expr<'tcx>]>, + args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, ) -> Option> { // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { @@ -998,7 +998,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_ty, item_name, - args.map(|args| args.len()), + args.map(|(_, args)| args.len() + 1), source, out_of_scope_traits, &unsatisfied_predicates, @@ -2310,7 +2310,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { fn print_disambiguation_help<'tcx>( item_name: Ident, - args: Option<&'tcx [hir::Expr<'tcx>]>, + args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, @@ -2322,7 +2322,7 @@ fn print_disambiguation_help<'tcx>( fn_has_self_parameter: bool, ) { let mut applicability = Applicability::MachineApplicable; - let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) { + let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) { let args = format!( "({}{})", if rcvr_ty.is_region_ptr() { @@ -2330,7 +2330,8 @@ fn print_disambiguation_help<'tcx>( } else { "" }, - args.iter() + std::iter::once(receiver) + .chain(args.iter()) .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| { applicability = Applicability::HasPlaceholders; "_".to_owned() diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index bfc4f061b70..f483342b445 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -233,8 +233,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_exprs(args); } - hir::ExprKind::MethodCall(.., args, _) => { + hir::ExprKind::MethodCall(.., receiver, args, _) => { // callee.m(args) + self.consume_expr(receiver); self.consume_exprs(args); } diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index d4b5e5e2fe4..ec5d03300b1 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs @@ -758,13 +758,13 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { num_assoc_fn_excess_args: usize, num_trait_generics_except_self: usize, ) { - if let hir::ExprKind::MethodCall(_, args, _) = expr.kind { - assert_eq!(args.len(), 1); + if let hir::ExprKind::MethodCall(_, receiver, args, ..) = expr.kind { + assert_eq!(args.len(), 0); if num_assoc_fn_excess_args == num_trait_generics_except_self { if let Some(gen_args) = self.gen_args.span_ext() && let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args) - && let Ok(args) = self.tcx.sess.source_map().span_to_snippet(args[0].span) { - let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), args); + && let Ok(receiver) = self.tcx.sess.source_map().span_to_snippet(receiver.span) { + let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), receiver); err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect); } } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 0d968402503..ca86ac89e85 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -159,7 +159,7 @@ where return; } } - hir::ExprKind::MethodCall(path, _, call_span) => { + hir::ExprKind::MethodCall(path, _, _, call_span) => { let types = tcx.typeck(ex.hir_id.owner); let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else { trace!("type_dependent_def_id({}) = None", ex.hir_id);