Don't form a bound method when calling a C++ operator. (#7345)

Because we now support calling a function with a `self` parameter
directly, we can unconditionally call `operator$(lhs, rhs)` rather than
calling `lhs.operator$(rhs)` if the selected operator function happens
to be a member function.

This makes the logic a bit simpler and the SemIR a bit smaller.

We can't do the same for Carbon operators, unfortunately, as we use the
member access to trigger impl lookup.
This commit is contained in:
Richard Smith
2026-06-11 21:49:20 +00:00
committed by GitHub
parent e83422b375
commit c3fc59b8b9
7 changed files with 13 additions and 143 deletions
+12 -25
View File
@@ -70,8 +70,6 @@ auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
return SemIR::ErrorInst::InstId;
}
SemIR::InstId op_fn_id = SemIR::InstId::None;
// For unary operators with a C++ class as the operand, try to import and call
// the C++ operator.
// TODO: Change impl lookup instead. See
@@ -80,20 +78,16 @@ auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
llvm::any_of(op.interface_args_ref, [&](SemIR::InstId arg_id) {
return IsCppClassType(context, arg_id);
})) {
op_fn_id = LookupCppOperator(context, loc_id, op, {operand_id});
// If C++ operator lookup found a non-method operator, call it with one call
// argument. Otherwise fall through to call it with a self argument.
if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {
return PerformCall(context, loc_id, op_fn_id, {operand_id},
if (auto cpp_op_fn_id =
LookupCppOperator(context, loc_id, op, {operand_id});
cpp_op_fn_id.has_value()) {
return PerformCall(context, loc_id, cpp_op_fn_id, {operand_id},
/*is_desugared=*/true);
}
}
if (!op_fn_id.has_value()) {
// Look up the operator function.
op_fn_id = GetOperatorOpFunction(context, loc_id, op);
}
// Look up the operator function.
auto op_fn_id = GetOperatorOpFunction(context, loc_id, op);
// Form `operand.(Op)`.
auto bound_op_id =
@@ -118,8 +112,6 @@ auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
return SemIR::ErrorInst::InstId;
}
SemIR::InstId op_fn_id = SemIR::InstId::None;
// For binary operators with a C++ class as at least one of the operands, try
// to import and call the C++ operator.
// TODO: Instead of hooking this here, change impl lookup, so that a generic
@@ -132,21 +124,16 @@ auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
llvm::any_of(op.interface_args_ref, [&](SemIR::InstId arg_id) {
return IsCppClassType(context, arg_id);
})) {
op_fn_id = LookupCppOperator(context, loc_id, op, {lhs_id, rhs_id});
// If C++ operator lookup found a non-method operator, call it with two call
// arguments. Otherwise fall through to call it with a self argument and one
// call argument.
if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {
return PerformCall(context, loc_id, op_fn_id, {lhs_id, rhs_id},
if (auto cpp_op_fn_id =
LookupCppOperator(context, loc_id, op, {lhs_id, rhs_id});
cpp_op_fn_id.has_value()) {
return PerformCall(context, loc_id, cpp_op_fn_id, {lhs_id, rhs_id},
/*is_desugared=*/true);
}
}
if (!op_fn_id.has_value()) {
// Look up the operator function.
op_fn_id = GetOperatorOpFunction(context, loc_id, op);
}
// Look up the operator function.
auto op_fn_id = GetOperatorOpFunction(context, loc_id, op);
// Form `lhs.(Op)`.
auto bound_op_id =