diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa3889f47484..18ec45ee0de4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -180,7 +180,7 @@ repos: Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - --custom_format - - '\.(carbon|proto|ypp)$' + - '\.(carbon|proto|ypp)(\.tmpl)?$' - '' - '// ' - '' diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 776f03076431..262d4277522e 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -55,7 +55,6 @@ cc_library( "decl_name_stack.cpp", "eval.cpp", "import_ref.cpp", - "import_ref.h", "inst_block_stack.cpp", "modifiers.cpp", "return.cpp", @@ -66,6 +65,7 @@ cc_library( "decl_name_stack.h", "decl_state.h", "eval.h", + "import_ref.h", "inst_block_stack.h", "modifiers.h", "param_and_arg_refs_stack.h", @@ -101,12 +101,14 @@ cc_library( ]), hdrs = ["check.h"], deps = [ + ":call", ":context", ":function", ":impl", ":import", ":interface", ":member_access", + ":operator", ":pointer_dereference", "//common:check", "//common:ostream", @@ -138,6 +140,20 @@ cc_fuzz_test( ], ) +cc_library( + name = "call", + srcs = ["call.cpp"], + hdrs = ["call.h"], + deps = [ + ":context", + "//common:check", + "//toolchain/sem_ir:file", + "//toolchain/sem_ir:ids", + "//toolchain/sem_ir:inst", + "//toolchain/sem_ir:inst_kind", + ], +) + cc_library( name = "function", srcs = ["function.cpp"], @@ -213,6 +229,23 @@ cc_library( ], ) +cc_library( + name = "operator", + srcs = ["operator.cpp"], + hdrs = ["operator.h"], + deps = [ + ":call", + ":context", + ":member_access", + "//common:check", + "//toolchain/parse:node_kind", + "//toolchain/sem_ir:file", + "//toolchain/sem_ir:ids", + "//toolchain/sem_ir:inst", + "//toolchain/sem_ir:inst_kind", + ], +) + cc_library( name = "pointer_dereference", srcs = ["pointer_dereference.cpp"], diff --git a/toolchain/check/call.cpp b/toolchain/check/call.cpp new file mode 100644 index 000000000000..47f7e6a9bc75 --- /dev/null +++ b/toolchain/check/call.cpp @@ -0,0 +1,77 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/call.h" + +#include "toolchain/check/context.h" +#include "toolchain/check/convert.h" +#include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/typed_insts.h" + +namespace Carbon::Check { + +auto PerformCall(Context& context, Parse::NodeId node_id, + SemIR::InstId callee_id, llvm::ArrayRef arg_ids) + -> SemIR::InstId { + auto diagnose_not_callable = [&] { + auto callee_type_id = context.insts().Get(callee_id).type_id(); + if (callee_type_id != SemIR::TypeId::Error) { + CARBON_DIAGNOSTIC(CallToNonCallable, Error, + "Value of type `{0}` is not callable.", SemIR::TypeId); + context.emitter().Emit(node_id, CallToNonCallable, callee_type_id); + } + return SemIR::InstId::BuiltinError; + }; + + // For a method call, pick out the `self` value. + auto function_callee_id = callee_id; + SemIR::InstId self_id = SemIR::InstId::Invalid; + if (auto bound_method = + context.insts().Get(callee_id).TryAs()) { + self_id = bound_method->object_id; + function_callee_id = bound_method->function_id; + } + + // Identify the function we're calling. + auto function_decl_id = context.constant_values().Get(function_callee_id); + if (!function_decl_id.is_constant()) { + return diagnose_not_callable(); + } + auto function_decl = context.insts() + .Get(function_decl_id.inst_id()) + .TryAs(); + if (!function_decl) { + return diagnose_not_callable(); + } + auto function_id = function_decl->function_id; + const auto& callable = context.functions().Get(function_id); + + // For functions with an implicit return type, the return type is the empty + // tuple type. + SemIR::TypeId type_id = callable.return_type_id; + if (!type_id.is_valid()) { + type_id = context.GetTupleType({}); + } + + // If there is a return slot, build storage for the result. + SemIR::InstId return_storage_id = SemIR::InstId::Invalid; + if (callable.return_slot_id.is_valid()) { + // Tentatively put storage for a temporary in the function's return slot. + // This will be replaced if necessary when we perform initialization. + return_storage_id = context.AddInst( + {node_id, SemIR::TemporaryStorage{callable.return_type_id}}); + } + + // Convert the arguments to match the parameters. + auto converted_args_id = + ConvertCallArgs(context, node_id, self_id, arg_ids, return_storage_id, + function_decl_id.inst_id(), + callable.implicit_param_refs_id, callable.param_refs_id); + auto call_inst_id = context.AddInst( + {node_id, SemIR::Call{type_id, callee_id, converted_args_id}}); + + return call_inst_id; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/call.h b/toolchain/check/call.h new file mode 100644 index 000000000000..ad0a2ea279bc --- /dev/null +++ b/toolchain/check/call.h @@ -0,0 +1,20 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_CALL_H_ +#define CARBON_TOOLCHAIN_CHECK_CALL_H_ + +#include "toolchain/check/context.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +// Checks and builds SemIR for a call to `callee_id` with arguments `args_id`. +auto PerformCall(Context& context, Parse::NodeId node_id, + SemIR::InstId callee_id, llvm::ArrayRef arg_ids) + -> SemIR::InstId; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_CALL_H_ diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 7b1e9366303a..39036f6d3a4f 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -164,7 +164,7 @@ static auto RebuildAndValidateIfFieldsAreConstant( if ((ReplaceFieldWithConstantValue(context, &typed_inst, each_field_id, &phase) && ...)) { - if (!validate_fn(typed_inst)) { + if (phase == Phase::UnknownDueToError || !validate_fn(typed_inst)) { return SemIR::ConstantId::Error; } return MakeConstantResult(context, typed_inst, phase); diff --git a/toolchain/check/handle_call_expr.cpp b/toolchain/check/handle_call_expr.cpp index 32aa8212fd8b..913a06522e53 100644 --- a/toolchain/check/handle_call_expr.cpp +++ b/toolchain/check/handle_call_expr.cpp @@ -2,9 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include "llvm/ADT/ScopeExit.h" +#include "toolchain/check/call.h" #include "toolchain/check/context.h" -#include "toolchain/check/convert.h" #include "toolchain/sem_ir/inst.h" namespace Carbon::Check { @@ -27,74 +26,15 @@ auto HandleCallExpr(Context& context, Parse::CallExprId node_id) -> bool { // Process the final explicit call argument now, but leave the arguments // block on the stack until the end of this function. context.param_and_arg_refs_stack().EndNoPop(Parse::NodeKind::CallExprStart); - auto discard_args_block = llvm::make_scope_exit( - [&] { context.param_and_arg_refs_stack().PopAndDiscard(); }); - auto [call_expr_node_id, callee_id] = context.node_stack().PopWithNodeId(); - auto diagnose_not_callable = [&, call_expr_node_id = call_expr_node_id, - callee_id = callee_id] { - auto callee_type_id = context.insts().Get(callee_id).type_id(); - if (callee_type_id != SemIR::TypeId::Error) { - CARBON_DIAGNOSTIC(CallToNonCallable, Error, - "Value of type `{0}` is not callable.", SemIR::TypeId); - context.emitter().Emit(call_expr_node_id, CallToNonCallable, - callee_type_id); - } - context.node_stack().Push(node_id, SemIR::InstId::BuiltinError); - return true; - }; + auto call_id = PerformCall( + context, call_expr_node_id, callee_id, + context.param_and_arg_refs_stack().PeekCurrentBlockContents()); - // For a method call, pick out the `self` value. - auto function_callee_id = callee_id; - SemIR::InstId self_id = SemIR::InstId::Invalid; - if (auto bound_method = - context.insts().Get(callee_id).TryAs()) { - self_id = bound_method->object_id; - function_callee_id = bound_method->function_id; - } - - // Identify the function we're calling. - auto function_decl_id = context.constant_values().Get(function_callee_id); - if (!function_decl_id.is_constant()) { - return diagnose_not_callable(); - } - auto function_decl = context.insts() - .Get(function_decl_id.inst_id()) - .TryAs(); - if (!function_decl) { - return diagnose_not_callable(); - } - auto function_id = function_decl->function_id; - const auto& callable = context.functions().Get(function_id); - - // For functions with an implicit return type, the return type is the empty - // tuple type. - SemIR::TypeId type_id = callable.return_type_id; - if (!type_id.is_valid()) { - type_id = context.GetTupleType({}); - } - - // If there is a return slot, build storage for the result. - SemIR::InstId return_storage_id = SemIR::InstId::Invalid; - if (callable.return_slot_id.is_valid()) { - // Tentatively put storage for a temporary in the function's return slot. - // This will be replaced if necessary when we perform initialization. - return_storage_id = context.AddInst( - {call_expr_node_id, SemIR::TemporaryStorage{callable.return_type_id}}); - } - - // Convert the arguments to match the parameters. - auto converted_args_id = ConvertCallArgs( - context, call_expr_node_id, self_id, - context.param_and_arg_refs_stack().PeekCurrentBlockContents(), - return_storage_id, function_decl_id.inst_id(), - callable.implicit_param_refs_id, callable.param_refs_id); - auto call_inst_id = context.AddInst( - {call_expr_node_id, SemIR::Call{type_id, callee_id, converted_args_id}}); - - context.node_stack().Push(node_id, call_inst_id); + context.param_and_arg_refs_stack().PopAndDiscard(); + context.node_stack().Push(node_id, call_id); return true; } diff --git a/toolchain/check/handle_operator.cpp b/toolchain/check/handle_operator.cpp index 41435943243c..78b4aa10e3ee 100644 --- a/toolchain/check/handle_operator.cpp +++ b/toolchain/check/handle_operator.cpp @@ -4,20 +4,48 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" +#include "toolchain/check/operator.h" #include "toolchain/check/pointer_dereference.h" #include "toolchain/diagnostics/diagnostic_emitter.h" namespace Carbon::Check { +// Common logic for unary operator handlers. +static auto HandleUnaryOperator(Context& context, Parse::NodeId node_id, + Operator op) -> bool { + // TODO: Support implicit conversion from specific node IDs to node ID + // categories and change this function to take an `AnyExprId` directly. + auto expr_node_id = static_cast(node_id); + auto operand_id = context.node_stack().PopExpr(); + auto result_id = BuildUnaryOperator(context, expr_node_id, op, operand_id); + context.node_stack().Push(expr_node_id, result_id); + return true; +} + +// Common logic for binary operator handlers. +static auto HandleBinaryOperator(Context& context, Parse::NodeId node_id, + Operator op) -> bool { + // TODO: Support implicit conversion from specific node IDs to node ID + // categories and change this function to take an `AnyExprId` directly. + auto expr_node_id = static_cast(node_id); + auto rhs_id = context.node_stack().PopExpr(); + auto lhs_id = context.node_stack().PopExpr(); + auto result_id = + BuildBinaryOperator(context, expr_node_id, op, lhs_id, rhs_id); + context.node_stack().Push(expr_node_id, result_id); + return true; +} + auto HandleInfixOperatorAmp(Context& context, Parse::InfixOperatorAmpId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorAmp"); + // TODO: Facet type intersection may need to be handled directly. + return HandleBinaryOperator(context, node_id, {"BitAnd"}); } auto HandleInfixOperatorAmpEqual(Context& context, Parse::InfixOperatorAmpEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorAmpEqual"); + return HandleBinaryOperator(context, node_id, {"BitAndAssign"}); } auto HandleInfixOperatorAs(Context& context, Parse::InfixOperatorAsId node_id) @@ -33,21 +61,24 @@ auto HandleInfixOperatorAs(Context& context, Parse::InfixOperatorAsId node_id) auto HandleInfixOperatorCaret(Context& context, Parse::InfixOperatorCaretId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorCaret"); + return HandleBinaryOperator(context, node_id, {"BitXor"}); } auto HandleInfixOperatorCaretEqual(Context& context, Parse::InfixOperatorCaretEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorCaretEqual"); + return HandleBinaryOperator(context, node_id, {"BitXorAssign"}); } auto HandleInfixOperatorEqual(Context& context, Parse::InfixOperatorEqualId node_id) -> bool { + // TODO: Switch to using assignment interface for most assignment. Some cases + // may need to be handled directly. + // + // return HandleBinaryOperator(context, node_id, {"Assign"}); + auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId(); auto [lhs_node, lhs_id] = context.node_stack().PopExprWithNodeId(); - - // TODO: handle complex assignment expression such as `a += 1`. if (auto lhs_cat = SemIR::GetExprCategory(context.sem_ir(), lhs_id); lhs_cat != SemIR::ExprCategory::DurableRef && lhs_cat != SemIR::ExprCategory::Error) { @@ -70,128 +101,130 @@ auto HandleInfixOperatorEqual(Context& context, auto HandleInfixOperatorEqualEqual(Context& context, Parse::InfixOperatorEqualEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorEqualEqual"); + return HandleBinaryOperator(context, node_id, {"Eq", "Equal"}); } auto HandleInfixOperatorExclaimEqual(Context& context, Parse::InfixOperatorExclaimEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorExclaimEqual"); + return HandleBinaryOperator(context, node_id, {"Eq", "NotEqual"}); } auto HandleInfixOperatorGreater(Context& context, Parse::InfixOperatorGreaterId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorGreater"); + return HandleBinaryOperator(context, node_id, {"Ordered", "Greater"}); } auto HandleInfixOperatorGreaterEqual(Context& context, Parse::InfixOperatorGreaterEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorGreaterEqual"); + return HandleBinaryOperator(context, node_id, + {"Ordered", "GreaterOrEquivalent"}); } auto HandleInfixOperatorGreaterGreater( Context& context, Parse::InfixOperatorGreaterGreaterId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorGreaterGreater"); + return HandleBinaryOperator(context, node_id, {"RightShift"}); } auto HandleInfixOperatorGreaterGreaterEqual( Context& context, Parse::InfixOperatorGreaterGreaterEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorGreaterGreaterEqual"); + return HandleBinaryOperator(context, node_id, {"RightShiftAssign"}); } auto HandleInfixOperatorLess(Context& context, Parse::InfixOperatorLessId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorLess"); + return HandleBinaryOperator(context, node_id, {"Ordered", "Less"}); } auto HandleInfixOperatorLessEqual(Context& context, Parse::InfixOperatorLessEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorLessEqual"); + return HandleBinaryOperator(context, node_id, + {"Ordered", "LessOrEquivalent"}); } auto HandleInfixOperatorLessEqualGreater( Context& context, Parse::InfixOperatorLessEqualGreaterId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorLessEqualGreater"); + return context.TODO(node_id, "remove <=> operator that is not in the design"); } auto HandleInfixOperatorLessLess(Context& context, Parse::InfixOperatorLessLessId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorLessLess"); + return HandleBinaryOperator(context, node_id, {"LeftShift"}); } auto HandleInfixOperatorLessLessEqual( Context& context, Parse::InfixOperatorLessLessEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorLessLessEqual"); + return HandleBinaryOperator(context, node_id, {"LeftShiftAssign"}); } auto HandleInfixOperatorMinus(Context& context, Parse::InfixOperatorMinusId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorMinus"); + return HandleBinaryOperator(context, node_id, {"Sub"}); } auto HandleInfixOperatorMinusEqual(Context& context, Parse::InfixOperatorMinusEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorMinusEqual"); + return HandleBinaryOperator(context, node_id, {"SubAssign"}); } auto HandleInfixOperatorPercent(Context& context, Parse::InfixOperatorPercentId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPercent"); + return HandleBinaryOperator(context, node_id, {"Mod"}); } auto HandleInfixOperatorPercentEqual(Context& context, Parse::InfixOperatorPercentEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPercentEqual"); + return HandleBinaryOperator(context, node_id, {"ModAssign"}); } auto HandleInfixOperatorPipe(Context& context, Parse::InfixOperatorPipeId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPipe"); + return HandleBinaryOperator(context, node_id, {"BitOr"}); } auto HandleInfixOperatorPipeEqual(Context& context, Parse::InfixOperatorPipeEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPipeEqual"); + return HandleBinaryOperator(context, node_id, {"BitOrAssign"}); } auto HandleInfixOperatorPlus(Context& context, Parse::InfixOperatorPlusId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPlus"); + return HandleBinaryOperator(context, node_id, {"Add"}); } auto HandleInfixOperatorPlusEqual(Context& context, Parse::InfixOperatorPlusEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorPlusEqual"); + return HandleBinaryOperator(context, node_id, {"AddAssign"}); } auto HandleInfixOperatorSlash(Context& context, Parse::InfixOperatorSlashId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorSlash"); + return HandleBinaryOperator(context, node_id, {"Div"}); } auto HandleInfixOperatorSlashEqual(Context& context, Parse::InfixOperatorSlashEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorSlashEqual"); + return HandleBinaryOperator(context, node_id, {"DivAssign"}); } auto HandleInfixOperatorStar(Context& context, Parse::InfixOperatorStarId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorStar"); + return HandleBinaryOperator(context, node_id, {"Mul"}); } auto HandleInfixOperatorStarEqual(Context& context, Parse::InfixOperatorStarEqualId node_id) -> bool { - return context.TODO(node_id, "HandleInfixOperatorStarEqual"); + return HandleBinaryOperator(context, node_id, {"MulAssign"}); } auto HandlePostfixOperatorStar(Context& context, @@ -232,7 +265,7 @@ auto HandlePrefixOperatorAmp(Context& context, auto HandlePrefixOperatorCaret(Context& context, Parse::PrefixOperatorCaretId node_id) -> bool { - return context.TODO(node_id, "HandlePrefixOperatorCaret"); + return HandleUnaryOperator(context, node_id, {"BitComplement"}); } auto HandlePrefixOperatorConst(Context& context, @@ -256,13 +289,13 @@ auto HandlePrefixOperatorConst(Context& context, auto HandlePrefixOperatorMinus(Context& context, Parse::PrefixOperatorMinusId node_id) -> bool { - return context.TODO(node_id, "HandlePrefixOperatorMinus"); + return HandleUnaryOperator(context, node_id, {"Negate"}); } auto HandlePrefixOperatorMinusMinus(Context& context, Parse::PrefixOperatorMinusMinusId node_id) -> bool { - return context.TODO(node_id, "HandlePrefixOperatorMinusMinus"); + return HandleUnaryOperator(context, node_id, {"Dec"}); } auto HandlePrefixOperatorNot(Context& context, @@ -278,7 +311,7 @@ auto HandlePrefixOperatorNot(Context& context, auto HandlePrefixOperatorPlusPlus(Context& context, Parse::PrefixOperatorPlusPlusId node_id) -> bool { - return context.TODO(node_id, "HandlePrefixOperatorPlusPlus"); + return HandleUnaryOperator(context, node_id, {"Inc"}); } auto HandlePrefixOperatorStar(Context& context, diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 94a4e1aa6675..ae3d06caff24 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/function.h" +#include "toolchain/check/import_ref.h" #include "toolchain/check/subst.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/sem_ir/ids.h" @@ -86,7 +87,10 @@ static auto BuildInterfaceWitness( .replacement_id = context.types().GetConstantId(impl.self_id)}}; for (auto decl_id : assoc_entities) { - auto decl = context.insts().Get(decl_id); + TryResolveImportRefUnused(context, decl_id); + auto const_id = context.constant_values().Get(decl_id); + CARBON_CHECK(const_id.is_constant()) << "Non-constant associated entity"; + auto decl = context.insts().Get(const_id.inst_id()); if (auto fn_decl = decl.TryAs()) { auto& fn = context.functions().Get(fn_decl->function_id); auto impl_decl_id = diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 798837223c20..767e4a380f35 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -23,17 +23,19 @@ namespace Carbon::Check { // Work items on work_stack_. At a high level, the loop is: // // 1. If Work has received a constant, it's considered resolved. -// - If made_incomplete_type, resolve unconditionally. +// - If made_forward_decl, resolve unconditionally. // - The constant check avoids performance costs of deduplication on add. // 2. Resolve the instruction: (TryResolveInst/TryResolveTypedInst) // - For most cases: -// A. For types which _can_ be incomplete, when not made_incomplete_type: -// i. Start by making an incomplete type to address circular references. -// ii. If the imported type is incomplete, return the constant. -// iii. Otherwise, set made_incomplete_type and continue resolving. -// - Creating an incomplete type will have set the constant, which -// influences step (1); setting made_incomplete_type gets us a second -// resolve pass when needed. +// A. For types which _can_ be forward declared, when not +// made_forward_decl: +// i. Start by making a forward declared type to address circular +// references. +// ii. If the imported type is not defined, return the constant. +// iii. Otherwise, set made_forward_decl and continue resolving. +// - Creating a forward declaration of the type will have set the +// constant, which influences step (1); setting made_forward_decl +// gets us a second resolve pass when needed. // B. Gather all input constants. // - Gathering constants directly adds unresolved values to work_stack_. // C. If any need to be resolved (HasNewWork), return Invalid; this @@ -72,11 +74,11 @@ class ImportRefResolver { // This should typically be checked before adding it, but a given // instruction may be added multiple times before its constant is // evaluated. - if (!work.made_incomplete_type && + if (!work.made_forward_decl && import_ir_constant_values_.Get(work.inst_id).is_valid()) { work_stack_.pop_back(); } else if (auto new_const_id = - TryResolveInst(work.inst_id, work.made_incomplete_type); + TryResolveInst(work.inst_id, work.made_forward_decl); new_const_id.is_valid()) { import_ir_constant_values_.Set(work.inst_id, new_const_id); work_stack_.pop_back(); @@ -110,8 +112,8 @@ class ImportRefResolver { // The instruction to work on. SemIR::InstId inst_id; - // True if a first pass made an incomplete type. - bool made_incomplete_type = false; + // True if a first pass made a forward declaration. + bool made_forward_decl = false; }; // For imported entities, we use an invalid enclosing scope. This will be okay @@ -161,6 +163,15 @@ class ImportRefResolver { for (auto inst_id : param_refs) { const_ids.push_back( GetLocalConstantId(import_ir_.insts().Get(inst_id).type_id())); + + // If the parameter is a symbolic binding, build the BindSymbolicName + // constant. + auto bind_id = inst_id; + if (auto addr = + import_ir_.insts().TryGetAs(bind_id)) { + bind_id = addr->inner_id; + } + GetLocalConstantId(bind_id); } return const_ids; } @@ -182,8 +193,10 @@ class ImportRefResolver { // TODO: Consider a different parameter handling to simplify import logic. auto inst = import_ir_.insts().Get(ref_id); auto addr_inst = inst.TryAs(); + auto bind_id = ref_id; if (addr_inst) { - inst = import_ir_.insts().Get(addr_inst->inner_id); + bind_id = addr_inst->inner_id; + inst = import_ir_.insts().Get(bind_id); } auto bind_inst = inst.TryAs(); if (bind_inst) { @@ -198,23 +211,32 @@ class ImportRefResolver { auto new_param_id = context_.AddInstInNoBlock( {Parse::NodeId::Invalid, SemIR::Param{type_id, name_id}}); if (bind_inst) { - auto bind_name_id = context_.bind_names().Add( - {.name_id = name_id, - .enclosing_scope_id = SemIR::NameScopeId::Invalid}); switch (bind_inst->kind) { - case SemIR::InstKind::BindName: + case SemIR::InstKind::BindName: { + auto bind_name_id = context_.bind_names().Add( + {.name_id = name_id, + .enclosing_scope_id = SemIR::NameScopeId::Invalid}); new_param_id = context_.AddInstInNoBlock( {Parse::NodeId::Invalid, SemIR::BindName{type_id, bind_name_id, new_param_id}}); break; - case SemIR::InstKind::BindSymbolicName: - new_param_id = context_.AddInstInNoBlock( - {Parse::NodeId::Invalid, - SemIR::BindSymbolicName{type_id, bind_name_id, new_param_id}}); + } + case SemIR::InstKind::BindSymbolicName: { + // The symbolic name will be created on first reference, so might + // already exist. Update the value in it to refer to the parameter. + auto new_bind_inst = + context_.insts().GetAs( + GetLocalConstantId(bind_id).inst_id()); + new_bind_inst.value_id = new_param_id; + // This is not before constant use, but doesn't change the + // constant value of the instruction. + context_.ReplaceInstBeforeConstantUse( + bind_id, {Parse::NodeId::Invalid, new_bind_inst}); break; - - default: + } + default: { CARBON_FATAL() << "Unexpected kind: " << bind_inst->kind; + } } } if (addr_inst) { @@ -272,23 +294,30 @@ class ImportRefResolver { // following TryResolveTypedInst helper functions. // // TODO: Error is returned when support is missing, but that should go away. - auto TryResolveInst(SemIR::InstId inst_id, bool made_incomplete_type) + auto TryResolveInst(SemIR::InstId inst_id, bool made_forward_decl) -> SemIR::ConstantId { if (inst_id.is_builtin()) { - CARBON_CHECK(!made_incomplete_type); + CARBON_CHECK(!made_forward_decl); // Constants for builtins can be directly copied. return context_.constant_values().Get(inst_id); } auto inst = import_ir_.insts().Get(inst_id); - CARBON_CHECK(!made_incomplete_type || - inst.kind() == SemIR::InstKind::ClassDecl) - << "Currently only decls with incomplete types should need " - "made_incomplete_type states: " + CARBON_CHECK(!made_forward_decl || + inst.kind() == SemIR::InstKind::ClassDecl || + inst.kind() == SemIR::InstKind::InterfaceDecl) + << "Only types that can be involved in cycles should need " + "made_forward_decl state: " << inst.kind(); switch (inst.kind()) { + case SemIR::InstKind::AssociatedEntity: + return TryResolveTypedInst(inst.As()); + + case SemIR::InstKind::AssociatedEntityType: + return TryResolveTypedInst(inst.As()); + case SemIR::InstKind::BaseDecl: return TryResolveTypedInst(inst.As()); @@ -297,7 +326,7 @@ class ImportRefResolver { case SemIR::InstKind::ClassDecl: return TryResolveTypedInst(inst.As(), inst_id, - made_incomplete_type); + made_forward_decl); case SemIR::InstKind::ClassType: return TryResolveTypedInst(inst.As()); @@ -312,7 +341,8 @@ class ImportRefResolver { return TryResolveTypedInst(inst.As()); case SemIR::InstKind::InterfaceDecl: - return TryResolveTypedInst(inst.As()); + return TryResolveTypedInst(inst.As(), inst_id, + made_forward_decl); case SemIR::InstKind::InterfaceType: return TryResolveTypedInst(inst.As()); @@ -334,12 +364,7 @@ class ImportRefResolver { return TryEvalInst(context_, inst_id, inst); case SemIR::InstKind::BindSymbolicName: - // TODO: This will return a `ConstantId` referring to the `inst_id` from - // the import IR. But we need all references to the same - // `BindSymbolicName` in the imported IR to resolve to the same constant - // value in the local IR, so we can't just create a new local - // `BindSymbolicName` here. - return TryEvalInst(context_, inst_id, inst); + return TryResolveTypedInst(inst.As()); default: context_.TODO( @@ -349,6 +374,46 @@ class ImportRefResolver { } } + auto TryResolveTypedInst(SemIR::AssociatedEntity inst) -> SemIR::ConstantId { + auto initial_work = work_stack_.size(); + auto type_const_id = GetLocalConstantId(inst.type_id); + if (HasNewWork(initial_work)) { + return SemIR::ConstantId::Invalid; + } + + // Add a lazy reference to the target declaration. + auto decl_id = context_.AddPlaceholderInst( + SemIR::ImportRefUnused{import_ir_id_, inst.decl_id}); + + auto inst_id = context_.AddInstInNoBlock( + {Parse::NodeId::Invalid, + SemIR::AssociatedEntity{ + context_.GetTypeIdForTypeConstant(type_const_id), inst.index, + decl_id}}); + return context_.constant_values().Get(inst_id); + } + + auto TryResolveTypedInst(SemIR::AssociatedEntityType inst) + -> SemIR::ConstantId { + CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); + + auto initial_work = work_stack_.size(); + auto entity_type_const_id = GetLocalConstantId(inst.entity_type_id); + auto interface_const_id = GetLocalConstantId( + import_ir_.interfaces().Get(inst.interface_id).decl_id); + if (HasNewWork(initial_work)) { + return SemIR::ConstantId::Invalid; + } + + auto inst_id = context_.AddInstInNoBlock(SemIR::AssociatedEntityType{ + SemIR::TypeId::TypeType, + context_.insts() + .GetAs(interface_const_id.inst_id()) + .interface_id, + context_.GetTypeIdForTypeConstant(entity_type_const_id)}); + return context_.constant_values().Get(inst_id); + } + auto TryResolveTypedInst(SemIR::BaseDecl inst) -> SemIR::ConstantId { auto initial_work = work_stack_.size(); auto type_const_id = GetLocalConstantId(inst.type_id); @@ -375,6 +440,25 @@ class ImportRefResolver { return value_id; } + auto TryResolveTypedInst(SemIR::BindSymbolicName inst) -> SemIR::ConstantId { + auto initial_work = work_stack_.size(); + auto type_id = GetLocalConstantId(inst.type_id); + if (HasNewWork(initial_work)) { + return SemIR::ConstantId::Invalid; + } + + auto name_id = + GetLocalNameId(import_ir_.bind_names().Get(inst.bind_name_id).name_id); + auto bind_name_id = context_.bind_names().Add( + {.name_id = name_id, + .enclosing_scope_id = SemIR::NameScopeId::Invalid}); + auto new_bind_id = context_.AddInstInNoBlock( + {Parse::NodeId::Invalid, + SemIR::BindSymbolicName{context_.GetTypeIdForTypeConstant(type_id), + bind_name_id, SemIR::InstId::Invalid}}); + return context_.constant_values().Get(new_bind_id); + } + // Makes an incomplete class. This is necessary even with classes with a // complete declaration, because things such as `Self` may refer back to the // type. @@ -452,13 +536,13 @@ class ImportRefResolver { } auto TryResolveTypedInst(SemIR::ClassDecl inst, SemIR::InstId inst_id, - bool made_incomplete_type) -> SemIR::ConstantId { + bool made_forward_decl) -> SemIR::ConstantId { const auto& import_class = import_ir_.classes().Get(inst.class_id); SemIR::ConstantId class_const_id = SemIR::ConstantId::Invalid; // On the first pass, there's no incomplete type; start by adding one for // any recursive references. - if (!made_incomplete_type) { + if (!made_forward_decl) { class_const_id = MakeIncompleteClass(inst_id, import_class); // If there's only a forward declaration, we're done. if (!import_class.is_defined()) { @@ -467,7 +551,7 @@ class ImportRefResolver { // This may not be needed because all constants might be ready, but we do // it here so that we don't need to track which work item corresponds to // this instruction. - work_stack_.back().made_incomplete_type = true; + work_stack_.back().made_forward_decl = true; } CARBON_CHECK(import_class.is_defined()) @@ -488,7 +572,7 @@ class ImportRefResolver { // On the first pass, we build the incomplete type's constant above. If we // get here on a subsequent pass we need to fetch the one we built in the // first pass. - if (made_incomplete_type) { + if (made_forward_decl) { CARBON_CHECK(!class_const_id.is_valid()) << "Shouldn't have a const yet when resuming"; class_const_id = import_ir_constant_values_.Get(inst_id); @@ -588,10 +672,11 @@ class ImportRefResolver { return context_.constant_values().Get(function_decl_id); } - auto TryResolveTypedInst(SemIR::InterfaceDecl inst) -> SemIR::ConstantId { - const auto& import_interface = - import_ir_.interfaces().Get(inst.interface_id); - + // Make a declaration of an interface. This is done as a separate step from + // importing the interface definition in order to resolve cycles. + auto MakeInterfaceDecl(SemIR::InstId inst_id, + const SemIR::Interface& import_interface) + -> SemIR::ConstantId { auto interface_decl = SemIR::InterfaceDecl{SemIR::TypeId::Invalid, SemIR::InterfaceId::Invalid, SemIR::InstBlockId::Empty}; @@ -605,34 +690,73 @@ class ImportRefResolver { .decl_id = interface_decl_id, }; - // If the interface is defined, we can complete it immediately. No constants - // are required. Do this before adding it to interfaces. - if (import_interface.is_defined()) { - new_interface.scope_id = context_.name_scopes().Add( - new_interface.decl_id, SemIR::NameId::Invalid, - new_interface.enclosing_scope_id); - auto& new_scope = context_.name_scopes().Get(new_interface.scope_id); - const auto& import_scope = - import_ir_.name_scopes().Get(import_interface.scope_id); - - // Push a block so that we can add scoped instructions to it. - context_.inst_block_stack().Push(); - AddNameScopeImportRefs(import_scope, new_scope); - new_interface.associated_entities_id = - AddAssociatedEntities(import_interface.associated_entities_id); - new_interface.body_block_id = context_.inst_block_stack().Pop(); - // TODO: Import new_interface.self_param_id. - - CARBON_CHECK(import_scope.extended_scopes.empty()) - << "Interfaces don't currently have extended scopes to support."; - } - // Write the interface ID into the InterfaceDecl. interface_decl.interface_id = context_.interfaces().Add(new_interface); context_.ReplaceInstBeforeConstantUse( interface_decl_id, {Parse::NodeId::Invalid, interface_decl}); - return context_.constant_values().Get(interface_decl_id); + // Set the constant value for the imported interface. + auto interface_const_id = context_.constant_values().Get(interface_decl_id); + import_ir_constant_values_.Set(inst_id, interface_const_id); + return interface_const_id; + } + + // Imports the definition for an interface that has been imported as a forward + // declaration. + auto AddInterfaceDefinition(const SemIR::Interface& import_interface, + SemIR::ConstantId interface_const_id, + SemIR::ConstantId self_param_id) -> void { + auto& new_interface = context_.interfaces().Get( + context_.insts() + .GetAs(interface_const_id.inst_id()) + .interface_id); + new_interface.scope_id = context_.name_scopes().Add( + new_interface.decl_id, SemIR::NameId::Invalid, + new_interface.enclosing_scope_id); + auto& new_scope = context_.name_scopes().Get(new_interface.scope_id); + const auto& import_scope = + import_ir_.name_scopes().Get(import_interface.scope_id); + + // Push a block so that we can add scoped instructions to it. + context_.inst_block_stack().Push(); + AddNameScopeImportRefs(import_scope, new_scope); + new_interface.associated_entities_id = + AddAssociatedEntities(import_interface.associated_entities_id); + new_interface.body_block_id = context_.inst_block_stack().Pop(); + new_interface.self_param_id = self_param_id.inst_id(); + + CARBON_CHECK(import_scope.extended_scopes.empty()) + << "Interfaces don't currently have extended scopes to support."; + } + + auto TryResolveTypedInst(SemIR::InterfaceDecl inst, SemIR::InstId inst_id, + bool made_forward_decl) -> SemIR::ConstantId { + const auto& import_interface = + import_ir_.interfaces().Get(inst.interface_id); + + // On the first pass, create a forward declaration of the interface. + if (!made_forward_decl) { + auto interface_const_id = MakeInterfaceDecl(inst_id, import_interface); + if (!import_interface.is_defined()) { + return interface_const_id; + } + // Track that we need another pass. We always will, because the type of + // the `Self` binding refers to the interface. + work_stack_.back().made_forward_decl = true; + } + + auto initial_work = work_stack_.size(); + auto self_param_id = GetLocalConstantId(import_interface.self_param_id); + if (HasNewWork(initial_work)) { + return SemIR::ConstantId::Invalid; + } + + // Add the interface definition. + CARBON_CHECK(import_interface.is_defined()) + << "Should not need second pass for undefined interface."; + auto interface_const_id = import_ir_constant_values_.Get(inst_id); + AddInterfaceDefinition(import_interface, interface_const_id, self_param_id); + return interface_const_id; } auto TryResolveTypedInst(SemIR::InterfaceType inst) -> SemIR::ConstantId { diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 57e3c321fc0b..172ba06f0a2f 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -149,7 +149,8 @@ static auto LookupInterfaceWitness(Context& context, // Performs impl lookup for a member name expression. This finds the relevant // impl witness and extracts the corresponding impl member. -static auto PerformImplLookup(Context& context, SemIR::ConstantId type_const_id, +static auto PerformImplLookup(Context& context, Parse::NodeId node_id, + SemIR::ConstantId type_const_id, SemIR::AssociatedEntityType assoc_type, SemIR::InstId member_id) -> SemIR::InstId { auto& interface = context.interfaces().Get(assoc_type.interface_id); @@ -161,7 +162,7 @@ static auto PerformImplLookup(Context& context, SemIR::ConstantId type_const_id, "that does not implement that interface.", SemIR::NameId, std::string); context.emitter().Emit( - member_id, MissingImplInMemberAccess, interface.name_id, + node_id, MissingImplInMemberAccess, interface.name_id, context.sem_ir().StringifyTypeExpr(type_const_id.inst_id())); return SemIR::InstId::BuiltinError; } @@ -194,8 +195,7 @@ static auto PerformImplLookup(Context& context, SemIR::ConstantId type_const_id, // Performs a member name lookup into the specified scope, including performing // impl lookup if necessary. If the scope is invalid, assume an error has // already been diagnosed, and return BuiltinError. -static auto LookupMemberNameInScope(Context& context, - Parse::AnyMemberAccessExprId node_id, +static auto LookupMemberNameInScope(Context& context, Parse::NodeId node_id, SemIR::InstId /*base_id*/, SemIR::NameId name_id, SemIR::ConstantId name_scope_const_id, @@ -219,8 +219,8 @@ static auto LookupMemberNameInScope(Context& context, if (auto assoc_type = context.types().TryGetAs( inst.type_id())) { if (ScopeNeedsImplLookup(context, name_scope_id)) { - member_id = PerformImplLookup(context, name_scope_const_id, *assoc_type, - member_id); + member_id = PerformImplLookup(context, node_id, name_scope_const_id, + *assoc_type, member_id); } } @@ -230,8 +230,7 @@ static auto LookupMemberNameInScope(Context& context, // Performs the instance binding step in member access. If the found member is a // field, forms a class member access. If the found member is an instance // method, forms a bound method. Otherwise, the member is returned unchanged. -static auto PerformInstanceBinding(Context& context, - Parse::AnyMemberAccessExprId node_id, +static auto PerformInstanceBinding(Context& context, Parse::NodeId node_id, SemIR::InstId base_id, SemIR::InstId member_id) -> SemIR::InstId { auto member_type_id = context.insts().Get(member_id).type_id(); @@ -295,7 +294,7 @@ static auto PerformInstanceBinding(Context& context, return member_id; } -auto PerformMemberAccess(Context& context, Parse::AnyMemberAccessExprId node_id, +auto PerformMemberAccess(Context& context, Parse::NodeId node_id, SemIR::InstId base_id, SemIR::NameId name_id) -> SemIR::InstId { // If the base is a name scope, such as a class or namespace, perform lookup @@ -370,8 +369,7 @@ auto PerformMemberAccess(Context& context, Parse::AnyMemberAccessExprId node_id, return member_id; } -auto PerformCompoundMemberAccess(Context& context, - Parse::AnyMemberAccessExprId node_id, +auto PerformCompoundMemberAccess(Context& context, Parse::NodeId node_id, SemIR::InstId base_id, SemIR::InstId member_expr_id) -> SemIR::InstId { @@ -387,8 +385,8 @@ auto PerformCompoundMemberAccess(Context& context, // performed using the type of the base expression. if (auto assoc_type = context.types().TryGetAs( member.type_id())) { - member_id = - PerformImplLookup(context, base_type_const_id, *assoc_type, member_id); + member_id = PerformImplLookup(context, node_id, base_type_const_id, + *assoc_type, member_id); } // Perform instance binding if we found an instance member. diff --git a/toolchain/check/member_access.h b/toolchain/check/member_access.h index f1f3594c92ab..562d3c3a14b8 100644 --- a/toolchain/check/member_access.h +++ b/toolchain/check/member_access.h @@ -12,15 +12,14 @@ namespace Carbon::Check { // Creates SemIR to perform a member access with base expression `base_id` and // member name `name_id`. Returns the result of the access. -auto PerformMemberAccess(Context& context, Parse::AnyMemberAccessExprId node_id, +auto PerformMemberAccess(Context& context, Parse::NodeId node_id, SemIR::InstId base_id, SemIR::NameId name_id) -> SemIR::InstId; // Creates SemIR to perform a compound member access with base expression // `base_id` and member name expression `member_expr_id`. Returns the result of // the access. -auto PerformCompoundMemberAccess(Context& context, - Parse::AnyMemberAccessExprId node_id, +auto PerformCompoundMemberAccess(Context& context, Parse::NodeId node_id, SemIR::InstId base_id, SemIR::InstId member_expr_id) -> SemIR::InstId; diff --git a/toolchain/check/operator.cpp b/toolchain/check/operator.cpp new file mode 100644 index 000000000000..291fef60b9b7 --- /dev/null +++ b/toolchain/check/operator.cpp @@ -0,0 +1,148 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/operator.h" + +#include "toolchain/check/call.h" +#include "toolchain/check/context.h" +#include "toolchain/check/member_access.h" +#include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/typed_insts.h" + +namespace Carbon::Check { + +// Returns the scope of the Core package, or Invalid if it's not found. +// +// TODO: Consider tracking the Core package in SemIR so we don't need to use +// name lookup to find it. +static auto GetCorePackage(Context& context, Parse::AnyExprId node_id) + -> SemIR::NameScopeId { + // TODO: If the current package is the `Core` package, return + // `SemIR::InstId::Package`. + + auto ident_id = context.identifiers().Lookup("Core"); + if (!ident_id.is_valid()) { + return SemIR::NameScopeId::Invalid; + } + auto name_id = SemIR::NameId::ForIdentifier(ident_id); + + // Look up `package.Core`. + auto package_id = context.LookupQualifiedName( + node_id, name_id, SemIR::NameScopeId::Package, /*required=*/false); + if (!package_id.is_valid()) { + return SemIR::NameScopeId::Invalid; + } + + // Look through import_refs and aliases. + package_id = context.constant_values().Get(package_id).inst_id(); + + // We expect it to be a package, and fail if not. + if (auto package_inst = + context.insts().TryGetAs(package_id)) { + auto& name_scope = context.name_scopes().Get(package_inst->name_scope_id); + // Check that this is really the `Core` package and not an alias. + if (name_scope.is_closed_import && name_scope.name_id == name_id && + name_scope.enclosing_scope_id == SemIR::NameScopeId::Package) { + return package_inst->name_scope_id; + } + } + return SemIR::NameScopeId::Invalid; +} + +// Returns the name scope of the operator interface for the specified operator +// from the Core package. +static auto GetOperatorInterface(Context& context, Parse::AnyExprId node_id, + Operator op) -> SemIR::NameScopeId { + auto carbon_package_id = GetCorePackage(context, node_id); + if (!carbon_package_id.is_valid()) { + return SemIR::NameScopeId::Invalid; + } + + // Lookup `Core.InterfaceName`. + auto interface_ident_id = context.identifiers().Add(op.interface_name); + auto interface_id = context.LookupQualifiedName( + node_id, SemIR::NameId::ForIdentifier(interface_ident_id), + carbon_package_id, /*required=*/false); + if (!interface_id.is_valid()) { + return SemIR::NameScopeId::Invalid; + } + + // Look through import_refs and aliases. + interface_id = context.constant_values().Get(interface_id).inst_id(); + + // We expect it to be an interface. + if (auto interface_inst = + context.insts().TryGetAs(interface_id)) { + return context.interfaces().Get(interface_inst->interface_id).scope_id; + } + return SemIR::NameScopeId::Invalid; +} + +// Returns the `Op` function for the specified operator. +static auto GetOperatorOpFunction(Context& context, Parse::AnyExprId node_id, + Operator op) -> SemIR::InstId { + auto interface_scope_id = GetOperatorInterface(context, node_id, op); + if (!interface_scope_id.is_valid()) { + return SemIR::InstId::Invalid; + } + + // Lookup `Interface.Op`. + auto op_ident_id = context.identifiers().Add(op.op_name); + auto op_id = context.LookupQualifiedName( + node_id, SemIR::NameId::ForIdentifier(op_ident_id), interface_scope_id, + /*required=*/false); + if (!op_id.is_valid()) { + return SemIR::InstId::Invalid; + } + + // Look through import_refs and aliases. + op_id = context.constant_values().Get(op_id).inst_id(); + + // We expect it to be an associated function. + if (context.insts().Is(op_id)) { + return op_id; + } + return SemIR::InstId::Invalid; +} + +auto BuildUnaryOperator(Context& context, Parse::AnyExprId node_id, Operator op, + SemIR::InstId operand_id) -> SemIR::InstId { + auto op_fn = GetOperatorOpFunction(context, node_id, op); + if (!op_fn.is_valid()) { + context.TODO(node_id, "missing or invalid operator interface"); + return SemIR::InstId::BuiltinError; + } + + // Form `operand.(Op)`. + auto bound_op_id = + PerformCompoundMemberAccess(context, node_id, operand_id, op_fn); + if (bound_op_id == SemIR::InstId::BuiltinError) { + return SemIR::InstId::BuiltinError; + } + + // Form `bound_op()`. + return PerformCall(context, node_id, bound_op_id, {}); +} + +auto BuildBinaryOperator(Context& context, Parse::AnyExprId node_id, + Operator op, SemIR::InstId lhs_id, + SemIR::InstId rhs_id) -> SemIR::InstId { + auto op_fn = GetOperatorOpFunction(context, node_id, op); + if (!op_fn.is_valid()) { + context.TODO(node_id, "missing or invalid operator interface"); + return SemIR::InstId::BuiltinError; + } + + // Form `lhs.(Op)`. + auto bound_op_id = + PerformCompoundMemberAccess(context, node_id, lhs_id, op_fn); + if (bound_op_id == SemIR::InstId::BuiltinError) { + return SemIR::InstId::BuiltinError; + } + + // Form `bound_op(rhs)`. + return PerformCall(context, node_id, bound_op_id, {rhs_id}); +} + +} // namespace Carbon::Check diff --git a/toolchain/check/operator.h b/toolchain/check/operator.h new file mode 100644 index 000000000000..77d79ae81801 --- /dev/null +++ b/toolchain/check/operator.h @@ -0,0 +1,32 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_OPERATOR_H_ +#define CARBON_TOOLCHAIN_CHECK_OPERATOR_H_ + +#include "toolchain/check/context.h" +#include "toolchain/parse/node_ids.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +struct Operator { + llvm::StringLiteral interface_name; + llvm::StringLiteral op_name = "Op"; +}; + +// Checks and builds SemIR for a unary operator expression. For example, +// `$operand` or `operand$`. +auto BuildUnaryOperator(Context& context, Parse::AnyExprId node_id, Operator op, + SemIR::InstId operand_id) -> SemIR::InstId; + +// Checks and builds SemIR for a binary operator expression. For example, +// `lhs_id $ rhs_id`. +auto BuildBinaryOperator(Context& context, Parse::AnyExprId node_id, + Operator op, SemIR::InstId lhs_id, + SemIR::InstId rhs_id) -> SemIR::InstId; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_OPERATOR_H_ diff --git a/toolchain/check/pointer_dereference.cpp b/toolchain/check/pointer_dereference.cpp index 556ae5ee3741..e8371e17c14d 100644 --- a/toolchain/check/pointer_dereference.cpp +++ b/toolchain/check/pointer_dereference.cpp @@ -15,6 +15,11 @@ auto PerformPointerDereference( SemIR::InstId base_id, llvm::function_refvoid> diagnose_not_pointer) -> SemIR::InstId { + // TODO: Once we have a finalized design for a pointer interface, use + // + // HandleUnaryOperator(context, node_id, {"Pointer", "Dereference"}); + // + // to convert to a pointer value. base_id = ConvertToValueExpr(context, base_id); auto type_id = context.GetUnqualifiedType(context.insts().Get(base_id).type_id()); diff --git a/toolchain/check/testdata/array/fail_bound_overflow.carbon b/toolchain/check/testdata/array/fail_bound_overflow.carbon index 0e8a93bba4ee..bc94d859ae76 100644 --- a/toolchain/check/testdata/array/fail_bound_overflow.carbon +++ b/toolchain/check/testdata/array/fail_bound_overflow.carbon @@ -9,12 +9,9 @@ // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ var a: [i32; 39999999999999999993]; -// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+6]]:9: ERROR: Cannot implicitly convert from `i32` to `type`. +// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+3]]:9: ERROR: Cannot implicitly convert from `i32` to `type`. // CHECK:STDERR: var b: [1; 39999999999999999993]; // CHECK:STDERR: ^ -// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+3]]:12: ERROR: Array bound of 39999999999999999993 is too large. -// CHECK:STDERR: var b: [1; 39999999999999999993]; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ var b: [1; 39999999999999999993]; // CHECK:STDOUT: --- fail_bound_overflow.carbon @@ -33,9 +30,9 @@ var b: [1; 39999999999999999993]; // CHECK:STDOUT: %.loc10_34: type = array_type %.loc10_14, i32 [template = ] // CHECK:STDOUT: %a.var: ref = var a // CHECK:STDOUT: %a: ref = bind_name a, %a.var -// CHECK:STDOUT: %.loc18_9: i32 = int_literal 1 [template = constants.%.2] -// CHECK:STDOUT: %.loc18_12: i32 = int_literal 39999999999999999993 [template = constants.%.1] -// CHECK:STDOUT: %.loc18_32: type = array_type %.loc18_12, [template = ] +// CHECK:STDOUT: %.loc15_9: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %.loc15_12: i32 = int_literal 39999999999999999993 [template = constants.%.1] +// CHECK:STDOUT: %.loc15_32: type = array_type %.loc15_12, [template = ] // CHECK:STDOUT: %b.var: ref = var b // CHECK:STDOUT: %b: ref = bind_name b, %b.var // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/index/fail_negative_indexing.carbon b/toolchain/check/testdata/index/fail_negative_indexing.carbon index 862f072049a1..4135c2334f8c 100644 --- a/toolchain/check/testdata/index/fail_negative_indexing.carbon +++ b/toolchain/check/testdata/index/fail_negative_indexing.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE var a: (i32, i32) = (12, 6); -// CHECK:STDERR: fail_negative_indexing.carbon:[[@LINE+3]]:16: ERROR: Semantics TODO: `HandlePrefixOperatorMinus`. +// CHECK:STDERR: fail_negative_indexing.carbon:[[@LINE+3]]:16: ERROR: Semantics TODO: `missing or invalid operator interface`. // CHECK:STDERR: var b: i32 = a[-10]; // CHECK:STDERR: ^~~ var b: i32 = a[-10]; @@ -22,5 +22,35 @@ var b: i32 = a[-10]; // CHECK:STDOUT: %.7: i32 = int_literal 10 [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: file {} +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .a = %a +// CHECK:STDOUT: .b = %b +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc7_17.1: (type, type) = tuple_literal (i32, i32) +// CHECK:STDOUT: %.loc7_17.2: type = converted %.loc7_17.1, constants.%.2 [template = constants.%.2] +// CHECK:STDOUT: %a.var: ref (i32, i32) = var a +// CHECK:STDOUT: %a: ref (i32, i32) = bind_name a, %a.var +// CHECK:STDOUT: %b.var: ref i32 = var b +// CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_22: i32 = int_literal 12 [template = constants.%.4] +// CHECK:STDOUT: %.loc7_26: i32 = int_literal 6 [template = constants.%.5] +// CHECK:STDOUT: %.loc7_27.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_26) +// CHECK:STDOUT: %.loc7_27.2: ref i32 = tuple_access file.%a.var, element0 +// CHECK:STDOUT: %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2 [template = constants.%.4] +// CHECK:STDOUT: %.loc7_27.4: ref i32 = tuple_access file.%a.var, element1 +// CHECK:STDOUT: %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4 [template = constants.%.5] +// CHECK:STDOUT: %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to file.%a.var [template = constants.%.6] +// CHECK:STDOUT: %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6 [template = constants.%.6] +// CHECK:STDOUT: assign file.%a.var, %.loc7_27.7 +// CHECK:STDOUT: %a.ref: ref (i32, i32) = name_ref a, file.%a +// CHECK:STDOUT: %.loc11_17: i32 = int_literal 10 [template = constants.%.7] +// CHECK:STDOUT: %.loc11_19: ref = tuple_index %a.ref, +// CHECK:STDOUT: assign file.%b.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/fail_todo_import.carbon b/toolchain/check/testdata/interface/fail_todo_import.carbon deleted file mode 100644 index d717cd901cfa..000000000000 --- a/toolchain/check/testdata/interface/fail_todo_import.carbon +++ /dev/null @@ -1,256 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntityType`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntity`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntityType`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntity`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntityType`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntity`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntityType`. -// CHECK:STDERR: fail_b.carbon: ERROR: Semantics TODO: `TryResolveInst on AssociatedEntity`. - -// --- a.carbon - -library "a" api; - -interface Empty { -} - -interface Basic { - let T:! type; - fn F(); -} - -interface ForwardDeclared; - -interface ForwardDeclared { - let T:! type; - fn F(); -} - -var f_ref: {.f: ForwardDeclared}; - -// --- fail_b.carbon - -library "b" api; - -import library "a"; - -fn UseEmpty(e: Empty) {} -fn UseBasic(e: Basic) {} -fn UseForwardDeclared(f: ForwardDeclared) {} - -alias UseBasicT = Basic.T; -alias UseBasicF = Basic.F; - -alias UseForwardDeclaredT = ForwardDeclared.T; -alias UseForwardDeclaredF = ForwardDeclared.F; - -var f: ForwardDeclared* = &f_ref.f; - -// CHECK:STDOUT: --- a.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = interface_type @Empty [template] -// CHECK:STDOUT: %.2: type = interface_type @Basic [template] -// CHECK:STDOUT: %.3: type = assoc_entity_type @Basic, type [template] -// CHECK:STDOUT: %.4: = assoc_entity element0, @Basic.%T [template] -// CHECK:STDOUT: %.5: type = assoc_entity_type @Basic, [template] -// CHECK:STDOUT: %.6: in Basic> = assoc_entity element1, @Basic.%F [template] -// CHECK:STDOUT: %.7: type = interface_type @ForwardDeclared [template] -// CHECK:STDOUT: %.8: type = assoc_entity_type @ForwardDeclared, type [template] -// CHECK:STDOUT: %.9: = assoc_entity element0, @ForwardDeclared.%T [template] -// CHECK:STDOUT: %.10: type = assoc_entity_type @ForwardDeclared, [template] -// CHECK:STDOUT: %.11: in ForwardDeclared> = assoc_entity element1, @ForwardDeclared.%F [template] -// CHECK:STDOUT: %.12: type = struct_type {.f: ForwardDeclared} [template] -// CHECK:STDOUT: %.13: type = tuple_type () [template] -// CHECK:STDOUT: %.14: type = struct_type {.f: ()} [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Empty = %Empty.decl -// CHECK:STDOUT: .Basic = %Basic.decl -// CHECK:STDOUT: .ForwardDeclared = %ForwardDeclared.decl.loc12 -// CHECK:STDOUT: .f_ref = %f_ref -// CHECK:STDOUT: } -// CHECK:STDOUT: %Empty.decl: type = interface_decl @Empty [template = constants.%.1] {} -// CHECK:STDOUT: %Basic.decl: type = interface_decl @Basic [template = constants.%.2] {} -// CHECK:STDOUT: %ForwardDeclared.decl.loc12: type = interface_decl @ForwardDeclared [template = constants.%.7] {} -// CHECK:STDOUT: %ForwardDeclared.decl.loc14: type = interface_decl @ForwardDeclared [template = constants.%.7] {} -// CHECK:STDOUT: %ForwardDeclared.ref: type = name_ref ForwardDeclared, %ForwardDeclared.decl.loc12 [template = constants.%.7] -// CHECK:STDOUT: %.loc19: type = struct_type {.f: ForwardDeclared} [template = constants.%.12] -// CHECK:STDOUT: %f_ref.var: ref {.f: ForwardDeclared} = var f_ref -// CHECK:STDOUT: %f_ref: ref {.f: ForwardDeclared} = bind_name f_ref, %f_ref.var -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @Empty { -// CHECK:STDOUT: %Self: Empty = bind_symbolic_name Self [symbolic] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %Self -// CHECK:STDOUT: witness = () -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @Basic { -// CHECK:STDOUT: %Self: Basic = bind_symbolic_name Self [symbolic] -// CHECK:STDOUT: %T: type = assoc_const_decl T [template] -// CHECK:STDOUT: %.loc8: = assoc_entity element0, %T [template = constants.%.4] -// CHECK:STDOUT: %F: = fn_decl @F.1 [template] {} -// CHECK:STDOUT: %.loc9: in Basic> = assoc_entity element1, %F [template = constants.%.6] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %Self -// CHECK:STDOUT: .T = %.loc8 -// CHECK:STDOUT: .F = %.loc9 -// CHECK:STDOUT: witness = (%T, %F) -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @ForwardDeclared { -// CHECK:STDOUT: %Self: ForwardDeclared = bind_symbolic_name Self [symbolic] -// CHECK:STDOUT: %T: type = assoc_const_decl T [template] -// CHECK:STDOUT: %.loc15: = assoc_entity element0, %T [template = constants.%.9] -// CHECK:STDOUT: %F: = fn_decl @F.2 [template] {} -// CHECK:STDOUT: %.loc16: in ForwardDeclared> = assoc_entity element1, %F [template = constants.%.11] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %Self -// CHECK:STDOUT: .T = %.loc15 -// CHECK:STDOUT: .F = %.loc16 -// CHECK:STDOUT: witness = (%T, %F) -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2(); -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_b.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = interface_type @Empty [template] -// CHECK:STDOUT: %.2: type = tuple_type () [template] -// CHECK:STDOUT: %.3: type = interface_type @Basic [template] -// CHECK:STDOUT: %.4: type = interface_type @ForwardDeclared [template] -// CHECK:STDOUT: %.5: type = ptr_type ForwardDeclared [template] -// CHECK:STDOUT: %.6: type = struct_type {.f: ForwardDeclared} [template] -// CHECK:STDOUT: %.7: type = struct_type {.f: ()} [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Empty = %import_ref.1 -// CHECK:STDOUT: .Basic = %import_ref.2 -// CHECK:STDOUT: .ForwardDeclared = %import_ref.3 -// CHECK:STDOUT: .f_ref = %import_ref.4 -// CHECK:STDOUT: .UseEmpty = %UseEmpty -// CHECK:STDOUT: .UseBasic = %UseBasic -// CHECK:STDOUT: .UseForwardDeclared = %UseForwardDeclared -// CHECK:STDOUT: .UseBasicT = %UseBasicT -// CHECK:STDOUT: .UseBasicF = %UseBasicF -// CHECK:STDOUT: .UseForwardDeclaredT = %UseForwardDeclaredT -// CHECK:STDOUT: .UseForwardDeclaredF = %UseForwardDeclaredF -// CHECK:STDOUT: .f = %f.loc16 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.1] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%.3] -// CHECK:STDOUT: %import_ref.3: type = import_ref ir1, inst+15, used [template = constants.%.4] -// CHECK:STDOUT: %import_ref.4: ref {.f: ForwardDeclared} = import_ref ir1, inst+36, used -// CHECK:STDOUT: %UseEmpty: = fn_decl @UseEmpty [template] { -// CHECK:STDOUT: %Empty.decl: invalid = interface_decl @Empty [template = constants.%.1] {} -// CHECK:STDOUT: %Empty.ref: type = name_ref Empty, %import_ref.1 [template = constants.%.1] -// CHECK:STDOUT: %e.loc6_13.1: Empty = param e -// CHECK:STDOUT: @UseEmpty.%e: Empty = bind_name e, %e.loc6_13.1 -// CHECK:STDOUT: } -// CHECK:STDOUT: %UseBasic: = fn_decl @UseBasic [template] { -// CHECK:STDOUT: %Basic.decl: invalid = interface_decl @Basic [template = constants.%.3] {} -// CHECK:STDOUT: %Basic.ref.loc7: type = name_ref Basic, %import_ref.2 [template = constants.%.3] -// CHECK:STDOUT: %e.loc7_13.1: Basic = param e -// CHECK:STDOUT: @UseBasic.%e: Basic = bind_name e, %e.loc7_13.1 -// CHECK:STDOUT: } -// CHECK:STDOUT: %UseForwardDeclared: = fn_decl @UseForwardDeclared [template] { -// CHECK:STDOUT: %ForwardDeclared.decl: invalid = interface_decl @ForwardDeclared [template = constants.%.4] {} -// CHECK:STDOUT: %ForwardDeclared.ref.loc8: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] -// CHECK:STDOUT: %f.loc8_23.1: ForwardDeclared = param f -// CHECK:STDOUT: @UseForwardDeclared.%f: ForwardDeclared = bind_name f, %f.loc8_23.1 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Basic.ref.loc10: type = name_ref Basic, %import_ref.2 [template = constants.%.3] -// CHECK:STDOUT: %T.ref.loc10: = name_ref T, @Basic.%import_ref.3 [template = ] -// CHECK:STDOUT: %UseBasicT: = bind_alias UseBasicT, @Basic.%import_ref.3 [template = ] -// CHECK:STDOUT: %Basic.ref.loc11: type = name_ref Basic, %import_ref.2 [template = constants.%.3] -// CHECK:STDOUT: %F.ref.loc11: = name_ref F, @Basic.%import_ref.2 [template = ] -// CHECK:STDOUT: %UseBasicF: = bind_alias UseBasicF, @Basic.%import_ref.2 [template = ] -// CHECK:STDOUT: %ForwardDeclared.ref.loc13: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] -// CHECK:STDOUT: %T.ref.loc13: = name_ref T, @ForwardDeclared.%import_ref.3 [template = ] -// CHECK:STDOUT: %UseForwardDeclaredT: = bind_alias UseForwardDeclaredT, @ForwardDeclared.%import_ref.3 [template = ] -// CHECK:STDOUT: %ForwardDeclared.ref.loc14: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] -// CHECK:STDOUT: %F.ref.loc14: = name_ref F, @ForwardDeclared.%import_ref.2 [template = ] -// CHECK:STDOUT: %UseForwardDeclaredF: = bind_alias UseForwardDeclaredF, @ForwardDeclared.%import_ref.2 [template = ] -// CHECK:STDOUT: %ForwardDeclared.ref.loc16: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] -// CHECK:STDOUT: %.loc16: type = ptr_type ForwardDeclared [template = constants.%.5] -// CHECK:STDOUT: %f.var: ref ForwardDeclared* = var f -// CHECK:STDOUT: %f.loc16: ref ForwardDeclared* = bind_name f, %f.var -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @Empty { -// CHECK:STDOUT: %import_ref = import_ref ir1, inst+3, unused -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %import_ref -// CHECK:STDOUT: witness = () -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @Basic { -// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+6, unused -// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+13, used [template = ] -// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+9, used [template = ] -// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+7, unused -// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+11, unused -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %import_ref.1 -// CHECK:STDOUT: .F = %import_ref.2 -// CHECK:STDOUT: .T = %import_ref.3 -// CHECK:STDOUT: witness = (%import_ref.4, %import_ref.5) -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: interface @ForwardDeclared { -// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+18, unused -// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+25, used [template = ] -// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+21, used [template = ] -// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+19, unused -// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+23, unused -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %import_ref.1 -// CHECK:STDOUT: .F = %import_ref.2 -// CHECK:STDOUT: .T = %import_ref.3 -// CHECK:STDOUT: witness = (%import_ref.4, %import_ref.5) -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @UseEmpty(%e: Empty) { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @UseBasic(%e: Basic) { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @UseForwardDeclared(%f: ForwardDeclared) { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %f_ref.ref: ref {.f: ForwardDeclared} = name_ref f_ref, file.%import_ref.4 -// CHECK:STDOUT: %.loc16_33: ref ForwardDeclared = struct_access %f_ref.ref, element0 -// CHECK:STDOUT: %.loc16_27: ForwardDeclared* = addr_of %.loc16_33 -// CHECK:STDOUT: assign file.%f.var, %.loc16_27 -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/import.carbon b/toolchain/check/testdata/interface/import.carbon index 1a363c63b7d2..475ee276f2b2 100644 --- a/toolchain/check/testdata/interface/import.carbon +++ b/toolchain/check/testdata/interface/import.carbon @@ -35,6 +35,12 @@ fn UseEmpty(e: Empty) {} fn UseBasic(e: Basic) {} fn UseForwardDeclared(f: ForwardDeclared) {} +alias UseBasicT = Basic.T; +alias UseBasicF = Basic.F; + +alias UseForwardDeclaredT = ForwardDeclared.T; +alias UseForwardDeclaredF = ForwardDeclared.F; + var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: --- a.carbon @@ -120,9 +126,17 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %.3: type = interface_type @Basic [template] // CHECK:STDOUT: %.4: type = interface_type @ForwardDeclared [template] -// CHECK:STDOUT: %.5: type = ptr_type ForwardDeclared [template] -// CHECK:STDOUT: %.6: type = struct_type {.f: ForwardDeclared} [template] -// CHECK:STDOUT: %.7: type = struct_type {.f: ()} [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type @Basic, type [template] +// CHECK:STDOUT: %.6: = assoc_entity element0, file.%import_ref.5 [template] +// CHECK:STDOUT: %.7: type = assoc_entity_type @Basic, [template] +// CHECK:STDOUT: %.8: in Basic> = assoc_entity element1, file.%import_ref.6 [template] +// CHECK:STDOUT: %.9: type = assoc_entity_type @ForwardDeclared, type [template] +// CHECK:STDOUT: %.10: = assoc_entity element0, file.%import_ref.7 [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @ForwardDeclared, [template] +// CHECK:STDOUT: %.12: in ForwardDeclared> = assoc_entity element1, file.%import_ref.8 [template] +// CHECK:STDOUT: %.13: type = ptr_type ForwardDeclared [template] +// CHECK:STDOUT: %.14: type = struct_type {.f: ForwardDeclared} [template] +// CHECK:STDOUT: %.15: type = struct_type {.f: ()} [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -134,7 +148,11 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: .UseEmpty = %UseEmpty // CHECK:STDOUT: .UseBasic = %UseBasic // CHECK:STDOUT: .UseForwardDeclared = %UseForwardDeclared -// CHECK:STDOUT: .f = %f.loc10 +// CHECK:STDOUT: .UseBasicT = %UseBasicT +// CHECK:STDOUT: .UseBasicF = %UseBasicF +// CHECK:STDOUT: .UseForwardDeclaredT = %UseForwardDeclaredT +// CHECK:STDOUT: .UseForwardDeclaredF = %UseForwardDeclaredF +// CHECK:STDOUT: .f = %f.loc16 // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.1] // CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%.3] @@ -148,7 +166,7 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: } // CHECK:STDOUT: %UseBasic: = fn_decl @UseBasic [template] { // CHECK:STDOUT: %Basic.decl: invalid = interface_decl @Basic [template = constants.%.3] {} -// CHECK:STDOUT: %Basic.ref: type = name_ref Basic, %import_ref.2 [template = constants.%.3] +// CHECK:STDOUT: %Basic.ref.loc7: type = name_ref Basic, %import_ref.2 [template = constants.%.3] // CHECK:STDOUT: %e.loc7_13.1: Basic = param e // CHECK:STDOUT: @UseBasic.%e: Basic = bind_name e, %e.loc7_13.1 // CHECK:STDOUT: } @@ -158,10 +176,26 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: %f.loc8_23.1: ForwardDeclared = param f // CHECK:STDOUT: @UseForwardDeclared.%f: ForwardDeclared = bind_name f, %f.loc8_23.1 // CHECK:STDOUT: } -// CHECK:STDOUT: %ForwardDeclared.ref.loc10: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] -// CHECK:STDOUT: %.loc10: type = ptr_type ForwardDeclared [template = constants.%.5] +// CHECK:STDOUT: %Basic.ref.loc10: type = name_ref Basic, %import_ref.2 [template = constants.%.3] +// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+7, unused +// CHECK:STDOUT: %T.ref.loc10: = name_ref T, @Basic.%import_ref.3 [template = constants.%.6] +// CHECK:STDOUT: %UseBasicT: = bind_alias UseBasicT, @Basic.%import_ref.3 [template = constants.%.6] +// CHECK:STDOUT: %Basic.ref.loc11: type = name_ref Basic, %import_ref.2 [template = constants.%.3] +// CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+11, unused +// CHECK:STDOUT: %F.ref.loc11: in Basic> = name_ref F, @Basic.%import_ref.2 [template = constants.%.8] +// CHECK:STDOUT: %UseBasicF: in Basic> = bind_alias UseBasicF, @Basic.%import_ref.2 [template = constants.%.8] +// CHECK:STDOUT: %ForwardDeclared.ref.loc13: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] +// CHECK:STDOUT: %import_ref.7 = import_ref ir1, inst+19, unused +// CHECK:STDOUT: %T.ref.loc13: = name_ref T, @ForwardDeclared.%import_ref.3 [template = constants.%.10] +// CHECK:STDOUT: %UseForwardDeclaredT: = bind_alias UseForwardDeclaredT, @ForwardDeclared.%import_ref.3 [template = constants.%.10] +// CHECK:STDOUT: %ForwardDeclared.ref.loc14: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] +// CHECK:STDOUT: %import_ref.8 = import_ref ir1, inst+23, unused +// CHECK:STDOUT: %F.ref.loc14: in ForwardDeclared> = name_ref F, @ForwardDeclared.%import_ref.2 [template = constants.%.12] +// CHECK:STDOUT: %UseForwardDeclaredF: in ForwardDeclared> = bind_alias UseForwardDeclaredF, @ForwardDeclared.%import_ref.2 [template = constants.%.12] +// CHECK:STDOUT: %ForwardDeclared.ref.loc16: type = name_ref ForwardDeclared, %import_ref.3 [template = constants.%.4] +// CHECK:STDOUT: %.loc16: type = ptr_type ForwardDeclared [template = constants.%.13] // CHECK:STDOUT: %f.var: ref ForwardDeclared* = var f -// CHECK:STDOUT: %f.loc10: ref ForwardDeclared* = bind_name f, %f.var +// CHECK:STDOUT: %f.loc16: ref ForwardDeclared* = bind_name f, %f.var // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @Empty { @@ -174,8 +208,8 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: // CHECK:STDOUT: interface @Basic { // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+6, unused -// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unused -// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unused +// CHECK:STDOUT: %import_ref.2: in Basic> = import_ref ir1, inst+13, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+9, used [template = constants.%.6] // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+7, unused // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+11, unused // CHECK:STDOUT: @@ -188,8 +222,8 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: // CHECK:STDOUT: interface @ForwardDeclared { // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+18, unused -// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+25, unused -// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+21, unused +// CHECK:STDOUT: %import_ref.2: in ForwardDeclared> = import_ref ir1, inst+25, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+21, used [template = constants.%.10] // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+19, unused // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+23, unused // CHECK:STDOUT: @@ -218,9 +252,9 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %f_ref.ref: ref {.f: ForwardDeclared} = name_ref f_ref, file.%import_ref.4 -// CHECK:STDOUT: %.loc10_33: ref ForwardDeclared = struct_access %f_ref.ref, element0 -// CHECK:STDOUT: %.loc10_27: ForwardDeclared* = addr_of %.loc10_33 -// CHECK:STDOUT: assign file.%f.var, %.loc10_27 +// CHECK:STDOUT: %.loc16_33: ref ForwardDeclared = struct_access %f_ref.ref, element0 +// CHECK:STDOUT: %.loc16_27: ForwardDeclared* = addr_of %.loc16_33 +// CHECK:STDOUT: assign file.%f.var, %.loc16_27 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/let/fail_generic_import.carbon b/toolchain/check/testdata/let/fail_generic_import.carbon index e58b751fde7f..97f7861922f3 100644 --- a/toolchain/check/testdata/let/fail_generic_import.carbon +++ b/toolchain/check/testdata/let/fail_generic_import.carbon @@ -37,8 +37,8 @@ let a: T = 0; // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .T = %import_ref // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [symbolic] -// CHECK:STDOUT: %T.ref: type = name_ref T, %import_ref [symbolic = %import_ref] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [symbolic = ] +// CHECK:STDOUT: %T.ref: type = name_ref T, %import_ref [symbolic = ] // CHECK:STDOUT: %.loc8: i32 = int_literal 0 [template = constants.%.1] // CHECK:STDOUT: %a: T = bind_name a, // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/let/generic_import.carbon b/toolchain/check/testdata/let/generic_import.carbon index e506f5d0aea2..360e482b5a40 100644 --- a/toolchain/check/testdata/let/generic_import.carbon +++ b/toolchain/check/testdata/let/generic_import.carbon @@ -36,12 +36,12 @@ var b: T = *a; // CHECK:STDOUT: .a = %a // CHECK:STDOUT: .b = %b // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [symbolic] -// CHECK:STDOUT: %T.ref.loc4: type = name_ref T, %import_ref [symbolic = %import_ref] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [symbolic = ] +// CHECK:STDOUT: %T.ref.loc4: type = name_ref T, %import_ref [symbolic = ] // CHECK:STDOUT: %.loc4: type = ptr_type T [symbolic = constants.%.1] // CHECK:STDOUT: %a.var: ref T* = var a // CHECK:STDOUT: %a: ref T* = bind_name a, %a.var -// CHECK:STDOUT: %T.ref.loc5: type = name_ref T, %import_ref [symbolic = %import_ref] +// CHECK:STDOUT: %T.ref.loc5: type = name_ref T, %import_ref [symbolic = ] // CHECK:STDOUT: %b.var: ref T = var b // CHECK:STDOUT: %b: ref T = bind_name b, %b.var // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/let/import.carbon b/toolchain/check/testdata/let/import.carbon index 1af3f96af7df..a081056b6460 100644 --- a/toolchain/check/testdata/let/import.carbon +++ b/toolchain/check/testdata/let/import.carbon @@ -34,8 +34,8 @@ let b:! bool = a; // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .a = %import_ref // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref: bool = import_ref ir1, inst+1, used [symbolic] -// CHECK:STDOUT: %a.ref: bool = name_ref a, %import_ref [symbolic = %import_ref] +// CHECK:STDOUT: %import_ref: bool = import_ref ir1, inst+1, used [symbolic = ] +// CHECK:STDOUT: %a.ref: bool = name_ref a, %import_ref [symbolic = ] // CHECK:STDOUT: %b: bool = bind_symbolic_name b, %a.ref [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/and.carbon b/toolchain/check/testdata/operators/builtin/and.carbon similarity index 100% rename from toolchain/check/testdata/operators/and.carbon rename to toolchain/check/testdata/operators/builtin/and.carbon diff --git a/toolchain/check/testdata/operators/assignment.carbon b/toolchain/check/testdata/operators/builtin/assignment.carbon similarity index 100% rename from toolchain/check/testdata/operators/assignment.carbon rename to toolchain/check/testdata/operators/builtin/assignment.carbon diff --git a/toolchain/check/testdata/operators/fail_and_or_not_in_function.carbon b/toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_and_or_not_in_function.carbon rename to toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon diff --git a/toolchain/check/testdata/operators/fail_assignment_to_error.carbon b/toolchain/check/testdata/operators/builtin/fail_assignment_to_error.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_assignment_to_error.carbon rename to toolchain/check/testdata/operators/builtin/fail_assignment_to_error.carbon diff --git a/toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon b/toolchain/check/testdata/operators/builtin/fail_assignment_to_non_assignable.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon rename to toolchain/check/testdata/operators/builtin/fail_assignment_to_non_assignable.carbon diff --git a/toolchain/check/testdata/operators/fail_redundant_compound_access.carbon b/toolchain/check/testdata/operators/builtin/fail_redundant_compound_access.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_redundant_compound_access.carbon rename to toolchain/check/testdata/operators/builtin/fail_redundant_compound_access.carbon diff --git a/toolchain/check/testdata/operators/fail_type_mismatch.carbon b/toolchain/check/testdata/operators/builtin/fail_type_mismatch.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_type_mismatch.carbon rename to toolchain/check/testdata/operators/builtin/fail_type_mismatch.carbon diff --git a/toolchain/check/testdata/operators/fail_type_mismatch_assignment.carbon b/toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon similarity index 100% rename from toolchain/check/testdata/operators/fail_type_mismatch_assignment.carbon rename to toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon diff --git a/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon b/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon new file mode 100644 index 000000000000..09b26ec151ca --- /dev/null +++ b/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon @@ -0,0 +1,42 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +fn Main() -> i32 { + // The following line has two mismatches, but after the first, it shouldn't + // keep erroring. + // CHECK:STDERR: fail_type_mismatch_once.carbon:[[@LINE+6]]:10: ERROR: Semantics TODO: `missing or invalid operator interface`. + // CHECK:STDERR: return 12 + 3.4 + 12; + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_type_mismatch_once.carbon:[[@LINE+3]]:10: ERROR: Semantics TODO: `missing or invalid operator interface`. + // CHECK:STDERR: return 12 + 3.4 + 12; + // CHECK:STDERR: ^~~~~~~~~~~~~ + return 12 + 3.4 + 12; +} + +// CHECK:STDOUT: --- fail_type_mismatch_once.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: i32 = int_literal 12 [template] +// CHECK:STDOUT: %.2: f64 = real_literal 34e-1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Main = %Main +// CHECK:STDOUT: } +// CHECK:STDOUT: %Main: = fn_decl @Main [template] { +// CHECK:STDOUT: %return.var: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Main() -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc16_10: i32 = int_literal 12 [template = constants.%.1] +// CHECK:STDOUT: %.loc16_15: f64 = real_literal 34e-1 [template = constants.%.2] +// CHECK:STDOUT: %.loc16_21: i32 = int_literal 12 [template = constants.%.1] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/fail_unimplemented_op.carbon b/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon similarity index 56% rename from toolchain/check/testdata/operators/fail_unimplemented_op.carbon rename to toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon index 0650514cca44..6236d5b6e311 100644 --- a/toolchain/check/testdata/operators/fail_unimplemented_op.carbon +++ b/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE fn Main() -> i32 { - // CHECK:STDERR: fail_unimplemented_op.carbon:[[@LINE+3]]:10: ERROR: Semantics TODO: `HandleInfixOperatorPlus`. + // CHECK:STDERR: fail_unimplemented_op.carbon:[[@LINE+3]]:10: ERROR: Semantics TODO: `missing or invalid operator interface`. // CHECK:STDERR: return 12 + 34; // CHECK:STDERR: ^~~~~~~ return 12 + 34; @@ -18,9 +18,19 @@ fn Main() -> i32 { // CHECK:STDOUT: %.2: i32 = int_literal 34 [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: file {} +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Main = %Main +// CHECK:STDOUT: } +// CHECK:STDOUT: %Main: = fn_decl @Main [template] { +// CHECK:STDOUT: %return.var: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Main() -> i32 { // CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc11_10: i32 = int_literal 12 [template = constants.%.1] +// CHECK:STDOUT: %.loc11_15: i32 = int_literal 34 [template = constants.%.2] +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/or.carbon b/toolchain/check/testdata/operators/builtin/or.carbon similarity index 100% rename from toolchain/check/testdata/operators/or.carbon rename to toolchain/check/testdata/operators/builtin/or.carbon diff --git a/toolchain/check/testdata/operators/unary_op.carbon b/toolchain/check/testdata/operators/builtin/unary_op.carbon similarity index 100% rename from toolchain/check/testdata/operators/unary_op.carbon rename to toolchain/check/testdata/operators/builtin/unary_op.carbon diff --git a/toolchain/check/testdata/operators/fail_type_mismatch_once.carbon b/toolchain/check/testdata/operators/fail_type_mismatch_once.carbon deleted file mode 100644 index 72c584999058..000000000000 --- a/toolchain/check/testdata/operators/fail_type_mismatch_once.carbon +++ /dev/null @@ -1,28 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE - -fn Main() -> i32 { - // The following line has two mismatches, but after the first, it shouldn't - // keep erroring. - // CHECK:STDERR: fail_type_mismatch_once.carbon:[[@LINE+3]]:10: ERROR: Semantics TODO: `HandleInfixOperatorPlus`. - // CHECK:STDERR: return 12 + 3.4 + 12; - // CHECK:STDERR: ^~~~~~~~ - return 12 + 3.4 + 12; -} - -// CHECK:STDOUT: --- fail_type_mismatch_once.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: i32 = int_literal 12 [template] -// CHECK:STDOUT: %.2: f64 = real_literal 34e-1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file {} -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Main() -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/add.carbon b/toolchain/check/testdata/operators/overloaded/add.carbon new file mode 100644 index 000000000000..21b1a7c61dd4 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/add.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Add { + fn Op[self: Self](other: Self) -> Self; +} +interface AddAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Add { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.AddAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a + b; +} + +fn TestAssign(a: C*, b: C) { + *a += b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Add [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.3: in Add> = assoc_entity element0, @Add.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.7: in AddAssign> = assoc_entity element0, @AddAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Add = %Add.decl +// CHECK:STDOUT: .AddAssign = %AddAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Add.decl: type = interface_decl @Add [template = constants.%.1] {} +// CHECK:STDOUT: %AddAssign.decl: type = interface_decl @AddAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %Self: Add = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Add> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %Self: AddAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in AddAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Add.%self.loc5_9.2: Self](@Add.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @AddAssign.%self.loc8_14.3: Self*](@AddAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Add [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.12: in Add> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.14: in AddAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Add.decl: invalid = interface_decl @Add [template = constants.%.2] {} +// CHECK:STDOUT: %Add.ref: type = name_ref Add, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %AddAssign.decl: invalid = interface_decl @AddAssign [template = constants.%.7] {} +// CHECK:STDOUT: %AddAssign.ref: type = name_ref AddAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %import_ref.1: in Add> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %import_ref.1: in AddAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Add { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as AddAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/binary_op.carbon.tmpl b/toolchain/check/testdata/operators/overloaded/binary_op.carbon.tmpl new file mode 100644 index 000000000000..1dc84d32c2f8 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/binary_op.carbon.tmpl @@ -0,0 +1,43 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +HEADER + +// --- prelude.carbon + +package Core api; + +interface INTERFACE { + fn Op[self: Self](other: Self) -> Self; +} +interface INTERFACEAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.INTERFACE { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.INTERFACEAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a OP b; +} + +fn TestAssign(a: C*, b: C) { + *a OP= b; +} diff --git a/toolchain/check/testdata/operators/overloaded/bit_and.carbon b/toolchain/check/testdata/operators/overloaded/bit_and.carbon new file mode 100644 index 000000000000..3f69e2d06a2a --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/bit_and.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface BitAnd { + fn Op[self: Self](other: Self) -> Self; +} +interface BitAndAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.BitAnd { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.BitAndAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a & b; +} + +fn TestAssign(a: C*, b: C) { + *a &= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @BitAnd [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @BitAnd, [template] +// CHECK:STDOUT: %.3: in BitAnd> = assoc_entity element0, @BitAnd.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @BitAndAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @BitAndAssign, [template] +// CHECK:STDOUT: %.7: in BitAndAssign> = assoc_entity element0, @BitAndAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .BitAnd = %BitAnd.decl +// CHECK:STDOUT: .BitAndAssign = %BitAndAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %BitAnd.decl: type = interface_decl @BitAnd [template = constants.%.1] {} +// CHECK:STDOUT: %BitAndAssign.decl: type = interface_decl @BitAndAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitAnd { +// CHECK:STDOUT: %Self: BitAnd = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: BitAnd = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: BitAnd = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: BitAnd = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in BitAnd> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitAndAssign { +// CHECK:STDOUT: %Self: BitAndAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: BitAndAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: BitAndAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in BitAndAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@BitAnd.%self.loc5_9.2: Self](@BitAnd.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @BitAndAssign.%self.loc8_14.3: Self*](@BitAndAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @BitAnd [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @BitAndAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @BitAnd, [template] +// CHECK:STDOUT: %.12: in BitAnd> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @BitAndAssign, [template] +// CHECK:STDOUT: %.14: in BitAndAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %BitAnd.decl: invalid = interface_decl @BitAnd [template = constants.%.2] {} +// CHECK:STDOUT: %BitAnd.ref: type = name_ref BitAnd, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %BitAndAssign.decl: invalid = interface_decl @BitAndAssign [template = constants.%.7] {} +// CHECK:STDOUT: %BitAndAssign.ref: type = name_ref BitAndAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitAnd { +// CHECK:STDOUT: %import_ref.1: in BitAnd> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitAndAssign { +// CHECK:STDOUT: %import_ref.1: in BitAndAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as BitAnd { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as BitAndAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/bit_complement.carbon b/toolchain/check/testdata/operators/overloaded/bit_complement.carbon new file mode 100644 index 000000000000..d4cf3720ee5c --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/bit_complement.carbon @@ -0,0 +1,163 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from unary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface BitComplement { + fn Op[self: Self]() -> Self; +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.BitComplement { + fn Op[self: C]() -> C { + return {}; + } +} + +fn TestOp(a: C) -> C { + return ^a; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @BitComplement [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @BitComplement, [template] +// CHECK:STDOUT: %.3: in BitComplement> = assoc_entity element0, @BitComplement.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .BitComplement = %BitComplement.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %BitComplement.decl: type = interface_decl @BitComplement [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitComplement { +// CHECK:STDOUT: %Self: BitComplement = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: BitComplement = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_26: BitComplement = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_26.1: type = facet_type_access %Self.ref.loc5_26 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_26.2: type = converted %Self.ref.loc5_26, %.loc5_26.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_30: in BitComplement> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_30 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op[@BitComplement.%self.loc5_9.2: Self]() -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @BitComplement [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.%Op) [template] +// CHECK:STDOUT: %.7: type = assoc_entity_type @BitComplement, [template] +// CHECK:STDOUT: %.8: in BitComplement> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %BitComplement.decl: invalid = interface_decl @BitComplement [template = constants.%.2] {} +// CHECK:STDOUT: %BitComplement.ref: type = name_ref BitComplement, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc14_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc14_11.1 +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitComplement { +// CHECK:STDOUT: %import_ref.1: in BitComplement> = import_ref ir1, inst+15, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+13, used [template = imports.%Op] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as BitComplement { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_23: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.%self.loc9_9.2: C]() -> @impl.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self]() -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Op] +// CHECK:STDOUT: %.loc15_10.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc14: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc15_10.2: init C = call %.loc15_10.1(%a.ref) to %.loc14 +// CHECK:STDOUT: return %.loc15_10.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/bit_or.carbon b/toolchain/check/testdata/operators/overloaded/bit_or.carbon new file mode 100644 index 000000000000..9981e8d04910 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/bit_or.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface BitOr { + fn Op[self: Self](other: Self) -> Self; +} +interface BitOrAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.BitOr { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.BitOrAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a | b; +} + +fn TestAssign(a: C*, b: C) { + *a |= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @BitOr [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @BitOr, [template] +// CHECK:STDOUT: %.3: in BitOr> = assoc_entity element0, @BitOr.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @BitOrAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @BitOrAssign, [template] +// CHECK:STDOUT: %.7: in BitOrAssign> = assoc_entity element0, @BitOrAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .BitOr = %BitOr.decl +// CHECK:STDOUT: .BitOrAssign = %BitOrAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %BitOr.decl: type = interface_decl @BitOr [template = constants.%.1] {} +// CHECK:STDOUT: %BitOrAssign.decl: type = interface_decl @BitOrAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitOr { +// CHECK:STDOUT: %Self: BitOr = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: BitOr = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: BitOr = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: BitOr = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in BitOr> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitOrAssign { +// CHECK:STDOUT: %Self: BitOrAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: BitOrAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: BitOrAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in BitOrAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@BitOr.%self.loc5_9.2: Self](@BitOr.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @BitOrAssign.%self.loc8_14.3: Self*](@BitOrAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @BitOr [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @BitOrAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @BitOr, [template] +// CHECK:STDOUT: %.12: in BitOr> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @BitOrAssign, [template] +// CHECK:STDOUT: %.14: in BitOrAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %BitOr.decl: invalid = interface_decl @BitOr [template = constants.%.2] {} +// CHECK:STDOUT: %BitOr.ref: type = name_ref BitOr, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %BitOrAssign.decl: invalid = interface_decl @BitOrAssign [template = constants.%.7] {} +// CHECK:STDOUT: %BitOrAssign.ref: type = name_ref BitOrAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitOr { +// CHECK:STDOUT: %import_ref.1: in BitOr> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitOrAssign { +// CHECK:STDOUT: %import_ref.1: in BitOrAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as BitOr { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as BitOrAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/bit_xor.carbon b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon new file mode 100644 index 000000000000..3dea50fb9052 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface BitXor { + fn Op[self: Self](other: Self) -> Self; +} +interface BitXorAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.BitXor { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.BitXorAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a ^ b; +} + +fn TestAssign(a: C*, b: C) { + *a ^= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @BitXor [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @BitXor, [template] +// CHECK:STDOUT: %.3: in BitXor> = assoc_entity element0, @BitXor.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @BitXorAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @BitXorAssign, [template] +// CHECK:STDOUT: %.7: in BitXorAssign> = assoc_entity element0, @BitXorAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .BitXor = %BitXor.decl +// CHECK:STDOUT: .BitXorAssign = %BitXorAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %BitXor.decl: type = interface_decl @BitXor [template = constants.%.1] {} +// CHECK:STDOUT: %BitXorAssign.decl: type = interface_decl @BitXorAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitXor { +// CHECK:STDOUT: %Self: BitXor = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: BitXor = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: BitXor = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: BitXor = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in BitXor> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitXorAssign { +// CHECK:STDOUT: %Self: BitXorAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: BitXorAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: BitXorAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in BitXorAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@BitXor.%self.loc5_9.2: Self](@BitXor.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @BitXorAssign.%self.loc8_14.3: Self*](@BitXorAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @BitXor [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @BitXorAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @BitXor, [template] +// CHECK:STDOUT: %.12: in BitXor> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @BitXorAssign, [template] +// CHECK:STDOUT: %.14: in BitXorAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %BitXor.decl: invalid = interface_decl @BitXor [template = constants.%.2] {} +// CHECK:STDOUT: %BitXor.ref: type = name_ref BitXor, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %BitXorAssign.decl: invalid = interface_decl @BitXorAssign [template = constants.%.7] {} +// CHECK:STDOUT: %BitXorAssign.ref: type = name_ref BitXorAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitXor { +// CHECK:STDOUT: %import_ref.1: in BitXor> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @BitXorAssign { +// CHECK:STDOUT: %import_ref.1: in BitXorAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as BitXor { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as BitXorAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/dec.carbon b/toolchain/check/testdata/operators/overloaded/dec.carbon new file mode 100644 index 000000000000..d09e17e1b15f --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/dec.carbon @@ -0,0 +1,158 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from unary_stmt.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Dec { + fn Op[addr self: Self*](); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Dec { + fn Op[addr self: C*](); +} + +fn TestOp() { + var c: C = {}; + --c; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Dec [template] +// CHECK:STDOUT: %.2: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @Dec, [template] +// CHECK:STDOUT: %.4: in Dec> = assoc_entity element0, @Dec.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Dec = %Dec.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Dec.decl: type = interface_decl @Dec [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Dec { +// CHECK:STDOUT: %Self: Dec = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op [template] { +// CHECK:STDOUT: %Self.ref: Dec = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.1: type = facet_type_access %Self.ref [symbolic = %Self] +// CHECK:STDOUT: %.loc5_20: type = converted %Self.ref, %.loc5_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.2: type = ptr_type Self [symbolic = constants.%.2] +// CHECK:STDOUT: %self.loc5_14.1: Self* = param self +// CHECK:STDOUT: %self.loc5_14.3: Self* = bind_name self, %self.loc5_14.1 +// CHECK:STDOUT: %.loc5_9: Self* = addr_pattern %self.loc5_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_28: in Dec> = assoc_entity element0, %Op [template = constants.%.4] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_28 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op[addr @Dec.%self.loc5_14.3: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Dec [template] +// CHECK:STDOUT: %.3: type = ptr_type C [template] +// CHECK:STDOUT: %.4: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.5: = interface_witness (@impl.%Op) [template] +// CHECK:STDOUT: %.6: type = tuple_type () [template] +// CHECK:STDOUT: %.7: type = ptr_type {} [template] +// CHECK:STDOUT: %.8: C = struct_value () [template] +// CHECK:STDOUT: %.9: type = assoc_entity_type @Dec, [template] +// CHECK:STDOUT: %.10: in Dec> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Dec.decl: invalid = interface_decl @Dec [template = constants.%.2] {} +// CHECK:STDOUT: %Dec.ref: type = name_ref Dec, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Dec { +// CHECK:STDOUT: %import_ref.1: in Dec> = import_ref ir1, inst+14, used [template = constants.%.10] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+12, used [template = imports.%Op] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Dec { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc9_21: type = ptr_type C [template = constants.%.3] +// CHECK:STDOUT: %self.loc9_14.1: C* = param self +// CHECK:STDOUT: %self.loc9_14.3: C* = bind_name self, %self.loc9_14.1 +// CHECK:STDOUT: %.loc9_9: C* = addr_pattern %self.loc9_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[addr @impl.%self.loc9_14.3: C*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr %self: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %c.var: ref C = var c +// CHECK:STDOUT: %c: ref C = bind_name c, %c.var +// CHECK:STDOUT: %.loc13_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc13_15.2: init C = class_init (), %c.var [template = constants.%.8] +// CHECK:STDOUT: %.loc13_15.3: init C = converted %.loc13_15.1, %.loc13_15.2 [template = constants.%.8] +// CHECK:STDOUT: assign %c.var, %.loc13_15.3 +// CHECK:STDOUT: %c.ref: ref C = name_ref c, %c +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+12, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Op] +// CHECK:STDOUT: %.loc14_3.1: = bound_method %c.ref, %.1 +// CHECK:STDOUT: %.loc14_5: C* = addr_of %c.ref +// CHECK:STDOUT: %.loc14_3.2: init () = call %.loc14_3.1(%.loc14_5) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/div.carbon b/toolchain/check/testdata/operators/overloaded/div.carbon new file mode 100644 index 000000000000..1de680612d5b --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/div.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Div { + fn Op[self: Self](other: Self) -> Self; +} +interface DivAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Div { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.DivAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a / b; +} + +fn TestAssign(a: C*, b: C) { + *a /= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Div [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Div, [template] +// CHECK:STDOUT: %.3: in Div> = assoc_entity element0, @Div.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @DivAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @DivAssign, [template] +// CHECK:STDOUT: %.7: in DivAssign> = assoc_entity element0, @DivAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Div = %Div.decl +// CHECK:STDOUT: .DivAssign = %DivAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Div.decl: type = interface_decl @Div [template = constants.%.1] {} +// CHECK:STDOUT: %DivAssign.decl: type = interface_decl @DivAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Div { +// CHECK:STDOUT: %Self: Div = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Div = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Div = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Div = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Div> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @DivAssign { +// CHECK:STDOUT: %Self: DivAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: DivAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: DivAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in DivAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Div.%self.loc5_9.2: Self](@Div.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @DivAssign.%self.loc8_14.3: Self*](@DivAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Div [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @DivAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Div, [template] +// CHECK:STDOUT: %.12: in Div> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @DivAssign, [template] +// CHECK:STDOUT: %.14: in DivAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Div.decl: invalid = interface_decl @Div [template = constants.%.2] {} +// CHECK:STDOUT: %Div.ref: type = name_ref Div, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %DivAssign.decl: invalid = interface_decl @DivAssign [template = constants.%.7] {} +// CHECK:STDOUT: %DivAssign.ref: type = name_ref DivAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Div { +// CHECK:STDOUT: %import_ref.1: in Div> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @DivAssign { +// CHECK:STDOUT: %import_ref.1: in DivAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Div { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as DivAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/eq.carbon b/toolchain/check/testdata/operators/overloaded/eq.carbon new file mode 100644 index 000000000000..bcc55e90a6fa --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/eq.carbon @@ -0,0 +1,494 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// --- prelude.carbon + +package Core api; + +interface Eq { + fn Equal[self: Self](other: Self) -> bool; + fn NotEqual[self: Self](other: Self) -> bool; +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Eq { + fn Equal[self: C](other: C) -> bool; + fn NotEqual[self: C](other: C) -> bool; +} + +fn TestEqual(a: C, b: C) -> bool { + return a == b; +} + +fn TestNotEqual(a: C, b: C) -> bool { + return a != b; +} + +// --- fail_no_impl.carbon + +package FailNoImpl api; + +import Core; + +class D {}; + +fn TestEqual(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Eq in type D that does not implement that interface. + // CHECK:STDERR: return a == b; + // CHECK:STDERR: ^~~~~~ + return a == b; +} + +fn TestNotEqual(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Eq in type D that does not implement that interface. + // CHECK:STDERR: return a != b; + // CHECK:STDERR: ^~~~~~ + return a != b; +} + +// --- fail_no_impl_for_args.carbon + +package FailNoImplForArgs api; + +import Core; + +class C {}; +class D {}; + +impl C as Core.Eq { + fn Equal[self: C](other: C) -> bool; + fn NotEqual[self: C](other: C) -> bool; +} + +fn TestRhsBad(a: C, b: D) -> bool { + // CHECK:STDERR: fail_no_impl_for_args.carbon:[[@LINE+6]]:10: ERROR: Cannot implicitly convert from `D` to `C`. + // CHECK:STDERR: return a == b; + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_no_impl_for_args.carbon:[[@LINE-8]]:3: Initializing parameter 1 of function declared here. + // CHECK:STDERR: fn Equal[self: C](other: C) -> bool; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return a == b; +} + +fn TestLhsBad(a: D, b: C) -> bool { + // CHECK:STDERR: fail_no_impl_for_args.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Eq in type D that does not implement that interface. + // CHECK:STDERR: return a != b; + // CHECK:STDERR: ^~~~~~ + return a != b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Eq [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Eq, [template] +// CHECK:STDOUT: %.3: in Eq> = assoc_entity element0, @Eq.%Equal [template] +// CHECK:STDOUT: %.4: in Eq> = assoc_entity element1, @Eq.%NotEqual [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Eq = %Eq.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Eq.decl: type = interface_decl @Eq [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Eq { +// CHECK:STDOUT: %Self: Eq = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Equal: = fn_decl @Equal [template] { +// CHECK:STDOUT: %Self.ref.loc5_18: Eq = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_18.1: type = facet_type_access %Self.ref.loc5_18 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_18.2: type = converted %Self.ref.loc5_18, %.loc5_18.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_12.1: Self = param self +// CHECK:STDOUT: %self.loc5_12.2: Self = bind_name self, %self.loc5_12.1 +// CHECK:STDOUT: %Self.ref.loc5_31: Eq = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_31.1: type = facet_type_access %Self.ref.loc5_31 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_31.2: type = converted %Self.ref.loc5_31, %.loc5_31.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_24.1: Self = param other +// CHECK:STDOUT: %other.loc5_24.2: Self = bind_name other, %other.loc5_24.1 +// CHECK:STDOUT: %return.var.loc5: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_44: in Eq> = assoc_entity element0, %Equal [template = constants.%.3] +// CHECK:STDOUT: %NotEqual: = fn_decl @NotEqual [template] { +// CHECK:STDOUT: %Self.ref.loc6_21: Eq = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc6_21.1: type = facet_type_access %Self.ref.loc6_21 [symbolic = %Self] +// CHECK:STDOUT: %.loc6_21.2: type = converted %Self.ref.loc6_21, %.loc6_21.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc6_15.1: Self = param self +// CHECK:STDOUT: %self.loc6_15.2: Self = bind_name self, %self.loc6_15.1 +// CHECK:STDOUT: %Self.ref.loc6_34: Eq = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc6_34.1: type = facet_type_access %Self.ref.loc6_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc6_34.2: type = converted %Self.ref.loc6_34, %.loc6_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc6_27.1: Self = param other +// CHECK:STDOUT: %other.loc6_27.2: Self = bind_name other, %other.loc6_27.1 +// CHECK:STDOUT: %return.var.loc6: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc6_47: in Eq> = assoc_entity element1, %NotEqual [template = constants.%.4] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Equal = %.loc5_44 +// CHECK:STDOUT: .NotEqual = %.loc6_47 +// CHECK:STDOUT: witness = (%Equal, %NotEqual) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Equal[@Eq.%self.loc5_12.2: Self](@Eq.%other.loc5_24.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEqual[@Eq.%self.loc6_15.2: Self](@Eq.%other.loc6_27.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Eq [template] +// CHECK:STDOUT: %.3: = interface_witness (@impl.%Equal, @impl.%NotEqual) [template] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: type = ptr_type {} [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type @Eq, [template] +// CHECK:STDOUT: %.7: in Eq> = assoc_entity element0, @TestEqual.%import_ref.2 [template] +// CHECK:STDOUT: %.8: in Eq> = assoc_entity element1, @TestNotEqual.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestEqual = %TestEqual +// CHECK:STDOUT: .TestNotEqual = %TestNotEqual +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Eq.decl: invalid = interface_decl @Eq [template = constants.%.2] {} +// CHECK:STDOUT: %Eq.ref: type = name_ref Eq, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestEqual: = fn_decl @TestEqual [template] { +// CHECK:STDOUT: %C.ref.loc13_17: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc13_14.1: C = param a +// CHECK:STDOUT: @TestEqual.%a: C = bind_name a, %a.loc13_14.1 +// CHECK:STDOUT: %C.ref.loc13_23: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc13_20.1: C = param b +// CHECK:STDOUT: @TestEqual.%b: C = bind_name b, %b.loc13_20.1 +// CHECK:STDOUT: %return.var.loc13: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestNotEqual: = fn_decl @TestNotEqual [template] { +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_17.1: C = param a +// CHECK:STDOUT: @TestNotEqual.%a: C = bind_name a, %a.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_23.1: C = param b +// CHECK:STDOUT: @TestNotEqual.%b: C = bind_name b, %b.loc17_23.1 +// CHECK:STDOUT: %return.var.loc17: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Eq { +// CHECK:STDOUT: %import_ref.1: in Eq> = import_ref ir1, inst+17, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: in Eq> = import_ref ir1, inst+31, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+15, used [template = imports.%Equal] +// CHECK:STDOUT: %import_ref.5: = import_ref ir1, inst+30, used [template = imports.%NotEqual] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Equal = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: .NotEqual = %import_ref.3 +// CHECK:STDOUT: witness = (%import_ref.4, %import_ref.5) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Eq { +// CHECK:STDOUT: %Equal: = fn_decl @Equal.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_18: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_12.1: C = param self +// CHECK:STDOUT: %self.loc9_12.2: C = bind_name self, %self.loc9_12.1 +// CHECK:STDOUT: %C.ref.loc9_28: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_21.1: C = param other +// CHECK:STDOUT: %other.loc9_21.2: C = bind_name other, %other.loc9_21.1 +// CHECK:STDOUT: %return.var.loc9: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %NotEqual: = fn_decl @NotEqual.1 [template] { +// CHECK:STDOUT: %C.ref.loc10_21: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc10_15.1: C = param self +// CHECK:STDOUT: %self.loc10_15.2: C = bind_name self, %self.loc10_15.1 +// CHECK:STDOUT: %C.ref.loc10_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc10_24.1: C = param other +// CHECK:STDOUT: %other.loc10_24.2: C = bind_name other, %other.loc10_24.1 +// CHECK:STDOUT: %return.var.loc10: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Equal, %NotEqual) [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Equal = %Equal +// CHECK:STDOUT: .NotEqual = %NotEqual +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Equal.1[@impl.%self.loc9_12.2: C](@impl.%other.loc9_21.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEqual.1[@impl.%self.loc10_15.2: C](@impl.%other.loc10_24.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Equal.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEqual.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestEqual(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Equal] +// CHECK:STDOUT: %.loc14_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc14_12.2: init bool = call %.loc14_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc14_16: bool = value_of_initializer %.loc14_12.2 +// CHECK:STDOUT: %.loc14_12.3: bool = converted %.loc14_12.2, %.loc14_16 +// CHECK:STDOUT: return %.loc14_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestNotEqual(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element1 [template = @impl.%NotEqual] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc18_12.2: init bool = call %.loc18_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc18_16: bool = value_of_initializer %.loc18_12.2 +// CHECK:STDOUT: %.loc18_12.3: bool = converted %.loc18_12.2, %.loc18_16 +// CHECK:STDOUT: return %.loc18_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %.4: type = interface_type @Eq [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type @Eq, [template] +// CHECK:STDOUT: %.6: in Eq> = assoc_entity element0, @TestEqual.%import_ref.2 [template] +// CHECK:STDOUT: %.7: in Eq> = assoc_entity element1, @TestNotEqual.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .TestEqual = %TestEqual +// CHECK:STDOUT: .TestNotEqual = %TestNotEqual +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: %TestEqual: = fn_decl @TestEqual [template] { +// CHECK:STDOUT: %D.ref.loc8_17: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc8_14.1: D = param a +// CHECK:STDOUT: @TestEqual.%a: D = bind_name a, %a.loc8_14.1 +// CHECK:STDOUT: %D.ref.loc8_23: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc8_20.1: D = param b +// CHECK:STDOUT: @TestEqual.%b: D = bind_name b, %b.loc8_20.1 +// CHECK:STDOUT: %return.var.loc8: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestNotEqual: = fn_decl @TestNotEqual [template] { +// CHECK:STDOUT: %D.ref.loc15_20: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc15_17.1: D = param a +// CHECK:STDOUT: @TestNotEqual.%a: D = bind_name a, %a.loc15_17.1 +// CHECK:STDOUT: %D.ref.loc15_26: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc15_23.1: D = param b +// CHECK:STDOUT: @TestNotEqual.%b: D = bind_name b, %b.loc15_23.1 +// CHECK:STDOUT: %return.var.loc15: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Eq { +// CHECK:STDOUT: %import_ref.1: in Eq> = import_ref ir1, inst+17, used [template = constants.%.6] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: in Eq> = import_ref ir1, inst+31, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Equal = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: .NotEqual = %import_ref.3 +// CHECK:STDOUT: witness = (%import_ref.4, %import_ref.5) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestEqual(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %Eq.decl: invalid = interface_decl @Eq [template = constants.%.4] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestNotEqual(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_impl_for_args.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.2: type = interface_type @Eq [template] +// CHECK:STDOUT: %.3: = interface_witness (@impl.%Equal, @impl.%NotEqual) [template] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: type = ptr_type {} [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type @Eq, [template] +// CHECK:STDOUT: %.7: in Eq> = assoc_entity element0, @TestRhsBad.%import_ref.2 [template] +// CHECK:STDOUT: %.8: in Eq> = assoc_entity element1, @TestLhsBad.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .TestRhsBad = %TestRhsBad +// CHECK:STDOUT: .TestLhsBad = %TestLhsBad +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Eq.decl: invalid = interface_decl @Eq [template = constants.%.2] {} +// CHECK:STDOUT: %Eq.ref: type = name_ref Eq, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestRhsBad: = fn_decl @TestRhsBad [template] { +// CHECK:STDOUT: %C.ref.loc14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_15.1: C = param a +// CHECK:STDOUT: @TestRhsBad.%a: C = bind_name a, %a.loc14_15.1 +// CHECK:STDOUT: %D.ref.loc14: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc14_21.1: D = param b +// CHECK:STDOUT: @TestRhsBad.%b: D = bind_name b, %b.loc14_21.1 +// CHECK:STDOUT: %return.var.loc14: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestLhsBad: = fn_decl @TestLhsBad [template] { +// CHECK:STDOUT: %D.ref.loc24: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc24_15.1: D = param a +// CHECK:STDOUT: @TestLhsBad.%a: D = bind_name a, %a.loc24_15.1 +// CHECK:STDOUT: %C.ref.loc24: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc24_21.1: C = param b +// CHECK:STDOUT: @TestLhsBad.%b: C = bind_name b, %b.loc24_21.1 +// CHECK:STDOUT: %return.var.loc24: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Eq { +// CHECK:STDOUT: %import_ref.1: in Eq> = import_ref ir1, inst+17, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: in Eq> = import_ref ir1, inst+31, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+15, used [template = imports.%Equal] +// CHECK:STDOUT: %import_ref.5: = import_ref ir1, inst+30, used [template = imports.%NotEqual] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Equal = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: .NotEqual = %import_ref.3 +// CHECK:STDOUT: witness = (%import_ref.4, %import_ref.5) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Eq { +// CHECK:STDOUT: %Equal: = fn_decl @Equal.1 [template] { +// CHECK:STDOUT: %C.ref.loc10_18: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc10_12.1: C = param self +// CHECK:STDOUT: %self.loc10_12.2: C = bind_name self, %self.loc10_12.1 +// CHECK:STDOUT: %C.ref.loc10_28: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc10_21.1: C = param other +// CHECK:STDOUT: %other.loc10_21.2: C = bind_name other, %other.loc10_21.1 +// CHECK:STDOUT: %return.var.loc10: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %NotEqual: = fn_decl @NotEqual.1 [template] { +// CHECK:STDOUT: %C.ref.loc11_21: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc11_15.1: C = param self +// CHECK:STDOUT: %self.loc11_15.2: C = bind_name self, %self.loc11_15.1 +// CHECK:STDOUT: %C.ref.loc11_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc11_24.1: C = param other +// CHECK:STDOUT: %other.loc11_24.2: C = bind_name other, %other.loc11_24.1 +// CHECK:STDOUT: %return.var.loc11: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Equal, %NotEqual) [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Equal = %Equal +// CHECK:STDOUT: .NotEqual = %NotEqual +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Equal.1[@impl.%self.loc10_12.2: C](@impl.%other.loc10_21.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEqual.1[@impl.%self.loc11_15.2: C](@impl.%other.loc11_24.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Equal.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEqual.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestRhsBad(%a: C, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Equal] +// CHECK:STDOUT: %.loc21_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc21_12.2: init bool = call %.loc21_12.1() +// CHECK:STDOUT: %.loc21_16: bool = value_of_initializer %.loc21_12.2 +// CHECK:STDOUT: %.loc21_12.3: bool = converted %.loc21_12.2, %.loc21_16 +// CHECK:STDOUT: return %.loc21_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestLhsBad(%a: D, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon new file mode 100644 index 000000000000..6def544f25c1 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon @@ -0,0 +1,270 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// --- prelude.carbon + +package Core api; + +interface Inc { + fn Op[addr self: Self*](); +} +interface AddAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- fail_assign_non_ref.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Inc { + fn Op[addr self: C*](); +} +impl C as Core.AddAssign { + fn Op[addr self: C*](other: C); +} + +fn TestIncNonRef(a: C) { + // CHECK:STDERR: fail_assign_non_ref.carbon:[[@LINE+6]]:3: ERROR: `addr self` method cannot be invoked on a value. + // CHECK:STDERR: ++a; + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_assign_non_ref.carbon:[[@LINE-10]]:14: Initializing `addr self` parameter of method declared here. + // CHECK:STDERR: fn Op[addr self: C*](); + // CHECK:STDERR: ^~~~ + ++a; +} + +fn TestAddAssignNonRef(a: C, b: C) { + // CHECK:STDERR: fail_assign_non_ref.carbon:[[@LINE+6]]:5: ERROR: `addr self` method cannot be invoked on a value. + // CHECK:STDERR: a += b; + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_assign_non_ref.carbon:[[@LINE-17]]:14: Initializing `addr self` parameter of method declared here. + // CHECK:STDERR: fn Op[addr self: C*](other: C); + // CHECK:STDERR: ^~~~ + a += b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Inc [template] +// CHECK:STDOUT: %.2: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.4: in Inc> = assoc_entity element0, @Inc.%Op [template] +// CHECK:STDOUT: %.5: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.6: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.7: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.8: in AddAssign> = assoc_entity element0, @AddAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Inc = %Inc.decl +// CHECK:STDOUT: .AddAssign = %AddAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Inc.decl: type = interface_decl @Inc [template = constants.%.1] {} +// CHECK:STDOUT: %AddAssign.decl: type = interface_decl @AddAssign [template = constants.%.5] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %Self: Inc = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref: Inc = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.1: type = facet_type_access %Self.ref [symbolic = %Self] +// CHECK:STDOUT: %.loc5_20: type = converted %Self.ref, %.loc5_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.2: type = ptr_type Self [symbolic = constants.%.2] +// CHECK:STDOUT: %self.loc5_14.1: Self* = param self +// CHECK:STDOUT: %self.loc5_14.3: Self* = bind_name self, %self.loc5_14.1 +// CHECK:STDOUT: %.loc5_9: Self* = addr_pattern %self.loc5_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_28: in Inc> = assoc_entity element0, %Op [template = constants.%.4] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_28 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %Self: AddAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.6] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in AddAssign> = assoc_entity element0, %Op [template = constants.%.8] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[addr @Inc.%self.loc5_14.3: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @AddAssign.%self.loc8_14.3: Self*](@AddAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_assign_non_ref.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Inc [template] +// CHECK:STDOUT: %.3: type = ptr_type C [template] +// CHECK:STDOUT: %.4: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.5: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.6: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.7: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.8: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.9: type = tuple_type () [template] +// CHECK:STDOUT: %.10: type = ptr_type {} [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.12: in Inc> = assoc_entity element0, @TestIncNonRef.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.14: in AddAssign> = assoc_entity element0, @TestAddAssignNonRef.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestIncNonRef = %TestIncNonRef +// CHECK:STDOUT: .TestAddAssignNonRef = %TestAddAssignNonRef +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Inc.decl: invalid = interface_decl @Inc [template = constants.%.2] {} +// CHECK:STDOUT: %Inc.ref: type = name_ref Inc, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc11: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc11: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+16, used [template = constants.%.6] +// CHECK:STDOUT: %AddAssign.decl: invalid = interface_decl @AddAssign [template = constants.%.6] {} +// CHECK:STDOUT: %AddAssign.ref: type = name_ref AddAssign, %import_ref.2 [template = constants.%.6] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestIncNonRef: = fn_decl @TestIncNonRef [template] { +// CHECK:STDOUT: %C.ref.loc15: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc15_18.1: C = param a +// CHECK:STDOUT: @TestIncNonRef.%a: C = bind_name a, %a.loc15_18.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAddAssignNonRef: = fn_decl @TestAddAssignNonRef [template] { +// CHECK:STDOUT: %C.ref.loc25_27: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc25_24.1: C = param a +// CHECK:STDOUT: @TestAddAssignNonRef.%a: C = bind_name a, %a.loc25_24.1 +// CHECK:STDOUT: %C.ref.loc25_33: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc25_30.1: C = param b +// CHECK:STDOUT: @TestAddAssignNonRef.%b: C = bind_name b, %b.loc25_30.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %import_ref.1: in Inc> = import_ref ir1, inst+14, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+12, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %import_ref.1: in AddAssign> = import_ref ir1, inst+34, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+32, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Inc { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc9_21: type = ptr_type C [template = constants.%.3] +// CHECK:STDOUT: %self.loc9_14.1: C* = param self +// CHECK:STDOUT: %self.loc9_14.3: C* = bind_name self, %self.loc9_14.1 +// CHECK:STDOUT: %.loc9_9: C* = addr_pattern %self.loc9_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as AddAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc12_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc12_21: type = ptr_type C [template = constants.%.3] +// CHECK:STDOUT: %self.loc12_14.1: C* = param self +// CHECK:STDOUT: %self.loc12_14.3: C* = bind_name self, %self.loc12_14.1 +// CHECK:STDOUT: %.loc12_9: C* = addr_pattern %self.loc12_14.3 +// CHECK:STDOUT: %C.ref.loc12_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc12_24.1: C = param other +// CHECK:STDOUT: %other.loc12_24.2: C = bind_name other, %other.loc12_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.8] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[addr @impl.1.%self.loc9_14.3: C*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr %self: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc12_14.3: C*](@impl.2.%other.loc12_24.2: C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestIncNonRef(%a: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+12, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc22_3.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc22_3.2: init () = call %.loc22_3.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAddAssignNonRef(%a: C, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+16, used [template = constants.%.6] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+32, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc32_5.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc32_5.2: init () = call %.loc32_5.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon new file mode 100644 index 000000000000..e6ed439945fa --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon @@ -0,0 +1,328 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// --- prelude.carbon + +package Core api; + +interface Negate { + fn Op[self: Self](); +} +interface Add { + fn Op[self: Self](other: Self) -> Self; +} +interface AddAssign { + fn Op[addr self: Self*](other: Self); +} +interface Inc { + fn Op[addr self: Self*](); +} + +// --- fail_no_impl.carbon + +package User api; + +import Core; + +class C {}; + +fn TestUnary(a: C) -> C { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Negate in type C that does not implement that interface. + // CHECK:STDERR: return -a; + // CHECK:STDERR: ^~ + return -a; +} + +fn TestBinary(a: C, b: C) -> C { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Add in type C that does not implement that interface. + // CHECK:STDERR: return a + b; + // CHECK:STDERR: ^~~~~ + return a + b; +} + +fn TestRef(b: C) { + var a: C = {}; + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:3: ERROR: Cannot access member of interface AddAssign in type C that does not implement that interface. + // CHECK:STDERR: a += b; + // CHECK:STDERR: ^~~~~~ + a += b; + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:3: ERROR: Cannot access member of interface Inc in type C that does not implement that interface. + // CHECK:STDERR: ++a; + // CHECK:STDERR: ^~~ + ++a; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Negate [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Negate, [template] +// CHECK:STDOUT: %.3: in Negate> = assoc_entity element0, @Negate.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @Add [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.6: in Add> = assoc_entity element0, @Add.%Op [template] +// CHECK:STDOUT: %.7: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.9: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.10: in AddAssign> = assoc_entity element0, @AddAssign.%Op [template] +// CHECK:STDOUT: %.11: type = interface_type @Inc [template] +// CHECK:STDOUT: %.12: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.13: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.14: in Inc> = assoc_entity element0, @Inc.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Negate = %Negate.decl +// CHECK:STDOUT: .Add = %Add.decl +// CHECK:STDOUT: .AddAssign = %AddAssign.decl +// CHECK:STDOUT: .Inc = %Inc.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Negate.decl: type = interface_decl @Negate [template = constants.%.1] {} +// CHECK:STDOUT: %Add.decl: type = interface_decl @Add [template = constants.%.4] {} +// CHECK:STDOUT: %AddAssign.decl: type = interface_decl @AddAssign [template = constants.%.7] {} +// CHECK:STDOUT: %Inc.decl: type = interface_decl @Inc [template = constants.%.11] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Negate { +// CHECK:STDOUT: %Self: Negate = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref: Negate = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_22: in Negate> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_22 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %Self: Add = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_15: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_15.1: type = facet_type_access %Self.ref.loc8_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_15.2: type = converted %Self.ref.loc8_15, %.loc8_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc8_9.1: Self = param self +// CHECK:STDOUT: %self.loc8_9.2: Self = bind_name self, %self.loc8_9.1 +// CHECK:STDOUT: %Self.ref.loc8_28: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_28.1: type = facet_type_access %Self.ref.loc8_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_28.2: type = converted %Self.ref.loc8_28, %.loc8_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_21.1: Self = param other +// CHECK:STDOUT: %other.loc8_21.2: Self = bind_name other, %other.loc8_21.1 +// CHECK:STDOUT: %Self.ref.loc8_37: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_37.1: type = facet_type_access %Self.ref.loc8_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_37.2: type = converted %Self.ref.loc8_37, %.loc8_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_41: in Add> = assoc_entity element0, %Op [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %Self: AddAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %Self.ref.loc11_20: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc11_24.1: type = facet_type_access %Self.ref.loc11_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc11_20: type = converted %Self.ref.loc11_20, %.loc11_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc11_24.2: type = ptr_type Self [symbolic = constants.%.8] +// CHECK:STDOUT: %self.loc11_14.1: Self* = param self +// CHECK:STDOUT: %self.loc11_14.3: Self* = bind_name self, %self.loc11_14.1 +// CHECK:STDOUT: %.loc11_9: Self* = addr_pattern %self.loc11_14.3 +// CHECK:STDOUT: %Self.ref.loc11_34: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc11_34.1: type = facet_type_access %Self.ref.loc11_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc11_34.2: type = converted %Self.ref.loc11_34, %.loc11_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc11_27.1: Self = param other +// CHECK:STDOUT: %other.loc11_27.2: Self = bind_name other, %other.loc11_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc11_39: in AddAssign> = assoc_entity element0, %Op [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc11_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %Self: Inc = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.4 [template] { +// CHECK:STDOUT: %Self.ref: Inc = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc14_24.1: type = facet_type_access %Self.ref [symbolic = %Self] +// CHECK:STDOUT: %.loc14_20: type = converted %Self.ref, %.loc14_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc14_24.2: type = ptr_type Self [symbolic = constants.%.12] +// CHECK:STDOUT: %self.loc14_14.1: Self* = param self +// CHECK:STDOUT: %self.loc14_14.3: Self* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: Self* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc14_28: in Inc> = assoc_entity element0, %Op [template = constants.%.14] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc14_28 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Negate.%self.loc5_9.2: Self](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[@Add.%self.loc8_9.2: Self](@Add.%other.loc8_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @AddAssign.%self.loc11_14.3: Self*](@AddAssign.%other.loc11_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr @Inc.%self.loc14_14.3: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %.4: type = interface_type @Negate [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type @Negate, [template] +// CHECK:STDOUT: %.6: in Negate> = assoc_entity element0, @TestUnary.%import_ref.2 [template] +// CHECK:STDOUT: %.7: type = interface_type @Add [template] +// CHECK:STDOUT: %.8: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.9: in Add> = assoc_entity element0, @TestBinary.%import_ref.2 [template] +// CHECK:STDOUT: %.10: C = struct_value () [template] +// CHECK:STDOUT: %.11: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.12: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.13: in AddAssign> = assoc_entity element0, @TestRef.%import_ref.2 [template] +// CHECK:STDOUT: %.14: type = interface_type @Inc [template] +// CHECK:STDOUT: %.15: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.16: in Inc> = assoc_entity element0, @TestRef.%import_ref.4 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestUnary = %TestUnary +// CHECK:STDOUT: .TestBinary = %TestBinary +// CHECK:STDOUT: .TestRef = %TestRef +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %TestUnary: = fn_decl @TestUnary [template] { +// CHECK:STDOUT: %C.ref.loc8_17: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc8_14.1: C = param a +// CHECK:STDOUT: @TestUnary.%a: C = bind_name a, %a.loc8_14.1 +// CHECK:STDOUT: %C.ref.loc8_23: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestUnary.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestBinary: = fn_decl @TestBinary [template] { +// CHECK:STDOUT: %C.ref.loc15_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc15_15.1: C = param a +// CHECK:STDOUT: @TestBinary.%a: C = bind_name a, %a.loc15_15.1 +// CHECK:STDOUT: %C.ref.loc15_24: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc15_21.1: C = param b +// CHECK:STDOUT: @TestBinary.%b: C = bind_name b, %b.loc15_21.1 +// CHECK:STDOUT: %C.ref.loc15_30: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestBinary.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestRef: = fn_decl @TestRef [template] { +// CHECK:STDOUT: %C.ref.loc22: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc22_12.1: C = param b +// CHECK:STDOUT: @TestRef.%b: C = bind_name b, %b.loc22_12.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Negate { +// CHECK:STDOUT: %import_ref.1: in Negate> = import_ref ir1, inst+11, used [template = constants.%.6] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %import_ref.1: in Add> = import_ref ir1, inst+32, used [template = constants.%.9] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %import_ref.1: in AddAssign> = import_ref ir1, inst+52, used [template = constants.%.13] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+36, unused +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+50, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %import_ref.1: in Inc> = import_ref ir1, inst+67, used [template = constants.%.16] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+56, unused +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+65, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestUnary(%a: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %Negate.decl: invalid = interface_decl @Negate [template = constants.%.4] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+9, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestBinary(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+13, used [template = constants.%.7] +// CHECK:STDOUT: %Add.decl: invalid = interface_decl @Add [template = constants.%.7] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestRef(%b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %a.var: ref C = var a +// CHECK:STDOUT: %a: ref C = bind_name a, %a.var +// CHECK:STDOUT: %.loc23_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc23_15.2: init C = class_init (), %a.var [template = constants.%.10] +// CHECK:STDOUT: %.loc23_15.3: init C = converted %.loc23_15.1, %.loc23_15.2 [template = constants.%.10] +// CHECK:STDOUT: assign %a.var, %.loc23_15.3 +// CHECK:STDOUT: %a.ref.loc27: ref C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+34, used [template = constants.%.11] +// CHECK:STDOUT: %AddAssign.decl: invalid = interface_decl @AddAssign [template = constants.%.11] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+50, unused +// CHECK:STDOUT: %a.ref.loc31: ref C = name_ref a, %a +// CHECK:STDOUT: %import_ref.3: type = import_ref ir1, inst+54, used [template = constants.%.14] +// CHECK:STDOUT: %Inc.decl: invalid = interface_decl @Inc [template = constants.%.14] {} +// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+65, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon new file mode 100644 index 000000000000..3e98a04b48ce --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon @@ -0,0 +1,301 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// --- prelude.carbon + +package Core api; + +interface Add { + fn Op[self: Self](other: Self) -> Self; +} +interface AddAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- fail_no_impl_for_arg.carbon + +package User api; + +import Core; + +class C {}; +class D {}; + +impl C as Core.Add { + fn Op[self: C](other: C) -> C; +} +impl C as Core.AddAssign { + fn Op[addr self: C*](other: C); +} + +fn Test(a: C, b: D) -> C { + // CHECK:STDERR: fail_no_impl_for_arg.carbon:[[@LINE+6]]:10: ERROR: Cannot implicitly convert from `D` to `C`. + // CHECK:STDERR: return a + b; + // CHECK:STDERR: ^~~~~ + // CHECK:STDERR: fail_no_impl_for_arg.carbon:[[@LINE-10]]:3: Initializing parameter 1 of function declared here. + // CHECK:STDERR: fn Op[self: C](other: C) -> C; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return a + b; +} + +fn TestAssign(b: D) { + var a: C = {}; + // CHECK:STDERR: fail_no_impl_for_arg.carbon:[[@LINE+6]]:3: ERROR: Cannot implicitly convert from `D` to `C`. + // CHECK:STDERR: a += b; + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_no_impl_for_arg.carbon:[[@LINE-18]]:3: Initializing parameter 1 of function declared here. + // CHECK:STDERR: fn Op[addr self: C*](other: C); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + a += b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Add [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.3: in Add> = assoc_entity element0, @Add.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.7: in AddAssign> = assoc_entity element0, @AddAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Add = %Add.decl +// CHECK:STDOUT: .AddAssign = %AddAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Add.decl: type = interface_decl @Add [template = constants.%.1] {} +// CHECK:STDOUT: %AddAssign.decl: type = interface_decl @AddAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %Self: Add = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Add = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Add> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %Self: AddAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: AddAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in AddAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Add.%self.loc5_9.2: Self](@Add.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @AddAssign.%self.loc8_14.3: Self*](@AddAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_impl_for_arg.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.2: type = interface_type @Add [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.6: type = interface_type @AddAssign [template] +// CHECK:STDOUT: %.7: type = ptr_type C [template] +// CHECK:STDOUT: %.8: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.9: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.10: type = assoc_entity_type @Add, [template] +// CHECK:STDOUT: %.11: in Add> = assoc_entity element0, @Test.%import_ref.2 [template] +// CHECK:STDOUT: %.12: C = struct_value () [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @AddAssign, [template] +// CHECK:STDOUT: %.14: in AddAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc9: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Add.decl: invalid = interface_decl @Add [template = constants.%.2] {} +// CHECK:STDOUT: %Add.ref: type = name_ref Add, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc12: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc12: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.6] +// CHECK:STDOUT: %AddAssign.decl: invalid = interface_decl @AddAssign [template = constants.%.6] {} +// CHECK:STDOUT: %AddAssign.ref: type = name_ref AddAssign, %import_ref.2 [template = constants.%.6] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = fn_decl @Test [template] { +// CHECK:STDOUT: %C.ref.loc16_12: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc16_9.1: C = param a +// CHECK:STDOUT: @Test.%a: C = bind_name a, %a.loc16_9.1 +// CHECK:STDOUT: %D.ref.loc16: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc16_15.1: D = param b +// CHECK:STDOUT: @Test.%b: D = bind_name b, %b.loc16_15.1 +// CHECK:STDOUT: %C.ref.loc16_24: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @Test.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %D.ref.loc26: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc26_15.1: D = param b +// CHECK:STDOUT: @TestAssign.%b: D = bind_name b, %b.loc26_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Add { +// CHECK:STDOUT: %import_ref.1: in Add> = import_ref ir1, inst+20, used [template = constants.%.11] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @AddAssign { +// CHECK:STDOUT: %import_ref.1: in AddAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Add { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc10_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc10_9.1: C = param self +// CHECK:STDOUT: %self.loc10_9.2: C = bind_name self, %self.loc10_9.1 +// CHECK:STDOUT: %C.ref.loc10_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc10_18.1: C = param other +// CHECK:STDOUT: %other.loc10_18.2: C = bind_name other, %other.loc10_18.1 +// CHECK:STDOUT: %C.ref.loc10_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as AddAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc13_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc13_21: type = ptr_type C [template = constants.%.7] +// CHECK:STDOUT: %self.loc13_14.1: C* = param self +// CHECK:STDOUT: %self.loc13_14.3: C* = bind_name self, %self.loc13_14.1 +// CHECK:STDOUT: %.loc13_9: C* = addr_pattern %self.loc13_14.3 +// CHECK:STDOUT: %C.ref.loc13_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc13_24.1: C = param other +// CHECK:STDOUT: %other.loc13_24.2: C = bind_name other, %other.loc13_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc10_9.2: C](@impl.1.%other.loc10_18.2: C) -> @impl.1.%return.var: C; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc13_14.3: C*](@impl.2.%other.loc13_24.2: C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Test(%a: C, %b: D) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc23_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc23_12.2: ref C = temporary_storage +// CHECK:STDOUT: %.loc23_12.3: init C = call %.loc23_12.1() +// CHECK:STDOUT: return %.loc23_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%b: D) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %a.var: ref C = var a +// CHECK:STDOUT: %a: ref C = bind_name a, %a.var +// CHECK:STDOUT: %.loc27_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc27_15.2: init C = class_init (), %a.var [template = constants.%.12] +// CHECK:STDOUT: %.loc27_15.3: init C = converted %.loc27_15.1, %.loc27_15.2 [template = constants.%.12] +// CHECK:STDOUT: assign %a.var, %.loc27_15.3 +// CHECK:STDOUT: %a.ref: ref C = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.6] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc34_5.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc34_3: C* = addr_of %a.ref +// CHECK:STDOUT: %.loc34_5.2: init () = call %.loc34_5.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/inc.carbon b/toolchain/check/testdata/operators/overloaded/inc.carbon new file mode 100644 index 000000000000..bf6df03b2ab6 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/inc.carbon @@ -0,0 +1,158 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from unary_stmt.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Inc { + fn Op[addr self: Self*](); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Inc { + fn Op[addr self: C*](); +} + +fn TestOp() { + var c: C = {}; + ++c; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Inc [template] +// CHECK:STDOUT: %.2: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.4: in Inc> = assoc_entity element0, @Inc.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Inc = %Inc.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Inc.decl: type = interface_decl @Inc [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %Self: Inc = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op [template] { +// CHECK:STDOUT: %Self.ref: Inc = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.1: type = facet_type_access %Self.ref [symbolic = %Self] +// CHECK:STDOUT: %.loc5_20: type = converted %Self.ref, %.loc5_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_24.2: type = ptr_type Self [symbolic = constants.%.2] +// CHECK:STDOUT: %self.loc5_14.1: Self* = param self +// CHECK:STDOUT: %self.loc5_14.3: Self* = bind_name self, %self.loc5_14.1 +// CHECK:STDOUT: %.loc5_9: Self* = addr_pattern %self.loc5_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_28: in Inc> = assoc_entity element0, %Op [template = constants.%.4] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_28 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op[addr @Inc.%self.loc5_14.3: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Inc [template] +// CHECK:STDOUT: %.3: type = ptr_type C [template] +// CHECK:STDOUT: %.4: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.5: = interface_witness (@impl.%Op) [template] +// CHECK:STDOUT: %.6: type = tuple_type () [template] +// CHECK:STDOUT: %.7: type = ptr_type {} [template] +// CHECK:STDOUT: %.8: C = struct_value () [template] +// CHECK:STDOUT: %.9: type = assoc_entity_type @Inc, [template] +// CHECK:STDOUT: %.10: in Inc> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Inc.decl: invalid = interface_decl @Inc [template = constants.%.2] {} +// CHECK:STDOUT: %Inc.ref: type = name_ref Inc, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Inc { +// CHECK:STDOUT: %import_ref.1: in Inc> = import_ref ir1, inst+14, used [template = constants.%.10] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+12, used [template = imports.%Op] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Inc { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc9_21: type = ptr_type C [template = constants.%.3] +// CHECK:STDOUT: %self.loc9_14.1: C* = param self +// CHECK:STDOUT: %self.loc9_14.3: C* = bind_name self, %self.loc9_14.1 +// CHECK:STDOUT: %.loc9_9: C* = addr_pattern %self.loc9_14.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[addr @impl.%self.loc9_14.3: C*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr %self: Self*](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %c.var: ref C = var c +// CHECK:STDOUT: %c: ref C = bind_name c, %c.var +// CHECK:STDOUT: %.loc13_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc13_15.2: init C = class_init (), %c.var [template = constants.%.8] +// CHECK:STDOUT: %.loc13_15.3: init C = converted %.loc13_15.1, %.loc13_15.2 [template = constants.%.8] +// CHECK:STDOUT: assign %c.var, %.loc13_15.3 +// CHECK:STDOUT: %c.ref: ref C = name_ref c, %c +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+12, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Op] +// CHECK:STDOUT: %.loc14_3.1: = bound_method %c.ref, %.1 +// CHECK:STDOUT: %.loc14_5: C* = addr_of %c.ref +// CHECK:STDOUT: %.loc14_3.2: init () = call %.loc14_3.1(%.loc14_5) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/left_shift.carbon b/toolchain/check/testdata/operators/overloaded/left_shift.carbon new file mode 100644 index 000000000000..2071d61155ac --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/left_shift.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface LeftShift { + fn Op[self: Self](other: Self) -> Self; +} +interface LeftShiftAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.LeftShift { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.LeftShiftAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a << b; +} + +fn TestAssign(a: C*, b: C) { + *a <<= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @LeftShift [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @LeftShift, [template] +// CHECK:STDOUT: %.3: in LeftShift> = assoc_entity element0, @LeftShift.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @LeftShiftAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @LeftShiftAssign, [template] +// CHECK:STDOUT: %.7: in LeftShiftAssign> = assoc_entity element0, @LeftShiftAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .LeftShift = %LeftShift.decl +// CHECK:STDOUT: .LeftShiftAssign = %LeftShiftAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %LeftShift.decl: type = interface_decl @LeftShift [template = constants.%.1] {} +// CHECK:STDOUT: %LeftShiftAssign.decl: type = interface_decl @LeftShiftAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @LeftShift { +// CHECK:STDOUT: %Self: LeftShift = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: LeftShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: LeftShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: LeftShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in LeftShift> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @LeftShiftAssign { +// CHECK:STDOUT: %Self: LeftShiftAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: LeftShiftAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: LeftShiftAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in LeftShiftAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@LeftShift.%self.loc5_9.2: Self](@LeftShift.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @LeftShiftAssign.%self.loc8_14.3: Self*](@LeftShiftAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @LeftShift [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @LeftShiftAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @LeftShift, [template] +// CHECK:STDOUT: %.12: in LeftShift> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @LeftShiftAssign, [template] +// CHECK:STDOUT: %.14: in LeftShiftAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %LeftShift.decl: invalid = interface_decl @LeftShift [template = constants.%.2] {} +// CHECK:STDOUT: %LeftShift.ref: type = name_ref LeftShift, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %LeftShiftAssign.decl: invalid = interface_decl @LeftShiftAssign [template = constants.%.7] {} +// CHECK:STDOUT: %LeftShiftAssign.ref: type = name_ref LeftShiftAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @LeftShift { +// CHECK:STDOUT: %import_ref.1: in LeftShift> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @LeftShiftAssign { +// CHECK:STDOUT: %import_ref.1: in LeftShiftAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as LeftShift { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as LeftShiftAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/make_tests.sh b/toolchain/check/testdata/operators/overloaded/make_tests.sh new file mode 100755 index 000000000000..5f8e2d7669cd --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/make_tests.sh @@ -0,0 +1,43 @@ +#! /bin/bash +# Part of the Carbon Language project, under the Apache License v2.0 with LLVM +# Exceptions. See /LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# TODO: This is a short-term script to regenerate the test files for operators +# while we're in a period where we expect the tests to have substantial churn. +# Once the implementation of overloaded operators has stabilized, this script +# and its template files should be removed. + +make_test() { + HEADER="// This file was generated from $4. Run make_tests.sh to regenerate." + sed "s,INTERFACE,$1,g; s,OP,$2,g; s,HEADER,$HEADER," "$4" > "$3.carbon" +} + +make_unary_op_test() { + make_test "$1" "$2" "$3" unary_op.carbon.tmpl +} + +make_unary_stmt_test() { + make_test "$1" "$2" "$3" unary_stmt.carbon.tmpl +} + +make_binary_op_test() { + make_test "$1" "$2" "$3" binary_op.carbon.tmpl +} + +make_unary_op_test BitComplement '^' bit_complement +make_unary_op_test Negate '-' negate + +make_unary_stmt_test Dec '--' dec +make_unary_stmt_test Inc '++' inc + +make_binary_op_test Add '+' add +make_binary_op_test BitAnd '\&' bit_and +make_binary_op_test BitOr '|' bit_or +make_binary_op_test BitXor '^' bit_xor +make_binary_op_test Div '/' div +make_binary_op_test LeftShift '<<' left_shift +make_binary_op_test Mod '%' mod +make_binary_op_test Mul '*' mul +make_binary_op_test RightShift '>>' right_shift +make_binary_op_test Sub '-' sub diff --git a/toolchain/check/testdata/operators/overloaded/mod.carbon b/toolchain/check/testdata/operators/overloaded/mod.carbon new file mode 100644 index 000000000000..c08914276c26 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/mod.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Mod { + fn Op[self: Self](other: Self) -> Self; +} +interface ModAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Mod { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.ModAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a % b; +} + +fn TestAssign(a: C*, b: C) { + *a %= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Mod [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Mod, [template] +// CHECK:STDOUT: %.3: in Mod> = assoc_entity element0, @Mod.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @ModAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @ModAssign, [template] +// CHECK:STDOUT: %.7: in ModAssign> = assoc_entity element0, @ModAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Mod = %Mod.decl +// CHECK:STDOUT: .ModAssign = %ModAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Mod.decl: type = interface_decl @Mod [template = constants.%.1] {} +// CHECK:STDOUT: %ModAssign.decl: type = interface_decl @ModAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Mod { +// CHECK:STDOUT: %Self: Mod = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Mod = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Mod = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Mod = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Mod> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @ModAssign { +// CHECK:STDOUT: %Self: ModAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: ModAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: ModAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in ModAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Mod.%self.loc5_9.2: Self](@Mod.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @ModAssign.%self.loc8_14.3: Self*](@ModAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Mod [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @ModAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Mod, [template] +// CHECK:STDOUT: %.12: in Mod> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @ModAssign, [template] +// CHECK:STDOUT: %.14: in ModAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Mod.decl: invalid = interface_decl @Mod [template = constants.%.2] {} +// CHECK:STDOUT: %Mod.ref: type = name_ref Mod, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %ModAssign.decl: invalid = interface_decl @ModAssign [template = constants.%.7] {} +// CHECK:STDOUT: %ModAssign.ref: type = name_ref ModAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Mod { +// CHECK:STDOUT: %import_ref.1: in Mod> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @ModAssign { +// CHECK:STDOUT: %import_ref.1: in ModAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Mod { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as ModAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/mul.carbon b/toolchain/check/testdata/operators/overloaded/mul.carbon new file mode 100644 index 000000000000..c5018912cba0 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/mul.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Mul { + fn Op[self: Self](other: Self) -> Self; +} +interface MulAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Mul { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.MulAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a * b; +} + +fn TestAssign(a: C*, b: C) { + *a *= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Mul [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Mul, [template] +// CHECK:STDOUT: %.3: in Mul> = assoc_entity element0, @Mul.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @MulAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @MulAssign, [template] +// CHECK:STDOUT: %.7: in MulAssign> = assoc_entity element0, @MulAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Mul = %Mul.decl +// CHECK:STDOUT: .MulAssign = %MulAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Mul.decl: type = interface_decl @Mul [template = constants.%.1] {} +// CHECK:STDOUT: %MulAssign.decl: type = interface_decl @MulAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Mul { +// CHECK:STDOUT: %Self: Mul = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Mul = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Mul = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Mul = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Mul> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @MulAssign { +// CHECK:STDOUT: %Self: MulAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: MulAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: MulAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in MulAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Mul.%self.loc5_9.2: Self](@Mul.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @MulAssign.%self.loc8_14.3: Self*](@MulAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Mul [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @MulAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Mul, [template] +// CHECK:STDOUT: %.12: in Mul> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @MulAssign, [template] +// CHECK:STDOUT: %.14: in MulAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Mul.decl: invalid = interface_decl @Mul [template = constants.%.2] {} +// CHECK:STDOUT: %Mul.ref: type = name_ref Mul, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %MulAssign.decl: invalid = interface_decl @MulAssign [template = constants.%.7] {} +// CHECK:STDOUT: %MulAssign.ref: type = name_ref MulAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Mul { +// CHECK:STDOUT: %import_ref.1: in Mul> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @MulAssign { +// CHECK:STDOUT: %import_ref.1: in MulAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Mul { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as MulAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/negate.carbon b/toolchain/check/testdata/operators/overloaded/negate.carbon new file mode 100644 index 000000000000..4301e8a96d32 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/negate.carbon @@ -0,0 +1,163 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from unary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Negate { + fn Op[self: Self]() -> Self; +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Negate { + fn Op[self: C]() -> C { + return {}; + } +} + +fn TestOp(a: C) -> C { + return -a; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Negate [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Negate, [template] +// CHECK:STDOUT: %.3: in Negate> = assoc_entity element0, @Negate.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Negate = %Negate.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Negate.decl: type = interface_decl @Negate [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Negate { +// CHECK:STDOUT: %Self: Negate = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Negate = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_26: Negate = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_26.1: type = facet_type_access %Self.ref.loc5_26 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_26.2: type = converted %Self.ref.loc5_26, %.loc5_26.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_30: in Negate> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_30 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op[@Negate.%self.loc5_9.2: Self]() -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Negate [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.%Op) [template] +// CHECK:STDOUT: %.7: type = assoc_entity_type @Negate, [template] +// CHECK:STDOUT: %.8: in Negate> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Negate.decl: invalid = interface_decl @Negate [template = constants.%.2] {} +// CHECK:STDOUT: %Negate.ref: type = name_ref Negate, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc14_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc14_11.1 +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Negate { +// CHECK:STDOUT: %import_ref.1: in Negate> = import_ref ir1, inst+15, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+13, used [template = imports.%Op] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Negate { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_23: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.%self.loc9_9.2: C]() -> @impl.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self]() -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Op] +// CHECK:STDOUT: %.loc15_10.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc14: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc15_10.2: init C = call %.loc15_10.1(%a.ref) to %.loc14 +// CHECK:STDOUT: return %.loc15_10.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/ordered.carbon b/toolchain/check/testdata/operators/overloaded/ordered.carbon new file mode 100644 index 000000000000..e158a533ab4c --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/ordered.carbon @@ -0,0 +1,521 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// --- prelude.carbon + +package Core api; + +interface Ordered { + // TODO: fn Compare + fn Less[self: Self](other: Self) -> bool; + fn LessOrEquivalent[self: Self](other: Self) -> bool; + fn Greater[self: Self](other: Self) -> bool; + fn GreaterOrEquivalent[self: Self](other: Self) -> bool; +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Ordered { + fn Less[self: C](other: C) -> bool; + fn LessOrEquivalent[self: C](other: C) -> bool; + fn Greater[self: C](other: C) -> bool; + fn GreaterOrEquivalent[self: C](other: C) -> bool; +} + +fn TestLess(a: C, b: C) -> bool { + return a < b; +} + +fn TestLessEqual(a: C, b: C) -> bool { + return a <= b; +} + +fn TestGreater(a: C, b: C) -> bool { + return a > b; +} + +fn TestGreaterEqual(a: C, b: C) -> bool { + return a >= b; +} + +// --- fail_no_impl.carbon + +package FailNoImpl api; + +import Core; + +class D {}; + +fn TestLess(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Ordered in type D that does not implement that interface. + // CHECK:STDERR: return a < b; + // CHECK:STDERR: ^~~~~ + return a < b; +} + +fn TestLessEqual(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Ordered in type D that does not implement that interface. + // CHECK:STDERR: return a <= b; + // CHECK:STDERR: ^~~~~~ + return a <= b; +} + +fn TestGreater(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Ordered in type D that does not implement that interface. + // CHECK:STDERR: return a > b; + // CHECK:STDERR: ^~~~~ + return a > b; +} + +fn TestGreaterEqual(a: D, b: D) -> bool { + // CHECK:STDERR: fail_no_impl.carbon:[[@LINE+3]]:10: ERROR: Cannot access member of interface Ordered in type D that does not implement that interface. + // CHECK:STDERR: return a >= b; + // CHECK:STDERR: ^~~~~~ + return a >= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Ordered [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Ordered, [template] +// CHECK:STDOUT: %.3: in Ordered> = assoc_entity element0, @Ordered.%Less [template] +// CHECK:STDOUT: %.4: in Ordered> = assoc_entity element1, @Ordered.%LessOrEquivalent [template] +// CHECK:STDOUT: %.5: in Ordered> = assoc_entity element2, @Ordered.%Greater [template] +// CHECK:STDOUT: %.6: in Ordered> = assoc_entity element3, @Ordered.%GreaterOrEquivalent [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Ordered = %Ordered.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Ordered.decl: type = interface_decl @Ordered [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Ordered { +// CHECK:STDOUT: %Self: Ordered = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Less: = fn_decl @Less [template] { +// CHECK:STDOUT: %Self.ref.loc6_17: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc6_17.1: type = facet_type_access %Self.ref.loc6_17 [symbolic = %Self] +// CHECK:STDOUT: %.loc6_17.2: type = converted %Self.ref.loc6_17, %.loc6_17.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc6_11.1: Self = param self +// CHECK:STDOUT: %self.loc6_11.2: Self = bind_name self, %self.loc6_11.1 +// CHECK:STDOUT: %Self.ref.loc6_30: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc6_30.1: type = facet_type_access %Self.ref.loc6_30 [symbolic = %Self] +// CHECK:STDOUT: %.loc6_30.2: type = converted %Self.ref.loc6_30, %.loc6_30.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc6_23.1: Self = param other +// CHECK:STDOUT: %other.loc6_23.2: Self = bind_name other, %other.loc6_23.1 +// CHECK:STDOUT: %return.var.loc6: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc6_43: in Ordered> = assoc_entity element0, %Less [template = constants.%.3] +// CHECK:STDOUT: %LessOrEquivalent: = fn_decl @LessOrEquivalent [template] { +// CHECK:STDOUT: %Self.ref.loc7_29: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc7_29.1: type = facet_type_access %Self.ref.loc7_29 [symbolic = %Self] +// CHECK:STDOUT: %.loc7_29.2: type = converted %Self.ref.loc7_29, %.loc7_29.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc7_23.1: Self = param self +// CHECK:STDOUT: %self.loc7_23.2: Self = bind_name self, %self.loc7_23.1 +// CHECK:STDOUT: %Self.ref.loc7_42: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc7_42.1: type = facet_type_access %Self.ref.loc7_42 [symbolic = %Self] +// CHECK:STDOUT: %.loc7_42.2: type = converted %Self.ref.loc7_42, %.loc7_42.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc7_35.1: Self = param other +// CHECK:STDOUT: %other.loc7_35.2: Self = bind_name other, %other.loc7_35.1 +// CHECK:STDOUT: %return.var.loc7: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc7_55: in Ordered> = assoc_entity element1, %LessOrEquivalent [template = constants.%.4] +// CHECK:STDOUT: %Greater: = fn_decl @Greater [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20.2: type = converted %Self.ref.loc8_20, %.loc8_20.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc8_14.1: Self = param self +// CHECK:STDOUT: %self.loc8_14.2: Self = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %Self.ref.loc8_33: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_33.1: type = facet_type_access %Self.ref.loc8_33 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_33.2: type = converted %Self.ref.loc8_33, %.loc8_33.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_26.1: Self = param other +// CHECK:STDOUT: %other.loc8_26.2: Self = bind_name other, %other.loc8_26.1 +// CHECK:STDOUT: %return.var.loc8: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_46: in Ordered> = assoc_entity element2, %Greater [template = constants.%.5] +// CHECK:STDOUT: %GreaterOrEquivalent: = fn_decl @GreaterOrEquivalent [template] { +// CHECK:STDOUT: %Self.ref.loc9_32: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc9_32.1: type = facet_type_access %Self.ref.loc9_32 [symbolic = %Self] +// CHECK:STDOUT: %.loc9_32.2: type = converted %Self.ref.loc9_32, %.loc9_32.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc9_26.1: Self = param self +// CHECK:STDOUT: %self.loc9_26.2: Self = bind_name self, %self.loc9_26.1 +// CHECK:STDOUT: %Self.ref.loc9_45: Ordered = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc9_45.1: type = facet_type_access %Self.ref.loc9_45 [symbolic = %Self] +// CHECK:STDOUT: %.loc9_45.2: type = converted %Self.ref.loc9_45, %.loc9_45.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc9_38.1: Self = param other +// CHECK:STDOUT: %other.loc9_38.2: Self = bind_name other, %other.loc9_38.1 +// CHECK:STDOUT: %return.var.loc9: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc9_58: in Ordered> = assoc_entity element3, %GreaterOrEquivalent [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Less = %.loc6_43 +// CHECK:STDOUT: .LessOrEquivalent = %.loc7_55 +// CHECK:STDOUT: .Greater = %.loc8_46 +// CHECK:STDOUT: .GreaterOrEquivalent = %.loc9_58 +// CHECK:STDOUT: witness = (%Less, %LessOrEquivalent, %Greater, %GreaterOrEquivalent) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Less[@Ordered.%self.loc6_11.2: Self](@Ordered.%other.loc6_23.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @LessOrEquivalent[@Ordered.%self.loc7_23.2: Self](@Ordered.%other.loc7_35.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Greater[@Ordered.%self.loc8_14.2: Self](@Ordered.%other.loc8_26.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @GreaterOrEquivalent[@Ordered.%self.loc9_26.2: Self](@Ordered.%other.loc9_38.2: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Ordered [template] +// CHECK:STDOUT: %.3: = interface_witness (@impl.%Less, @impl.%LessOrEquivalent, @impl.%Greater, @impl.%GreaterOrEquivalent) [template] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: type = ptr_type {} [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type @Ordered, [template] +// CHECK:STDOUT: %.7: in Ordered> = assoc_entity element0, @TestLess.%import_ref.2 [template] +// CHECK:STDOUT: %.8: in Ordered> = assoc_entity element1, @TestLessEqual.%import_ref.2 [template] +// CHECK:STDOUT: %.9: in Ordered> = assoc_entity element2, @TestGreater.%import_ref.2 [template] +// CHECK:STDOUT: %.10: in Ordered> = assoc_entity element3, @TestGreaterEqual.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestLess = %TestLess +// CHECK:STDOUT: .TestLessEqual = %TestLessEqual +// CHECK:STDOUT: .TestGreater = %TestGreater +// CHECK:STDOUT: .TestGreaterEqual = %TestGreaterEqual +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Ordered.decl: invalid = interface_decl @Ordered [template = constants.%.2] {} +// CHECK:STDOUT: %Ordered.ref: type = name_ref Ordered, %import_ref [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestLess: = fn_decl @TestLess [template] { +// CHECK:STDOUT: %C.ref.loc15_16: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc15_13.1: C = param a +// CHECK:STDOUT: @TestLess.%a: C = bind_name a, %a.loc15_13.1 +// CHECK:STDOUT: %C.ref.loc15_22: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc15_19.1: C = param b +// CHECK:STDOUT: @TestLess.%b: C = bind_name b, %b.loc15_19.1 +// CHECK:STDOUT: %return.var.loc15: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestLessEqual: = fn_decl @TestLessEqual [template] { +// CHECK:STDOUT: %C.ref.loc19_21: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc19_18.1: C = param a +// CHECK:STDOUT: @TestLessEqual.%a: C = bind_name a, %a.loc19_18.1 +// CHECK:STDOUT: %C.ref.loc19_27: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc19_24.1: C = param b +// CHECK:STDOUT: @TestLessEqual.%b: C = bind_name b, %b.loc19_24.1 +// CHECK:STDOUT: %return.var.loc19: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestGreater: = fn_decl @TestGreater [template] { +// CHECK:STDOUT: %C.ref.loc23_19: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc23_16.1: C = param a +// CHECK:STDOUT: @TestGreater.%a: C = bind_name a, %a.loc23_16.1 +// CHECK:STDOUT: %C.ref.loc23_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc23_22.1: C = param b +// CHECK:STDOUT: @TestGreater.%b: C = bind_name b, %b.loc23_22.1 +// CHECK:STDOUT: %return.var.loc23: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestGreaterEqual: = fn_decl @TestGreaterEqual [template] { +// CHECK:STDOUT: %C.ref.loc27_24: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc27_21.1: C = param a +// CHECK:STDOUT: @TestGreaterEqual.%a: C = bind_name a, %a.loc27_21.1 +// CHECK:STDOUT: %C.ref.loc27_30: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc27_27.1: C = param b +// CHECK:STDOUT: @TestGreaterEqual.%b: C = bind_name b, %b.loc27_27.1 +// CHECK:STDOUT: %return.var.loc27: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Ordered { +// CHECK:STDOUT: %import_ref.1: in Ordered> = import_ref ir1, inst+17, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: in Ordered> = import_ref ir1, inst+31, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.4: in Ordered> = import_ref ir1, inst+59, used [template = constants.%.10] +// CHECK:STDOUT: %import_ref.5: in Ordered> = import_ref ir1, inst+45, used [template = constants.%.9] +// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+15, used [template = imports.%Less] +// CHECK:STDOUT: %import_ref.7: = import_ref ir1, inst+30, used [template = imports.%LessOrEquivalent] +// CHECK:STDOUT: %import_ref.8: = import_ref ir1, inst+44, used [template = imports.%Greater] +// CHECK:STDOUT: %import_ref.9: = import_ref ir1, inst+58, used [template = imports.%GreaterOrEquivalent] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Less = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: .LessOrEquivalent = %import_ref.3 +// CHECK:STDOUT: .GreaterOrEquivalent = %import_ref.4 +// CHECK:STDOUT: .Greater = %import_ref.5 +// CHECK:STDOUT: witness = (%import_ref.6, %import_ref.7, %import_ref.8, %import_ref.9) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: C as Ordered { +// CHECK:STDOUT: %Less: = fn_decl @Less.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_17: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_11.1: C = param self +// CHECK:STDOUT: %self.loc9_11.2: C = bind_name self, %self.loc9_11.1 +// CHECK:STDOUT: %C.ref.loc9_27: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_20.1: C = param other +// CHECK:STDOUT: %other.loc9_20.2: C = bind_name other, %other.loc9_20.1 +// CHECK:STDOUT: %return.var.loc9: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %LessOrEquivalent: = fn_decl @LessOrEquivalent.1 [template] { +// CHECK:STDOUT: %C.ref.loc10_29: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc10_23.1: C = param self +// CHECK:STDOUT: %self.loc10_23.2: C = bind_name self, %self.loc10_23.1 +// CHECK:STDOUT: %C.ref.loc10_39: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc10_32.1: C = param other +// CHECK:STDOUT: %other.loc10_32.2: C = bind_name other, %other.loc10_32.1 +// CHECK:STDOUT: %return.var.loc10: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %Greater: = fn_decl @Greater.1 [template] { +// CHECK:STDOUT: %C.ref.loc11_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc11_14.1: C = param self +// CHECK:STDOUT: %self.loc11_14.2: C = bind_name self, %self.loc11_14.1 +// CHECK:STDOUT: %C.ref.loc11_30: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc11_23.1: C = param other +// CHECK:STDOUT: %other.loc11_23.2: C = bind_name other, %other.loc11_23.1 +// CHECK:STDOUT: %return.var.loc11: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %GreaterOrEquivalent: = fn_decl @GreaterOrEquivalent.1 [template] { +// CHECK:STDOUT: %C.ref.loc12_32: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc12_26.1: C = param self +// CHECK:STDOUT: %self.loc12_26.2: C = bind_name self, %self.loc12_26.1 +// CHECK:STDOUT: %C.ref.loc12_42: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc12_35.1: C = param other +// CHECK:STDOUT: %other.loc12_35.2: C = bind_name other, %other.loc12_35.1 +// CHECK:STDOUT: %return.var.loc12: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Less, %LessOrEquivalent, %Greater, %GreaterOrEquivalent) [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Less = %Less +// CHECK:STDOUT: .LessOrEquivalent = %LessOrEquivalent +// CHECK:STDOUT: .Greater = %Greater +// CHECK:STDOUT: .GreaterOrEquivalent = %GreaterOrEquivalent +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Less.1[@impl.%self.loc9_11.2: C](@impl.%other.loc9_20.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @LessOrEquivalent.1[@impl.%self.loc10_23.2: C](@impl.%other.loc10_32.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Greater.1[@impl.%self.loc11_14.2: C](@impl.%other.loc11_23.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @GreaterOrEquivalent.1[@impl.%self.loc12_26.2: C](@impl.%other.loc12_35.2: C) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Less.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @LessOrEquivalent.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Greater.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @GreaterOrEquivalent.2[%self: Self](%other: Self) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestLess(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element0 [template = @impl.%Less] +// CHECK:STDOUT: %.loc16_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc16_12.2: init bool = call %.loc16_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc16_15: bool = value_of_initializer %.loc16_12.2 +// CHECK:STDOUT: %.loc16_12.3: bool = converted %.loc16_12.2, %.loc16_15 +// CHECK:STDOUT: return %.loc16_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestLessEqual(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element1 [template = @impl.%LessOrEquivalent] +// CHECK:STDOUT: %.loc20_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc20_12.2: init bool = call %.loc20_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc20_16: bool = value_of_initializer %.loc20_12.2 +// CHECK:STDOUT: %.loc20_12.3: bool = converted %.loc20_12.2, %.loc20_16 +// CHECK:STDOUT: return %.loc20_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestGreater(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+44, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element2 [template = @impl.%Greater] +// CHECK:STDOUT: %.loc24_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc24_12.2: init bool = call %.loc24_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc24_15: bool = value_of_initializer %.loc24_12.2 +// CHECK:STDOUT: %.loc24_12.3: bool = converted %.loc24_12.2, %.loc24_15 +// CHECK:STDOUT: return %.loc24_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestGreaterEqual(%a: C, %b: C) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+58, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.%.1, element3 [template = @impl.%GreaterOrEquivalent] +// CHECK:STDOUT: %.loc28_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc28_12.2: init bool = call %.loc28_12.1(%a.ref, %b.ref) +// CHECK:STDOUT: %.loc28_16: bool = value_of_initializer %.loc28_12.2 +// CHECK:STDOUT: %.loc28_12.3: bool = converted %.loc28_12.2, %.loc28_16 +// CHECK:STDOUT: return %.loc28_12.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %.4: type = interface_type @Ordered [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type @Ordered, [template] +// CHECK:STDOUT: %.6: in Ordered> = assoc_entity element0, @TestLess.%import_ref.2 [template] +// CHECK:STDOUT: %.7: in Ordered> = assoc_entity element1, @TestLessEqual.%import_ref.2 [template] +// CHECK:STDOUT: %.8: in Ordered> = assoc_entity element2, @TestGreater.%import_ref.2 [template] +// CHECK:STDOUT: %.9: in Ordered> = assoc_entity element3, @TestGreaterEqual.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: .TestLess = %TestLess +// CHECK:STDOUT: .TestLessEqual = %TestLessEqual +// CHECK:STDOUT: .TestGreater = %TestGreater +// CHECK:STDOUT: .TestGreaterEqual = %TestGreaterEqual +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: %TestLess: = fn_decl @TestLess [template] { +// CHECK:STDOUT: %D.ref.loc8_16: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc8_13.1: D = param a +// CHECK:STDOUT: @TestLess.%a: D = bind_name a, %a.loc8_13.1 +// CHECK:STDOUT: %D.ref.loc8_22: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc8_19.1: D = param b +// CHECK:STDOUT: @TestLess.%b: D = bind_name b, %b.loc8_19.1 +// CHECK:STDOUT: %return.var.loc8: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestLessEqual: = fn_decl @TestLessEqual [template] { +// CHECK:STDOUT: %D.ref.loc15_21: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc15_18.1: D = param a +// CHECK:STDOUT: @TestLessEqual.%a: D = bind_name a, %a.loc15_18.1 +// CHECK:STDOUT: %D.ref.loc15_27: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc15_24.1: D = param b +// CHECK:STDOUT: @TestLessEqual.%b: D = bind_name b, %b.loc15_24.1 +// CHECK:STDOUT: %return.var.loc15: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestGreater: = fn_decl @TestGreater [template] { +// CHECK:STDOUT: %D.ref.loc22_19: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc22_16.1: D = param a +// CHECK:STDOUT: @TestGreater.%a: D = bind_name a, %a.loc22_16.1 +// CHECK:STDOUT: %D.ref.loc22_25: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc22_22.1: D = param b +// CHECK:STDOUT: @TestGreater.%b: D = bind_name b, %b.loc22_22.1 +// CHECK:STDOUT: %return.var.loc22: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestGreaterEqual: = fn_decl @TestGreaterEqual [template] { +// CHECK:STDOUT: %D.ref.loc29_24: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %a.loc29_21.1: D = param a +// CHECK:STDOUT: @TestGreaterEqual.%a: D = bind_name a, %a.loc29_21.1 +// CHECK:STDOUT: %D.ref.loc29_30: type = name_ref D, %D.decl [template = constants.%D] +// CHECK:STDOUT: %b.loc29_27.1: D = param b +// CHECK:STDOUT: @TestGreaterEqual.%b: D = bind_name b, %b.loc29_27.1 +// CHECK:STDOUT: %return.var.loc29: ref bool = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Ordered { +// CHECK:STDOUT: %import_ref.1: in Ordered> = import_ref ir1, inst+17, used [template = constants.%.6] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: in Ordered> = import_ref ir1, inst+31, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.4: in Ordered> = import_ref ir1, inst+59, used [template = constants.%.9] +// CHECK:STDOUT: %import_ref.5: in Ordered> = import_ref ir1, inst+45, used [template = constants.%.8] +// CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: %import_ref.7 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: %import_ref.8 = import_ref ir1, inst+44, unused +// CHECK:STDOUT: %import_ref.9 = import_ref ir1, inst+58, unused +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Less = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: .LessOrEquivalent = %import_ref.3 +// CHECK:STDOUT: .GreaterOrEquivalent = %import_ref.4 +// CHECK:STDOUT: .Greater = %import_ref.5 +// CHECK:STDOUT: witness = (%import_ref.6, %import_ref.7, %import_ref.8, %import_ref.9) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestLess(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %Ordered.decl: invalid = interface_decl @Ordered [template = constants.%.4] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+15, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestLessEqual(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+30, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestGreater(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+44, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestGreaterEqual(%a: D, %b: D) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: D = name_ref a, %a +// CHECK:STDOUT: %b.ref: D = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.4] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+58, unused +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/right_shift.carbon b/toolchain/check/testdata/operators/overloaded/right_shift.carbon new file mode 100644 index 000000000000..33a161daa6b1 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/right_shift.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface RightShift { + fn Op[self: Self](other: Self) -> Self; +} +interface RightShiftAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.RightShift { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.RightShiftAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a >> b; +} + +fn TestAssign(a: C*, b: C) { + *a >>= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @RightShift [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @RightShift, [template] +// CHECK:STDOUT: %.3: in RightShift> = assoc_entity element0, @RightShift.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @RightShiftAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @RightShiftAssign, [template] +// CHECK:STDOUT: %.7: in RightShiftAssign> = assoc_entity element0, @RightShiftAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .RightShift = %RightShift.decl +// CHECK:STDOUT: .RightShiftAssign = %RightShiftAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %RightShift.decl: type = interface_decl @RightShift [template = constants.%.1] {} +// CHECK:STDOUT: %RightShiftAssign.decl: type = interface_decl @RightShiftAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @RightShift { +// CHECK:STDOUT: %Self: RightShift = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: RightShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: RightShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: RightShift = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in RightShift> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @RightShiftAssign { +// CHECK:STDOUT: %Self: RightShiftAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: RightShiftAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: RightShiftAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in RightShiftAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@RightShift.%self.loc5_9.2: Self](@RightShift.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @RightShiftAssign.%self.loc8_14.3: Self*](@RightShiftAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @RightShift [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @RightShiftAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @RightShift, [template] +// CHECK:STDOUT: %.12: in RightShift> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @RightShiftAssign, [template] +// CHECK:STDOUT: %.14: in RightShiftAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %RightShift.decl: invalid = interface_decl @RightShift [template = constants.%.2] {} +// CHECK:STDOUT: %RightShift.ref: type = name_ref RightShift, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %RightShiftAssign.decl: invalid = interface_decl @RightShiftAssign [template = constants.%.7] {} +// CHECK:STDOUT: %RightShiftAssign.ref: type = name_ref RightShiftAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @RightShift { +// CHECK:STDOUT: %import_ref.1: in RightShift> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @RightShiftAssign { +// CHECK:STDOUT: %import_ref.1: in RightShiftAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as RightShift { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as RightShiftAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/sub.carbon b/toolchain/check/testdata/operators/overloaded/sub.carbon new file mode 100644 index 000000000000..a9bf34490889 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/sub.carbon @@ -0,0 +1,290 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +// This file was generated from binary_op.carbon.tmpl. Run make_tests.sh to regenerate. + +// --- prelude.carbon + +package Core api; + +interface Sub { + fn Op[self: Self](other: Self) -> Self; +} +interface SubAssign { + fn Op[addr self: Self*](other: Self); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.Sub { + fn Op[self: C](other: C) -> C { + return {}; + } +} +impl C as Core.SubAssign { + fn Op[addr self: C*](other: C) {} +} + +fn TestOp(a: C, b: C) -> C { + return a - b; +} + +fn TestAssign(a: C*, b: C) { + *a -= b; +} + +// CHECK:STDOUT: --- prelude.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Sub [template] +// CHECK:STDOUT: %.2: type = assoc_entity_type @Sub, [template] +// CHECK:STDOUT: %.3: in Sub> = assoc_entity element0, @Sub.%Op [template] +// CHECK:STDOUT: %.4: type = interface_type @SubAssign [template] +// CHECK:STDOUT: %.5: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type @SubAssign, [template] +// CHECK:STDOUT: %.7: in SubAssign> = assoc_entity element0, @SubAssign.%Op [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Sub = %Sub.decl +// CHECK:STDOUT: .SubAssign = %SubAssign.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Sub.decl: type = interface_decl @Sub [template = constants.%.1] {} +// CHECK:STDOUT: %SubAssign.decl: type = interface_decl @SubAssign [template = constants.%.4] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Sub { +// CHECK:STDOUT: %Self: Sub = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %Self.ref.loc5_15: Sub = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.1: type = facet_type_access %Self.ref.loc5_15 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_15.2: type = converted %Self.ref.loc5_15, %.loc5_15.1 [symbolic = %Self] +// CHECK:STDOUT: %self.loc5_9.1: Self = param self +// CHECK:STDOUT: %self.loc5_9.2: Self = bind_name self, %self.loc5_9.1 +// CHECK:STDOUT: %Self.ref.loc5_28: Sub = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.1: type = facet_type_access %Self.ref.loc5_28 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_28.2: type = converted %Self.ref.loc5_28, %.loc5_28.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc5_21.1: Self = param other +// CHECK:STDOUT: %other.loc5_21.2: Self = bind_name other, %other.loc5_21.1 +// CHECK:STDOUT: %Self.ref.loc5_37: Sub = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = %Self] +// CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = %Self] +// CHECK:STDOUT: %return.var: ref Self = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_41: in Sub> = assoc_entity element0, %Op [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc5_41 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @SubAssign { +// CHECK:STDOUT: %Self: SubAssign = bind_symbolic_name Self [symbolic] +// CHECK:STDOUT: %Op: = fn_decl @Op.2 [template] { +// CHECK:STDOUT: %Self.ref.loc8_20: SubAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.1: type = facet_type_access %Self.ref.loc8_20 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_20: type = converted %Self.ref.loc8_20, %.loc8_24.1 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_24.2: type = ptr_type Self [symbolic = constants.%.5] +// CHECK:STDOUT: %self.loc8_14.1: Self* = param self +// CHECK:STDOUT: %self.loc8_14.3: Self* = bind_name self, %self.loc8_14.1 +// CHECK:STDOUT: %.loc8_9: Self* = addr_pattern %self.loc8_14.3 +// CHECK:STDOUT: %Self.ref.loc8_34: SubAssign = name_ref Self, %Self [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.1: type = facet_type_access %Self.ref.loc8_34 [symbolic = %Self] +// CHECK:STDOUT: %.loc8_34.2: type = converted %Self.ref.loc8_34, %.loc8_34.1 [symbolic = %Self] +// CHECK:STDOUT: %other.loc8_27.1: Self = param other +// CHECK:STDOUT: %other.loc8_27.2: Self = bind_name other, %other.loc8_27.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_39: in SubAssign> = assoc_entity element0, %Op [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Op = %.loc8_39 +// CHECK:STDOUT: witness = (%Op) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@Sub.%self.loc5_9.2: Self](@Sub.%other.loc5_21.2: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[addr @SubAssign.%self.loc8_14.3: Self*](@SubAssign.%other.loc8_27.2: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: --- user.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = interface_type @Sub [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: type = ptr_type {} [template] +// CHECK:STDOUT: %.5: C = struct_value () [template] +// CHECK:STDOUT: %.6: = interface_witness (@impl.1.%Op) [template] +// CHECK:STDOUT: %.7: type = interface_type @SubAssign [template] +// CHECK:STDOUT: %.8: type = ptr_type C [template] +// CHECK:STDOUT: %.9: type = ptr_type Self [symbolic] +// CHECK:STDOUT: %.10: = interface_witness (@impl.2.%Op) [template] +// CHECK:STDOUT: %.11: type = assoc_entity_type @Sub, [template] +// CHECK:STDOUT: %.12: in Sub> = assoc_entity element0, @TestOp.%import_ref.2 [template] +// CHECK:STDOUT: %.13: type = assoc_entity_type @SubAssign, [template] +// CHECK:STDOUT: %.14: in SubAssign> = assoc_entity element0, @TestAssign.%import_ref.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .TestOp = %TestOp +// CHECK:STDOUT: .TestAssign = %TestAssign +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc8: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %Sub.decl: invalid = interface_decl @Sub [template = constants.%.2] {} +// CHECK:STDOUT: %Sub.ref: type = name_ref Sub, %import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Core.ref.loc13: = name_ref Core, %Core [template = %Core] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %SubAssign.decl: invalid = interface_decl @SubAssign [template = constants.%.7] {} +// CHECK:STDOUT: %SubAssign.ref: type = name_ref SubAssign, %import_ref.2 [template = constants.%.7] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestOp: = fn_decl @TestOp [template] { +// CHECK:STDOUT: %C.ref.loc17_14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc17_11.1: C = param a +// CHECK:STDOUT: @TestOp.%a: C = bind_name a, %a.loc17_11.1 +// CHECK:STDOUT: %C.ref.loc17_20: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc17_17.1: C = param b +// CHECK:STDOUT: @TestOp.%b: C = bind_name b, %b.loc17_17.1 +// CHECK:STDOUT: %C.ref.loc17_26: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: @TestOp.%return: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestAssign: = fn_decl @TestAssign [template] { +// CHECK:STDOUT: %C.ref.loc21_18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %a.loc21_15.1: C* = param a +// CHECK:STDOUT: @TestAssign.%a: C* = bind_name a, %a.loc21_15.1 +// CHECK:STDOUT: %C.ref.loc21_25: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %b.loc21_22.1: C = param b +// CHECK:STDOUT: @TestAssign.%b: C = bind_name b, %b.loc21_22.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Sub { +// CHECK:STDOUT: %import_ref.1: in Sub> = import_ref ir1, inst+20, used [template = constants.%.12] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, used [template = imports.%Op.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @SubAssign { +// CHECK:STDOUT: %import_ref.1: in SubAssign> = import_ref ir1, inst+40, used [template = constants.%.14] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+24, unused +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+38, used [template = imports.%Op.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %import_ref.1 +// CHECK:STDOUT: .Self = %import_ref.2 +// CHECK:STDOUT: witness = (%import_ref.3) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: C as Sub { +// CHECK:STDOUT: %Op: = fn_decl @Op.1 [template] { +// CHECK:STDOUT: %C.ref.loc9_15: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %self.loc9_9.1: C = param self +// CHECK:STDOUT: %self.loc9_9.2: C = bind_name self, %self.loc9_9.1 +// CHECK:STDOUT: %C.ref.loc9_25: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc9_18.1: C = param other +// CHECK:STDOUT: %other.loc9_18.2: C = bind_name other, %other.loc9_18.1 +// CHECK:STDOUT: %C.ref.loc9_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var: ref C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: C as SubAssign { +// CHECK:STDOUT: %Op: = fn_decl @Op.3 [template] { +// CHECK:STDOUT: %C.ref.loc14_20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_21: type = ptr_type C [template = constants.%.8] +// CHECK:STDOUT: %self.loc14_14.1: C* = param self +// CHECK:STDOUT: %self.loc14_14.3: C* = bind_name self, %self.loc14_14.1 +// CHECK:STDOUT: %.loc14_9: C* = addr_pattern %self.loc14_14.3 +// CHECK:STDOUT: %C.ref.loc14_31: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %other.loc14_24.1: C = param other +// CHECK:STDOUT: %other.loc14_24.2: C = bind_name other, %other.loc14_24.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.1: = interface_witness (%Op) [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Op = %Op +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc9_9.2: C](@impl.1.%other.loc9_18.2: C) -> @impl.1.%return.var: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_13.1: {} = struct_literal () +// CHECK:STDOUT: %.loc10_13.2: init C = class_init (), @impl.1.%return.var [template = constants.%.5] +// CHECK:STDOUT: %.loc10_13.3: init C = converted %.loc10_13.1, %.loc10_13.2 [template = constants.%.5] +// CHECK:STDOUT: return %.loc10_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.2[%self: Self](%other: Self) -> Self; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc14_14.3: C*](@impl.2.%other.loc14_24.2: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Op.4[addr %self: Self*](%other: Self); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestOp(%a: C, %b: C) -> %return: C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C = name_ref a, %a +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%.2] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+18, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.1.%.1, element0 [template = @impl.1.%Op] +// CHECK:STDOUT: %.loc18_12.1: = bound_method %a.ref, %.1 +// CHECK:STDOUT: %.loc17: ref C = splice_block %return {} +// CHECK:STDOUT: %.loc18_12.2: init C = call %.loc18_12.1(%a.ref, %b.ref) to %.loc17 +// CHECK:STDOUT: return %.loc18_12.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestAssign(%a: C*, %b: C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: C* = name_ref a, %a +// CHECK:STDOUT: %.loc22_3.1: ref C = deref %a.ref +// CHECK:STDOUT: %b.ref: C = name_ref b, %b +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+22, used [template = constants.%.7] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+38, unused +// CHECK:STDOUT: %.1: = interface_witness_access @impl.2.%.1, element0 [template = @impl.2.%Op] +// CHECK:STDOUT: %.loc22_6.1: = bound_method %.loc22_3.1, %.1 +// CHECK:STDOUT: %.loc22_3.2: C* = addr_of %.loc22_3.1 +// CHECK:STDOUT: %.loc22_6.2: init () = call %.loc22_6.1(%.loc22_3.2, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/unary_op.carbon.tmpl b/toolchain/check/testdata/operators/overloaded/unary_op.carbon.tmpl new file mode 100644 index 000000000000..6730d3c7e63f --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/unary_op.carbon.tmpl @@ -0,0 +1,33 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +HEADER + +// --- prelude.carbon + +package Core api; + +interface INTERFACE { + fn Op[self: Self]() -> Self; +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.INTERFACE { + fn Op[self: C]() -> C { + return {}; + } +} + +fn TestOp(a: C) -> C { + return OPa; +} diff --git a/toolchain/check/testdata/operators/overloaded/unary_stmt.carbon.tmpl b/toolchain/check/testdata/operators/overloaded/unary_stmt.carbon.tmpl new file mode 100644 index 000000000000..34daef335465 --- /dev/null +++ b/toolchain/check/testdata/operators/overloaded/unary_stmt.carbon.tmpl @@ -0,0 +1,32 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +HEADER + +// --- prelude.carbon + +package Core api; + +interface INTERFACE { + fn Op[addr self: Self*](); +} + +// --- user.carbon + +package User api; + +import Core; + +class C {}; + +impl C as Core.INTERFACE { + fn Op[addr self: C*](); +} + +fn TestOp() { + var c: C = {}; + OPc; +} diff --git a/toolchain/parse/node_ids.h b/toolchain/parse/node_ids.h index 6fa15b152bd9..93824d5cb25d 100644 --- a/toolchain/parse/node_ids.h +++ b/toolchain/parse/node_ids.h @@ -65,7 +65,6 @@ struct NodeIdInCategory : public NodeId { using AnyDeclId = NodeIdInCategory; using AnyExprId = NodeIdInCategory; using AnyImplAsId = NodeIdInCategory; -using AnyMemberNameId = NodeIdInCategory; using AnyMemberNameOrMemberExprId = NodeIdInCategory; using AnyModifierId = NodeIdInCategory; @@ -94,8 +93,6 @@ using AnyImplDeclId = NodeIdOneOf; using AnyInterfaceDeclId = NodeIdOneOf; using AnyNamespaceId = NodeIdOneOf; -using AnyMemberAccessExprId = - NodeIdOneOf; using AnyPointerDeferenceExprId = NodeIdOneOf; diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index 728d0b2ce3f1..755fc4b7fe33 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -273,8 +273,7 @@ struct BoolLiteral { // `self` parameter, such as `object.MethodName`. struct BoundMethod { static constexpr auto Kind = - InstKind::BoundMethod.Define( - "bound_method"); + InstKind::BoundMethod.Define("bound_method"); TypeId type_id; // The object argument in the bound method, which will be used to initialize @@ -335,8 +334,10 @@ struct Builtin { }; struct Call { - static constexpr auto Kind = - InstKind::Call.Define("call"); + // For a syntactic call, the parse node will be a CallExprStartId. However, + // calls can arise from other syntaxes, such as operators and implicit + // conversions. + static constexpr auto Kind = InstKind::Call.Define("call"); TypeId type_id; InstId callee_id;