Skip to content

Commit

Permalink
Auto merge of #101261 - TaKO8Ki:separate-receiver-from-arguments-in-h…
Browse files Browse the repository at this point in the history
…ir, r=cjgillot

Separate the receiver from arguments in HIR

Related to #100232

cc `@cjgillot`
  • Loading branch information
bors committed Sep 5, 2022
2 parents 2dc703f + 9cde34e commit b44197a
Show file tree
Hide file tree
Showing 140 changed files with 815 additions and 720 deletions.
8 changes: 4 additions & 4 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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..);
Expand All @@ -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()),
Expand Down Expand Up @@ -911,11 +911,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
[
Expr {
kind:
MethodCall(
path_segment,
_args,
span,
),
MethodCall(path_segment, _, _, span),
hir_id,
..
},
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,14 +900,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let mut closure_span = None::<rustc_span::Span>;
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
}) = arg.kind
{
closure_span = Some(args[i].span.shrink_to_lo());
closure_span = Some(arg.span.shrink_to_lo());
break;
}
}
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1876,19 +1876,19 @@ pub enum ExprKind<'hir> {
///
/// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets).
/// The first element of the `&[Expr]` is the expression that evaluates
/// The `&Expr` is the expression that evaluates
/// to the object on which the method is being called on (the receiver),
/// and the remaining elements are the rest of the arguments.
/// and the `&[Expr]` is the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d], span)`.
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d], span)`.
/// The final `Span` represents the span of the function and arguments
/// (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`]: ../../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`).
Expand Down Expand Up @@ -3492,8 +3492,8 @@ 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!(ExprKind<'_>, 40);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 48);
static_assert_size!(FnDecl<'_>, 40);
static_assert_size!(ForeignItem<'_>, 72);
static_assert_size!(ForeignItemKind<'_>, 40);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
19 changes: 12 additions & 7 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -2393,9 +2398,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,
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
};

Expand Down Expand Up @@ -1181,20 +1181,20 @@ 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)
&& self.infcx.tcx.trait_of_item(def_id).is_some()
&& !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,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_lint/src/array_into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_arg, ..) = &expr.kind {
if call.ident.name != sym::into_iter {
return;
}
Expand All @@ -75,7 +75,6 @@ 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_ty = cx.typeck_results().expr_ty(receiver_arg);
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_lint/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -59,15 +63,13 @@ 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, unwrap_arg)) if path.ident.name == sym::as_ptr => {
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];
lint_cstring_as_ptr(cx, as_ptr_span, source_arg, unwrap_arg);
lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg);
}
_ => return,
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_lint/src/noop_method_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
};

Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,19 @@ 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,
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,9 +1039,10 @@ 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)
let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(receiver, succ)
}

hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ),
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_save_analysis/src/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -823,6 +824,7 @@ impl<'tcx> DumpVisitor<'tcx> {
}

// walk receiver and args
self.visit_expr(receiver);
walk_list!(self, visit_expr, args);
}

Expand Down Expand Up @@ -1343,7 +1345,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);

Expand Down
Loading

0 comments on commit b44197a

Please sign in to comment.