diff --git a/toolchain/check/action.cpp b/toolchain/check/action.cpp index a4a8ffd7892d..411c7f5243d5 100644 --- a/toolchain/check/action.cpp +++ b/toolchain/check/action.cpp @@ -86,6 +86,16 @@ static auto OperandDependence(Context& context, context.bundles().GetAsTuple(bundle_id)); } +static auto OperandDependence(Context& context, SemIR::SpecificId specific_id) + -> SemIR::ConstantDependence { + auto specific = context.specifics().Get(specific_id); + auto result = SemIR::ConstantDependence::None; + for (auto arg_id : context.inst_blocks().Get(specific.args_id)) { + result = std::max(result, OperandDependence(context, arg_id)); + } + return result; +} + template requires SemIR::Internal::IsIdKindType static auto OperandDependence(Context& /*context*/, IdT /*id*/) @@ -273,7 +283,7 @@ auto Internal::EndPerformDelayedAction(Context& context, } else { // TODO: pattern insts can depend on non-pattern insts, so we'll probably // eventually need to support actions that produce both. - CARBON_CHECK(!contents.empty()); + CARBON_CHECK(contents.empty()); block_id = context.pattern_block_stack().Pop(); context.inst_block_stack().PopAndDiscard(); } diff --git a/toolchain/check/action.h b/toolchain/check/action.h index 34830ef35457..510a7f683f47 100644 --- a/toolchain/check/action.h +++ b/toolchain/check/action.h @@ -30,6 +30,10 @@ auto PerformAction(Context& context, SemIR::LocId loc_id, auto PerformAction(Context& context, SemIR::LocId loc_id, SemIR::OutFormParamPatternAction action) -> SemIR::InstId; +// Performs a caller pattern match action. Defined in pattern_match.cpp. +auto PerformAction(Context& context, SemIR::LocId loc_id, + SemIR::CallerPatternMatchAction action) -> SemIR::InstId; + // Performs a callee pattern match action. Defined in pattern_match.cpp. auto PerformAction(Context& context, SemIR::LocId loc_id, SemIR::CalleePatternMatchAction action) -> SemIR::InstId; diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 19a292e2dd69..618c3f8712b7 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -2290,8 +2290,12 @@ auto FormExprAsForm(Context& context, SemIR::LocId loc_id, return Context::FormExpr::Error; } - auto type_id = GetTypeComponent(context, form_inst_id); - auto type_inst_id = context.types().GetTypeInstId(type_id); + auto type_inst_id = context.types().GetAsTypeInstId(AddInst( + context, SemIR::LocIdAndInst::RuntimeVerified( + context.sem_ir(), loc_id, + SemIR::TypeComponentOf{.type_id = SemIR::TypeType::TypeId, + .form_inst_id = form_inst_id}))); + auto type_id = context.types().GetTypeIdForTypeInstId(type_inst_id); return {.form_inst_id = form_inst_id, .type_component_inst_id = type_inst_id, .type_component_id = type_id}; diff --git a/toolchain/check/cpp/type_mapping.cpp b/toolchain/check/cpp/type_mapping.cpp index 24f933bbada9..f43b27e6e63e 100644 --- a/toolchain/check/cpp/type_mapping.cpp +++ b/toolchain/check/cpp/type_mapping.cpp @@ -444,6 +444,7 @@ static auto InventCompoundClangArg(Context& context, SemIR::FormInfo form, switch (form.kind) { case SemIR::FormInfo::Primitive: + case SemIR::FormInfo::Dependent: CARBON_FATAL("Not a compound form"); case SemIR::FormInfo::Tuple: { @@ -536,6 +537,13 @@ auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* { std::reverse(worklist.begin() + initial_size, worklist.end()); break; } + case SemIR::FormInfo::Dependent: { + context.TODO( + arg_id, + "Support passing form-dependent args to C++ functions."); + pending_results.push_back(nullptr); + break; + } } break; } diff --git a/toolchain/check/custom_witness.cpp b/toolchain/check/custom_witness.cpp index 2373e0ad4875..80d6f74ce7ba 100644 --- a/toolchain/check/custom_witness.cpp +++ b/toolchain/check/custom_witness.cpp @@ -300,6 +300,7 @@ static auto CanDestroyType( case SemIR::BoolType::Kind: case SemIR::FacetType::Kind: case SemIR::FloatType::Kind: + case SemIR::FormType::Kind: case SemIR::IntLiteralType::Kind: case SemIR::IntType::Kind: case SemIR::PointerType::Kind: diff --git a/toolchain/check/eval_inst.cpp b/toolchain/check/eval_inst.cpp index 8de144ec5b61..2ecb22935e8e 100644 --- a/toolchain/check/eval_inst.cpp +++ b/toolchain/check/eval_inst.cpp @@ -131,6 +131,16 @@ auto EvalConstantInst(Context& /*context*/, SemIR::ValueBinding /*inst*/) return ConstantEvalResult::NotConstant; } +auto EvalConstantInst(Context& context, SemIR::WrapperBinding inst) + -> ConstantEvalResult { + // A wrapper binding evaluates to the value it's bound to. + if (inst.value_id.has_value()) { + return ConstantEvalResult::Existing( + context.constant_values().Get(inst.value_id)); + } + return ConstantEvalResult::NotConstant; +} + auto EvalConstantInst(Context& context, SemIR::InstId inst_id, SemIR::AcquireValue inst) -> ConstantEvalResult { SemIR::ConstantId const_id = SemIR::ConstantId::NotConstant; diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index 9cc135755200..414171732b64 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -384,7 +384,7 @@ auto CheckFunctionDefinitionSignature(Context& context, // The parameter types need to be complete. RequireCompleteType( - context, context.insts().GetAs(param_ref_id).type_id, + context, context.insts().Get(param_ref_id).type_id(), SemIR::LocId(param_ref_id), [&](auto& builder) { CARBON_DIAGNOSTIC( IncompleteTypeInFunctionParam, Context, @@ -406,10 +406,9 @@ auto CheckFunctionDefinitionSignature(Context& context, if (return_call_param.has_value()) { // TODO: If the types are already checked for completeness then this does // nothing? - TryToCompleteType( - context, - context.insts().GetAs(return_call_param).type_id, - SemIR::LocId(return_call_param)); + TryToCompleteType(context, + context.insts().Get(return_call_param).type_id(), + SemIR::LocId(return_call_param)); } } } diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 885e69070726..b8ce5e41664f 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -165,11 +165,6 @@ static auto HandleAnyBindingPattern( SemIR::InstId self_type_inst_id = SemIR::InstId::None) -> bool { auto type_expr = HandleAnyBindingPatternType(context, node_id, node_kind, self_type_inst_id); - if (context.types() - .GetAsInst(type_expr.type_component_id) - .Is()) { - return context.TODO(node_id, "Support symbolic form bindings"); - } SemIR::ExprRegionId type_expr_region_id = ConsumeSubpatternExpr(context, type_expr.inst_id); diff --git a/toolchain/check/pattern.cpp b/toolchain/check/pattern.cpp index 59e8b3827587..a71b9f2e454c 100644 --- a/toolchain/check/pattern.cpp +++ b/toolchain/check/pattern.cpp @@ -130,6 +130,9 @@ auto AddBindingForPattern(Context& context, SemIR::LocId name_loc, case SemIR::ValueParamPattern::Kind: bind_name_kind = SemIR::ValueBinding::Kind; break; + case SemIR::SpliceInst::Kind: + bind_name_kind = SemIR::WrapperBinding::Kind; + break; default: CARBON_FATAL("Unexpected subpattern kind for at_binding_pattern: {0}", subpattern); diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index fcb750c20f45..5f6eb6127899 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -813,12 +813,29 @@ auto MatchContext::DoPostWork(State /*state*/, results_stack_.AppendToTop(tuple_value_id); } -auto MatchContext::DoPreWork(State state, SemIR::SpliceInst splice, +auto MatchContext::DoPreWork(State state, SemIR::SpliceInst /*splice*/, SemIR::InstId scrutinee_id, WorkItem entry) -> void { + auto specific_pattern_const_id = SemIR::GetConstantValueInSpecific( + context_.sem_ir(), specific_id_stack_.back(), entry.pattern_id); + auto specific_pattern_id = + context_.constant_values().GetInstId(specific_pattern_const_id); CARBON_KIND_SWITCH(state) { - case CARBON_KIND(CallerState* _): { - CARBON_FATAL("TODO: support caller-side matching of pattern splices"); + case CARBON_KIND(CallerState* caller_state): { + // TODO: find a way to defer adding the bundle until we know we're + // adding the action. + auto args_id = context_.bundles() + .AddCanonical( + {.pattern_id = specific_pattern_id, + .arg_id = scrutinee_id, + .callee_specific_id = specific_id_stack_.back()}); + caller_state->call_args.push_back( + HandleAction( + context_, SemIR::LocId(entry.pattern_id), + context_.types().GetTypeInstId(GetScrutineeTypeInSpecific( + context_, entry.pattern_id, specific_id_stack_.back())), + {.type_id = SemIR::InstType::TypeId, .args_id = args_id})); + break; } case CARBON_KIND(ThunkState* _): { CARBON_FATAL("TODO: support thunk matching of pattern splices"); @@ -830,12 +847,13 @@ auto MatchContext::DoPreWork(State state, SemIR::SpliceInst splice, CARBON_CHECK(!scrutinee_id.has_value()); auto result_id = HandleAction( context_, SemIR::LocId(entry.pattern_id), - context_.types().GetTypeInstId(splice.type_id), + context_.types().GetTypeInstId(GetScrutineeTypeInSpecific( + context_, entry.pattern_id, specific_id_stack_.back())), {.type_id = SemIR::InstType::TypeId, .args_id = context_.bundles() .AddCanonical( - {.pattern_id = entry.pattern_id, + {.pattern_id = specific_pattern_id, .parent_index = callee_state->index.Allocate()})}); callee_state->PushCallParamPattern( context_, SemIR::LocId(entry.pattern_id), entry.pattern_id, @@ -1097,6 +1115,22 @@ auto ThunkPatternMatch(Context& context, .ignored_call_args = state.outer_call_args}; } +auto PerformAction(Context& context, SemIR::LocId /*loc_id*/, + SemIR::CallerPatternMatchAction action) -> SemIR::InstId { + auto args = context.bundles().Get(action.args_id); + CallerState state; + MatchContext match(context, args.callee_specific_id); + + match.Match(&state, + {.pattern_id = args.pattern_id, + .work = MatchContext::PreWork{.scrutinee_id = args.arg_id}, + .allow_unmarked_ref = false}); + + CARBON_CHECK(state.call_args.size() == 1, + "TODO: add support for composite forms"); + return state.call_args[0]; +} + auto PerformAction(Context& context, SemIR::LocId /*loc_id*/, SemIR::CalleePatternMatchAction action) -> SemIR::InstId { auto args = context.bundles().Get(action.args_id); diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index 56d1045840f6..01d8cd1ec0e9 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" #include "toolchain/check/inst.h" +#include "toolchain/sem_ir/expr_info.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -169,8 +170,8 @@ auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id, diag.Emit(); expr_id = SemIR::ErrorInst::InstId; } else { - auto return_form = - context.insts().Get(function.GetDeclaredReturnForm(context.sem_ir())); + auto return_form_id = function.GetDeclaredReturnForm(context.sem_ir()); + auto return_form = context.insts().Get(return_form_id); CARBON_KIND_SWITCH(return_form) { case CARBON_KIND(SemIR::InitForm _): { if (!SemIR::InitRepr::ForType(context.sem_ir(), return_type_id) @@ -210,6 +211,29 @@ auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id, expr_id = SemIR::ErrorInst::InstId; break; } + case CARBON_KIND(SemIR::SymbolicBinding _): { + auto expr_form_info = SemIR::GetFormInfo(context.sem_ir(), expr_id); + if (expr_form_info.kind != SemIR::FormInfo::Dependent) { + context.TODO(loc_id, + "support nontrivial conversions between symbolic forms"); + expr_id = SemIR::ErrorInst::InstId; + break; + } + auto expr_form_const_id = SemIR::GetConstantValueInSpecific( + context.sem_ir(), SemIR::SpecificId::None, + expr_form_info.form_inst_id); + auto declared_form_const_id = SemIR::GetConstantValueInSpecific( + context.sem_ir(), SemIR::SpecificId::None, return_form_id); + if (expr_form_const_id != declared_form_const_id) { + context.TODO(loc_id, + "support nontrivial conversions between symbolic forms"); + expr_id = SemIR::ErrorInst::InstId; + break; + } + // expr_id's form is identical to the expected form, so we can use it + // directly. + break; + } default: CARBON_FATAL("Unexpected inst kind: {0}", return_form); } diff --git a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon index e51153938a7c..09b4feb019da 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon @@ -31,20 +31,20 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: -// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst70000011, name0: inst7000002F}} +// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst70000011, name0: inst70000030}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000016}} // CHECK:STDOUT: entity_names: // CHECK:STDOUT: entity_name70000000: {name: name(PeriodSelf), parent_scope: name_scope, index: -1, is_template: 0, is_unused: 0, form: inst} // CHECK:STDOUT: entity_name70000001: {name: name1, parent_scope: name_scope70000001, index: -1, is_template: 0, is_unused: 0, form: inst} // CHECK:STDOUT: entity_name70000002: {name: name1, parent_scope: name_scope, index: 0, is_template: 0, is_unused: 0, form: inst} // CHECK:STDOUT: functions: -// CHECK:STDOUT: function70000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block70000007, call_params_id: inst_block70000008, return_type_inst_id: inst70000020, return_form_inst_id: inst7000001F, return_pattern_id: inst70000028} +// CHECK:STDOUT: function70000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block70000007, call_params_id: inst_block70000008, return_type_inst_id: inst70000020, return_form_inst_id: inst7000001F, return_pattern_id: inst70000029} // CHECK:STDOUT: classes: {} // CHECK:STDOUT: interfaces: {} // CHECK:STDOUT: associated_constants: {} // CHECK:STDOUT: impls: {} // CHECK:STDOUT: generics: -// CHECK:STDOUT: generic70000000: {decl: inst7000002F, bindings: inst_block7000000B, self_specific_id: specific70000000, decl_block_id: inst_block7000000D, definition_block_id: inst_block} +// CHECK:STDOUT: generic70000000: {decl: inst70000030, bindings: inst_block7000000B, self_specific_id: specific70000000, decl_block_id: inst_block7000000D, definition_block_id: inst_block} // CHECK:STDOUT: specifics: // CHECK:STDOUT: specific70000000: {generic: generic70000000, args: inst_block7000000C, decl_block_id: inst_block7000000E, decl_has_error: 0, definition_block_id: inst_block, definition_has_error: 0} // CHECK:STDOUT: specific_interfaces: {} @@ -76,13 +76,13 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: object_layout: // CHECK:STDOUT: size: 0 // CHECK:STDOUT: alignment: 1 -// CHECK:STDOUT: 'type(inst70000034)': -// CHECK:STDOUT: value_repr: {kind: none, type: type(inst70000035)} +// CHECK:STDOUT: 'type(inst70000035)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst70000036)} // CHECK:STDOUT: object_layout: // CHECK:STDOUT: size: 0 // CHECK:STDOUT: alignment: 1 -// CHECK:STDOUT: 'type(inst70000035)': -// CHECK:STDOUT: value_repr: {kind: none, type: type(inst70000035)} +// CHECK:STDOUT: 'type(inst70000036)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst70000036)} // CHECK:STDOUT: object_layout: // CHECK:STDOUT: size: 0 // CHECK:STDOUT: alignment: 1 @@ -106,32 +106,32 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: inst7000001D: {kind: SymbolicBinding, arg0: entity_name70000002, arg1: inst, type: type(inst(FormType))} // CHECK:STDOUT: inst7000001E: {kind: SymbolicBinding, arg0: entity_name70000002, arg1: inst, type: type(inst(FormType))} // CHECK:STDOUT: inst7000001F: {kind: NameRef, arg0: name1, arg1: inst7000001C, type: type(inst(FormType))} -// CHECK:STDOUT: inst70000020: {kind: TypeComponentOf, arg0: inst7000001D, type: type(TypeType)} -// CHECK:STDOUT: inst70000021: {kind: PatternType, arg0: inst70000020, type: type(TypeType)} -// CHECK:STDOUT: inst70000022: {kind: OutFormParamPatternAction, arg0: inst7000001F, type: type(inst(InstType))} -// CHECK:STDOUT: inst70000023: {kind: SpliceInst, arg0: inst70000022, type: type(symbolic_constant7000000A)} -// CHECK:STDOUT: inst70000024: {kind: SpliceInst, arg0: inst70000022, type: type(symbolic_constant70000006)} -// CHECK:STDOUT: inst70000025: {kind: TypeComponentOf, arg0: inst7000001E, type: type(TypeType)} -// CHECK:STDOUT: inst70000026: {kind: PatternType, arg0: inst70000025, type: type(TypeType)} -// CHECK:STDOUT: inst70000027: {kind: SpliceInst, arg0: inst70000022, type: type(symbolic_constant7000000A)} -// CHECK:STDOUT: inst70000028: {kind: ReturnSlotPattern, arg0: inst70000023, arg1: inst70000020, type: type(symbolic_constant7000000A)} -// CHECK:STDOUT: inst70000029: {kind: ReturnSlotPattern, arg0: inst70000024, arg1: inst70000020, type: type(symbolic_constant70000006)} -// CHECK:STDOUT: inst7000002A: {kind: ReturnSlotPattern, arg0: inst70000027, arg1: inst70000025, type: type(symbolic_constant7000000A)} -// CHECK:STDOUT: inst7000002B: {kind: SpliceBlock, arg0: inst_block70000005, arg1: inst70000017, type: type(TypeType)} -// CHECK:STDOUT: inst7000002C: {kind: CalleePatternMatchAction, arg0: bundle70000000, type: type(inst(InstType))} -// CHECK:STDOUT: inst7000002D: {kind: SpliceInst, arg0: inst7000002C, type: type(symbolic_constant7000000A)} -// CHECK:STDOUT: inst7000002E: {kind: ReturnSlot, arg0: inst70000020, arg1: inst7000002D, type: type(symbolic_constant70000009)} -// CHECK:STDOUT: inst7000002F: {kind: FunctionDecl, arg0: function70000000, arg1: inst_block7000000A, type: type(inst70000034)} -// CHECK:STDOUT: inst70000030: {kind: OutFormParamPatternAction, arg0: inst7000001D, type: type(inst(InstType))} -// CHECK:STDOUT: inst70000031: {kind: SpliceInst, arg0: inst70000030, type: type(symbolic_constant70000006)} -// CHECK:STDOUT: inst70000032: {kind: ReturnSlotPattern, arg0: inst70000031, arg1: inst70000020, type: type(symbolic_constant70000006)} -// CHECK:STDOUT: inst70000033: {kind: CalleePatternMatchAction, arg0: bundle70000001, type: type(inst(InstType))} -// CHECK:STDOUT: inst70000034: {kind: FunctionType, arg0: function70000000, arg1: specific, type: type(TypeType)} -// CHECK:STDOUT: inst70000035: {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)} -// CHECK:STDOUT: inst70000036: {kind: StructValue, arg0: inst_block_empty, type: type(inst70000034)} +// CHECK:STDOUT: inst70000020: {kind: TypeComponentOf, arg0: inst7000001F, type: type(TypeType)} +// CHECK:STDOUT: inst70000021: {kind: TypeComponentOf, arg0: inst7000001D, type: type(TypeType)} +// CHECK:STDOUT: inst70000022: {kind: TypeComponentOf, arg0: inst7000001E, type: type(TypeType)} +// CHECK:STDOUT: inst70000023: {kind: PatternType, arg0: inst70000021, type: type(TypeType)} +// CHECK:STDOUT: inst70000024: {kind: OutFormParamPatternAction, arg0: inst7000001F, type: type(inst(InstType))} +// CHECK:STDOUT: inst70000025: {kind: SpliceInst, arg0: inst70000024, type: type(symbolic_constant7000000A)} +// CHECK:STDOUT: inst70000026: {kind: SpliceInst, arg0: inst70000024, type: type(symbolic_constant70000007)} +// CHECK:STDOUT: inst70000027: {kind: PatternType, arg0: inst70000022, type: type(TypeType)} +// CHECK:STDOUT: inst70000028: {kind: SpliceInst, arg0: inst70000024, type: type(symbolic_constant7000000A)} +// CHECK:STDOUT: inst70000029: {kind: ReturnSlotPattern, arg0: inst70000025, arg1: inst70000020, type: type(symbolic_constant7000000A)} +// CHECK:STDOUT: inst7000002A: {kind: ReturnSlotPattern, arg0: inst70000026, arg1: inst70000021, type: type(symbolic_constant70000007)} +// CHECK:STDOUT: inst7000002B: {kind: ReturnSlotPattern, arg0: inst70000028, arg1: inst70000022, type: type(symbolic_constant7000000A)} +// CHECK:STDOUT: inst7000002C: {kind: SpliceBlock, arg0: inst_block70000005, arg1: inst70000017, type: type(TypeType)} +// CHECK:STDOUT: inst7000002D: {kind: CalleePatternMatchAction, arg0: bundle70000000, type: type(inst(InstType))} +// CHECK:STDOUT: inst7000002E: {kind: SpliceInst, arg0: inst7000002D, type: type(symbolic_constant70000006)} +// CHECK:STDOUT: inst7000002F: {kind: ReturnSlot, arg0: inst70000021, arg1: inst7000002E, type: type(symbolic_constant70000006)} +// CHECK:STDOUT: inst70000030: {kind: FunctionDecl, arg0: function70000000, arg1: inst_block7000000A, type: type(inst70000035)} +// CHECK:STDOUT: inst70000031: {kind: OutFormParamPatternAction, arg0: inst7000001D, type: type(inst(InstType))} +// CHECK:STDOUT: inst70000032: {kind: SpliceInst, arg0: inst70000031, type: type(symbolic_constant70000007)} +// CHECK:STDOUT: inst70000033: {kind: ReturnSlotPattern, arg0: inst70000032, arg1: inst70000021, type: type(symbolic_constant70000007)} +// CHECK:STDOUT: inst70000034: {kind: CalleePatternMatchAction, arg0: bundle70000000, type: type(inst(InstType))} +// CHECK:STDOUT: inst70000035: {kind: FunctionType, arg0: function70000000, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst70000036: {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)} +// CHECK:STDOUT: inst70000037: {kind: StructValue, arg0: inst_block_empty, type: type(inst70000035)} // CHECK:STDOUT: bundles: -// CHECK:STDOUT: bundle70000000: {arg0: inst70000023, arg1: call_param0} -// CHECK:STDOUT: bundle70000001: {arg0: inst70000031, arg1: call_param0} +// CHECK:STDOUT: bundle70000000: {arg0: inst70000026, arg1: call_param0} // CHECK:STDOUT: constant_values: // CHECK:STDOUT: values: // CHECK:STDOUT: instF: concrete_constant(instF) @@ -150,51 +150,52 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: inst7000001D: symbolic_constant70000003 // CHECK:STDOUT: inst7000001E: symbolic_constant70000004 // CHECK:STDOUT: inst7000001F: symbolic_constant70000004 -// CHECK:STDOUT: inst70000020: symbolic_constant70000005 -// CHECK:STDOUT: inst70000021: symbolic_constant70000006 -// CHECK:STDOUT: inst70000022: symbolic_constant70000007 -// CHECK:STDOUT: inst70000023: symbolic_constant7000000B +// CHECK:STDOUT: inst70000020: symbolic_constant70000006 +// CHECK:STDOUT: inst70000021: symbolic_constant70000005 +// CHECK:STDOUT: inst70000022: symbolic_constant70000006 +// CHECK:STDOUT: inst70000023: symbolic_constant70000007 // CHECK:STDOUT: inst70000024: symbolic_constant70000008 -// CHECK:STDOUT: inst70000025: symbolic_constant70000009 -// CHECK:STDOUT: inst70000026: symbolic_constant7000000A -// CHECK:STDOUT: inst70000027: symbolic_constant7000000B -// CHECK:STDOUT: inst70000028: symbolic_constant7000000D -// CHECK:STDOUT: inst70000029: symbolic_constant7000000C -// CHECK:STDOUT: inst7000002A: symbolic_constant7000000D -// CHECK:STDOUT: inst7000002B: concrete_constant(inst(FormType)) -// CHECK:STDOUT: inst7000002C: symbolic_constant7000000E -// CHECK:STDOUT: inst7000002F: concrete_constant(inst70000036) -// CHECK:STDOUT: inst70000030: symbolic_constant7000000F -// CHECK:STDOUT: inst70000031: symbolic_constant70000010 -// CHECK:STDOUT: inst70000032: symbolic_constant70000011 -// CHECK:STDOUT: inst70000033: symbolic_constant70000012 -// CHECK:STDOUT: inst70000034: concrete_constant(inst70000034) +// CHECK:STDOUT: inst70000025: symbolic_constant7000000B +// CHECK:STDOUT: inst70000026: symbolic_constant70000009 +// CHECK:STDOUT: inst70000027: symbolic_constant7000000A +// CHECK:STDOUT: inst70000028: symbolic_constant7000000B +// CHECK:STDOUT: inst70000029: symbolic_constant7000000D +// CHECK:STDOUT: inst7000002A: symbolic_constant7000000C +// CHECK:STDOUT: inst7000002B: symbolic_constant7000000D +// CHECK:STDOUT: inst7000002C: concrete_constant(inst(FormType)) +// CHECK:STDOUT: inst7000002D: symbolic_constant7000000E +// CHECK:STDOUT: inst70000030: concrete_constant(inst70000037) +// CHECK:STDOUT: inst70000031: symbolic_constant7000000F +// CHECK:STDOUT: inst70000032: symbolic_constant70000010 +// CHECK:STDOUT: inst70000033: symbolic_constant70000011 +// CHECK:STDOUT: inst70000034: symbolic_constant70000012 // CHECK:STDOUT: inst70000035: concrete_constant(inst70000035) // CHECK:STDOUT: inst70000036: concrete_constant(inst70000036) +// CHECK:STDOUT: inst70000037: concrete_constant(inst70000037) // CHECK:STDOUT: symbolic_constants: // CHECK:STDOUT: symbolic_constant70000000: {inst: inst70000014, kind: self, attached: null} // CHECK:STDOUT: symbolic_constant70000001: {inst: inst7000001A, kind: checked, attached: null} // CHECK:STDOUT: symbolic_constant70000002: {inst: inst7000001A, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl0}} // CHECK:STDOUT: symbolic_constant70000003: {inst: inst7000001D, kind: checked, attached: null} // CHECK:STDOUT: symbolic_constant70000004: {inst: inst7000001D, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl1}} -// CHECK:STDOUT: symbolic_constant70000005: {inst: inst70000020, kind: checked, attached: null} -// CHECK:STDOUT: symbolic_constant70000006: {inst: inst70000021, kind: checked, attached: null} -// CHECK:STDOUT: symbolic_constant70000007: {inst: inst70000022, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl2}} -// CHECK:STDOUT: symbolic_constant70000008: {inst: inst70000024, kind: template, attached: null} -// CHECK:STDOUT: symbolic_constant70000009: {inst: inst70000020, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl3}} -// CHECK:STDOUT: symbolic_constant7000000A: {inst: inst70000021, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl4}} -// CHECK:STDOUT: symbolic_constant7000000B: {inst: inst70000024, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl5}} -// CHECK:STDOUT: symbolic_constant7000000C: {inst: inst70000029, kind: template, attached: null} -// CHECK:STDOUT: symbolic_constant7000000D: {inst: inst70000029, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl6}} -// CHECK:STDOUT: symbolic_constant7000000E: {inst: inst7000002C, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl7}} -// CHECK:STDOUT: symbolic_constant7000000F: {inst: inst70000030, kind: template, attached: null} -// CHECK:STDOUT: symbolic_constant70000010: {inst: inst70000031, kind: template, attached: null} -// CHECK:STDOUT: symbolic_constant70000011: {inst: inst70000032, kind: template, attached: null} -// CHECK:STDOUT: symbolic_constant70000012: {inst: inst70000033, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant70000005: {inst: inst70000021, kind: checked, attached: null} +// CHECK:STDOUT: symbolic_constant70000006: {inst: inst70000021, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl2}} +// CHECK:STDOUT: symbolic_constant70000007: {inst: inst70000023, kind: checked, attached: null} +// CHECK:STDOUT: symbolic_constant70000008: {inst: inst70000024, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl3}} +// CHECK:STDOUT: symbolic_constant70000009: {inst: inst70000026, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant7000000A: {inst: inst70000023, kind: checked, attached: {generic: generic70000000, index: generic_inst_in_decl4}} +// CHECK:STDOUT: symbolic_constant7000000B: {inst: inst70000026, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl5}} +// CHECK:STDOUT: symbolic_constant7000000C: {inst: inst7000002A, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant7000000D: {inst: inst7000002A, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl6}} +// CHECK:STDOUT: symbolic_constant7000000E: {inst: inst7000002D, kind: template, attached: {generic: generic70000000, index: generic_inst_in_decl7}} +// CHECK:STDOUT: symbolic_constant7000000F: {inst: inst70000031, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant70000010: {inst: inst70000032, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant70000011: {inst: inst70000033, kind: template, attached: null} +// CHECK:STDOUT: symbolic_constant70000012: {inst: inst70000034, kind: template, attached: null} // CHECK:STDOUT: inst_blocks: // CHECK:STDOUT: inst_block_empty: {} // CHECK:STDOUT: exports: -// CHECK:STDOUT: 0: inst7000002F +// CHECK:STDOUT: 0: inst70000030 // CHECK:STDOUT: generated: {} // CHECK:STDOUT: imports: // CHECK:STDOUT: 0: inst70000011 @@ -207,19 +208,20 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: inst_block70000006: // CHECK:STDOUT: 0: inst70000019 // CHECK:STDOUT: inst_block70000007: -// CHECK:STDOUT: 0: inst70000023 +// CHECK:STDOUT: 0: inst70000025 // CHECK:STDOUT: inst_block70000008: -// CHECK:STDOUT: 0: inst7000002D +// CHECK:STDOUT: 0: inst7000002E // CHECK:STDOUT: inst_block70000009: // CHECK:STDOUT: 0: inst70000019 -// CHECK:STDOUT: 1: inst70000028 +// CHECK:STDOUT: 1: inst70000029 // CHECK:STDOUT: inst_block7000000A: // CHECK:STDOUT: 0: inst7000001F -// CHECK:STDOUT: 1: inst70000023 -// CHECK:STDOUT: 2: inst7000002B -// CHECK:STDOUT: 3: inst7000001C -// CHECK:STDOUT: 4: inst7000002D +// CHECK:STDOUT: 1: inst70000020 +// CHECK:STDOUT: 2: inst70000025 +// CHECK:STDOUT: 3: inst7000002C +// CHECK:STDOUT: 4: inst7000001C // CHECK:STDOUT: 5: inst7000002E +// CHECK:STDOUT: 6: inst7000002F // CHECK:STDOUT: inst_block7000000B: // CHECK:STDOUT: 0: inst7000001C // CHECK:STDOUT: inst_block7000000C: @@ -228,24 +230,24 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: 0: inst7000001B // CHECK:STDOUT: 1: inst7000001E // CHECK:STDOUT: 2: inst70000022 -// CHECK:STDOUT: 3: inst70000025 -// CHECK:STDOUT: 4: inst70000026 -// CHECK:STDOUT: 5: inst70000027 -// CHECK:STDOUT: 6: inst7000002A -// CHECK:STDOUT: 7: inst7000002C +// CHECK:STDOUT: 3: inst70000024 +// CHECK:STDOUT: 4: inst70000027 +// CHECK:STDOUT: 5: inst70000028 +// CHECK:STDOUT: 6: inst7000002B +// CHECK:STDOUT: 7: inst7000002D // CHECK:STDOUT: inst_block7000000E: // CHECK:STDOUT: 0: inst7000001A // CHECK:STDOUT: 1: inst7000001D -// CHECK:STDOUT: 2: inst70000030 -// CHECK:STDOUT: 3: inst70000020 -// CHECK:STDOUT: 4: inst70000021 -// CHECK:STDOUT: 5: inst70000031 -// CHECK:STDOUT: 6: inst70000032 -// CHECK:STDOUT: 7: inst70000033 +// CHECK:STDOUT: 2: inst70000021 +// CHECK:STDOUT: 3: inst70000031 +// CHECK:STDOUT: 4: inst70000023 +// CHECK:STDOUT: 5: inst70000032 +// CHECK:STDOUT: 6: inst70000033 +// CHECK:STDOUT: 7: inst70000034 // CHECK:STDOUT: inst_block7000000F: // CHECK:STDOUT: 0: instF // CHECK:STDOUT: 1: inst70000010 -// CHECK:STDOUT: 2: inst7000002F +// CHECK:STDOUT: 2: inst70000030 // CHECK:STDOUT: value_stores: // CHECK:STDOUT: shared_values: // CHECK:STDOUT: ints: {} diff --git a/toolchain/check/testdata/function/call/form.carbon b/toolchain/check/testdata/function/call/form.carbon index 699dffc79985..b30fa8b634e7 100644 --- a/toolchain/check/testdata/function/call/form.carbon +++ b/toolchain/check/testdata/function/call/form.carbon @@ -105,20 +105,91 @@ fn G() { F(y); } -// --- fail_todo_form_generic_param.carbon +// --- form_generic_param.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_todo_form_generic_param.carbon:[[@LINE+4]]:24: error: semantics TODO: `Support symbolic form bindings` [SemanticsTodo] -// CHECK:STDERR: fn F(Form:! Core.Form, x:? Form); -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -fn F(Form:! Core.Form, x:? Form); +fn F(Fm:! Core.Form, unused x:? Fm) {} fn G() { var x: i32; F(form(var i32), x); } +// --- fail_todo_composite_generic_form.carbon +library "[[@TEST_NAME]]"; + +fn F(Fm:! Core.Form, unused x:? Fm) {} + +fn G() { + var x: i32; + // CHECK:STDERR: fail_todo_composite_generic_form.carbon:[[@LINE+10]]:3: error: cannot implicitly convert expression of type `(Core.Form, Core.Form)` to `Core.Form` [ConversionFailure] + // CHECK:STDERR: F((form(var i32), form(ref i32)), (x, ref x)); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_composite_generic_form.carbon:[[@LINE+7]]:3: note: type `(Core.Form, Core.Form)` does not implement interface `Core.ImplicitAs(Core.Form)` [MissingImplInMemberAccessInContext] + // CHECK:STDERR: F((form(var i32), form(ref i32)), (x, ref x)); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_composite_generic_form.carbon:[[@LINE-10]]:6: note: initializing generic parameter `Fm` declared here [InitializingGenericParam] + // CHECK:STDERR: fn F(Fm:! Core.Form, unused x:? Fm) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + F((form(var i32), form(ref i32)), (x, ref x)); +} + +// --- fail_todo_deduce_generic_form.carbon +library "[[@TEST_NAME]]"; + +fn F[Fm:! Core.Form](v:? Fm); + +fn G() { + var v: i32 = 0; + // CHECK:STDERR: fail_todo_deduce_generic_form.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `Fm` [DeductionIncomplete] + // CHECK:STDERR: F(ref v); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_todo_deduce_generic_form.carbon:[[@LINE-7]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn F[Fm:! Core.Form](v:? Fm); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + F(ref v); +} + +// --- fail_form_generic_arg_not_form.carbon +library "[[@TEST_NAME]]"; + +fn F(Fm:! Core.Form, unused x:? Fm) {} + +fn G() { + var x: i32; + // CHECK:STDERR: fail_form_generic_arg_not_form.carbon:[[@LINE+10]]:3: error: cannot implicitly convert expression of type `type` to `Core.Form` [ConversionFailure] + // CHECK:STDERR: F(i32, x); + // CHECK:STDERR: ^~~~~~~~~ + // CHECK:STDERR: fail_form_generic_arg_not_form.carbon:[[@LINE+7]]:3: note: type `type` does not implement interface `Core.ImplicitAs(Core.Form)` [MissingImplInMemberAccessInContext] + // CHECK:STDERR: F(i32, x); + // CHECK:STDERR: ^~~~~~~~~ + // CHECK:STDERR: fail_form_generic_arg_not_form.carbon:[[@LINE-10]]:6: note: initializing generic parameter `Fm` declared here [InitializingGenericParam] + // CHECK:STDERR: fn F(Fm:! Core.Form, unused x:? Fm) {} + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + F(i32, x); +} + +// --- fail_form_generic_missing_ref_tag.carbon +library "[[@TEST_NAME]]"; + +fn F(Fm:! Core.Form, unused x:? Fm) {} + +fn G() { + var x: i32; + // CHECK:STDERR: fail_form_generic_missing_ref_tag.carbon:[[@LINE+8]]:20: error: argument to `ref` parameter not marked with `ref` [RefParamNoRefTag] + // CHECK:STDERR: F(form(ref i32), x); + // CHECK:STDERR: ^ + // CHECK:STDERR: fail_form_generic_missing_ref_tag.carbon: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fail_form_generic_missing_ref_tag.carbon:[[@LINE-8]]:29: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fn F(Fm:! Core.Form, unused x:? Fm) {} + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: + F(form(ref i32), x); +} + // --- fail_todo_local_init_form_binding.carbon library "[[@TEST_NAME]]"; @@ -136,7 +207,7 @@ library "[[@TEST_NAME]]"; // TODO: this code should fail for a different reason, but right now we don't // have a way to write correct code that reaches the TODO we're exercising here. fn F(Form:! Core.Form) { - // CHECK:STDERR: fail_todo_local_symbolic_form_binding.carbon:[[@LINE+4]]:7: error: semantics TODO: `Support symbolic form bindings` [SemanticsTodo] + // CHECK:STDERR: fail_todo_local_symbolic_form_binding.carbon:[[@LINE+4]]:7: error: semantics TODO: `support local form bindings` [SemanticsTodo] // CHECK:STDERR: let y:? Form = 0; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -201,10 +272,21 @@ fn F() ->? ref i32; // --- form_generic_return.carbon library "[[@TEST_NAME]]"; +//@include-in-dumps -//@dump-sem-ir-begin -fn F(Form:! Core.Form) ->? Form; -//@dump-sem-ir-end +fn F(Fm:! Core.Form, v:? Fm) ->? Fm { + // TODO: This should fail because `Fm` might be `form(var T)` for a + // non-copyable `T`. + return v; +} + +fn G() { + var v: i32 = 0; + + var unused x: i32 = F(form(var i32), v); + let unused ref y: i32 = F(form(ref i32), ref v); + let unused z: i32 = F(form(val i32), v); +} // CHECK:STDOUT: --- ref_form_param.carbon // CHECK:STDOUT: @@ -229,6 +311,7 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.512] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = ref_form %i32 [concrete = constants.%.512] +// CHECK:STDOUT: %.loc4_15.3: type = type_component_of %.loc4_15.2 [concrete = constants.%i32] // CHECK:STDOUT: } // CHECK:STDOUT: %x: ref %i32 = ref_binding x, %x.param // CHECK:STDOUT: } @@ -294,6 +377,7 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.795] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = init_form %i32 [concrete = constants.%.795] +// CHECK:STDOUT: %.loc4_15.3: type = type_component_of %.loc4_15.2 [concrete = constants.%i32] // CHECK:STDOUT: } // CHECK:STDOUT: %x: ref %i32 = ref_binding x, %x.param // CHECK:STDOUT: } @@ -369,6 +453,7 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.c2a] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_15.2: Core.Form = value_form %i32 [concrete = constants.%.c2a] +// CHECK:STDOUT: %.loc4_15.3: type = type_component_of %.loc4_15.2 [concrete = constants.%i32] // CHECK:STDOUT: } // CHECK:STDOUT: %x: %i32 = value_binding x, %x.param // CHECK:STDOUT: } @@ -414,6 +499,7 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: %.loc4_20.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] // CHECK:STDOUT: %.loc4_20.2: type = converted %.loc4_20.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] // CHECK:STDOUT: %.loc4_15.2: Core.Form = ref_form %.loc4_20.2 [concrete = constants.%.9f9] +// CHECK:STDOUT: %.loc4_15.3: type = type_component_of %.loc4_15.2 [concrete = constants.%empty_tuple.type] // CHECK:STDOUT: } // CHECK:STDOUT: %x: ref %empty_tuple.type = ref_binding x, %x.param // CHECK:STDOUT: } @@ -438,12 +524,13 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %.loc4_17.1: %pattern_type.6b6 = ref_return_pattern [concrete = constants.%.ae0] -// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %.loc4_17.1, constants.%i32 [concrete = constants.%return.patt] +// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %.loc4_17.1, %.loc4_17.3 [concrete = constants.%return.patt] // CHECK:STDOUT: } { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_17.2: Core.Form = ref_form %i32 [concrete = constants.%.512] -// CHECK:STDOUT: %.loc4_17.3: ref %i32 = ref_return -// CHECK:STDOUT: %return: ref %i32 = return_slot %.loc4_17.3 +// CHECK:STDOUT: %.loc4_17.3: type = type_component_of %.loc4_17.2 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc4_17.4: ref %i32 = ref_return +// CHECK:STDOUT: %return: ref %i32 = return_slot %.loc4_17.4 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -483,10 +570,11 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt] -// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, constants.%i32 [concrete = constants.%return.patt] +// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %.loc4_17.2 [concrete = constants.%return.patt] // CHECK:STDOUT: } { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %.loc4: Core.Form = init_form %i32 [concrete = constants.%.795] +// CHECK:STDOUT: %.loc4_17.1: Core.Form = init_form %i32 [concrete = constants.%.795] +// CHECK:STDOUT: %.loc4_17.2: type = type_component_of %.loc4_17.1 [concrete = constants.%i32] // CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0 // CHECK:STDOUT: %return: ref %i32 = return_slot %return.param // CHECK:STDOUT: } @@ -535,12 +623,13 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: file { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { // CHECK:STDOUT: %.loc4_17.1: %pattern_type.6b6 = value_return_pattern [concrete = constants.%.1a5] -// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %.loc4_17.1, constants.%i32 [concrete = constants.%return.patt] +// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %.loc4_17.1, %.loc4_17.3 [concrete = constants.%return.patt] // CHECK:STDOUT: } { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc4_17.2: Core.Form = value_form %i32 [concrete = constants.%.c2a] -// CHECK:STDOUT: %.loc4_17.3: %i32 = value_return -// CHECK:STDOUT: %return: %i32 = return_slot %.loc4_17.3 +// CHECK:STDOUT: %.loc4_17.3: type = type_component_of %.loc4_17.2 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc4_17.4: %i32 = value_return +// CHECK:STDOUT: %return: %i32 = return_slot %.loc4_17.4 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -564,68 +653,350 @@ fn F(Form:! Core.Form) ->? Form; // CHECK:STDOUT: %type: type = facet_type [concrete] // CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self] // CHECK:STDOUT: %pattern_type.13f: type = pattern_type Core.Form [concrete] -// CHECK:STDOUT: %Form.patt: %pattern_type.13f = symbolic_binding_pattern Form, 0 [symbolic] -// CHECK:STDOUT: %Form: Core.Form = symbolic_binding Form, 0 [symbolic] -// CHECK:STDOUT: %.42f: type = type_component_of %Form [symbolic] +// CHECK:STDOUT: %Fm.patt: %pattern_type.13f = symbolic_binding_pattern Fm, 0 [symbolic] +// CHECK:STDOUT: %Fm: Core.Form = symbolic_binding Fm, 0 [symbolic] +// CHECK:STDOUT: %.42f: type = type_component_of %Fm [symbolic] // CHECK:STDOUT: %pattern_type.177: type = pattern_type %.42f [symbolic] -// CHECK:STDOUT: %.35a: %pattern_type.177 = splice_inst @F.%.loc4_24.2 [template] -// CHECK:STDOUT: %return.patt.5b7: %pattern_type.177 = return_slot_pattern %.35a, %.42f [template] -// CHECK:STDOUT: %.94f: = out_form_param_pattern_action %Form [template] +// CHECK:STDOUT: %.f15: %pattern_type.177 = splice_inst @F.%.loc4_23.2 [template] +// CHECK:STDOUT: %v.patt.0b3: %pattern_type.177 = at_binding_pattern v, %.f15 [template] +// CHECK:STDOUT: %.677: %pattern_type.177 = splice_inst @F.%.loc4_30.2 [template] +// CHECK:STDOUT: %return.patt.113: %pattern_type.177 = return_slot_pattern %.677, %.42f [template] +// CHECK:STDOUT: %.cfa: = form_param_pattern_action %Fm, v [template] +// CHECK:STDOUT: %.26b: %pattern_type.177 = splice_inst %.cfa [template] +// CHECK:STDOUT: %v.patt.cda: %pattern_type.177 = at_binding_pattern v, %.26b [template] +// CHECK:STDOUT: %.94f: = out_form_param_pattern_action %Fm [template] // CHECK:STDOUT: %.1ac: %pattern_type.177 = splice_inst %.94f [template] // CHECK:STDOUT: %return.patt.333: %pattern_type.177 = return_slot_pattern %.1ac, %.42f [template] -// CHECK:STDOUT: %.82b: = callee_pattern_match_action %.1ac, call_param0 [template] +// CHECK:STDOUT: %.095: = callee_pattern_match_action %.f15, call_param0 [template] +// CHECK:STDOUT: %.efc: = callee_pattern_match_action %.677, call_param1 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %require_complete.c9b: = require_complete_type %.42f [symbolic] +// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] +// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete] +// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] +// CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %i32.builtin: type = int_type signed, %int_32 [concrete] +// CHECK:STDOUT: %complete_type.f8a: = complete_type_witness %i32.builtin [concrete] +// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %v.patt.113: %pattern_type.6b6 = ref_binding_pattern v [concrete] +// CHECK:STDOUT: %v.var_patt.68d: %pattern_type.6b6 = var_pattern %v.patt.113 [concrete] +// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete] +// CHECK:STDOUT: %ImplicitAs.type.0ff: type = generic_interface_type @ImplicitAs [concrete] +// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.0ff = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.914: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.845: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.a23: = impl_witness imports.%ImplicitAs.impl_witness_table.b3c, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.914 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.a23) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.740: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.1c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.740, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39 [concrete] +// CHECK:STDOUT: %.795: Core.Form = init_form %i32 [concrete] +// CHECK:STDOUT: %return.param_patt.a9a4c7.1: %pattern_type.6b6 = out_param_pattern [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_0.3c0: %i32 = int_value 0 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = ref_binding_pattern x [concrete] +// CHECK:STDOUT: %x.var_patt: %pattern_type.6b6 = var_pattern %x.patt [concrete] +// CHECK:STDOUT: %v.param_patt.e9ad17.1: %pattern_type.6b6 = ref_param_pattern [concrete] +// CHECK:STDOUT: %v.var_patt.13561f.1: %pattern_type.6b6 = var_pattern %v.param_patt.e9ad17.1 [concrete] +// CHECK:STDOUT: %inst.splice_block: = inst_value [concrete] { +// CHECK:STDOUT: %.eb8: %pattern_type.6b6 = splice_block %v.var_patt.13561f.2 [concrete = %v.var_patt.13561f.1] { +// CHECK:STDOUT: %v.param_patt.e9ad17.3: %pattern_type.6b6 = ref_param_pattern [concrete = %v.param_patt.e9ad17.1] +// CHECK:STDOUT: %v.var_patt.13561f.2: %pattern_type.6b6 = var_pattern %v.param_patt.e9ad17.3 [concrete = %v.var_patt.13561f.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: %v.patt.b2b: %pattern_type.6b6 = at_binding_pattern v, %v.var_patt.13561f.1 [concrete] +// CHECK:STDOUT: %inst.out_param_pattern: = inst_value [concrete] { +// CHECK:STDOUT: %return.param_patt.a9a4c7.2: %pattern_type.6b6 = out_param_pattern [concrete = %return.param_patt.a9a4c7.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a4c7.1, %i32 [concrete] +// CHECK:STDOUT: %F.specific_fn.8ea: = specific_function %F, @F(%.795) [concrete] +// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] +// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] +// CHECK:STDOUT: %Int.as.Copy.impl.Op.5e0: %Int.as.Copy.impl.Op.type.ac8 = struct_value () [symbolic] +// CHECK:STDOUT: %Copy.impl_witness.0e0: = impl_witness imports.%Copy.impl_witness_table.367, @Int.as.Copy.impl(%int_32) [concrete] +// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.3f6: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete] +// CHECK:STDOUT: %Int.as.Copy.impl.Op.4f6: %Int.as.Copy.impl.Op.type.3f6 = struct_value () [concrete] +// CHECK:STDOUT: %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.0e0) [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.type.d09: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete] +// CHECK:STDOUT: %.7a6: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d09, %Copy.facet [concrete] +// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type.6b6 = ref_binding_pattern y [concrete] +// CHECK:STDOUT: %.512: Core.Form = ref_form %i32 [concrete] +// CHECK:STDOUT: %inst.ref_param_pattern: = inst_value [concrete] { +// CHECK:STDOUT: %v.param_patt.e9ad17.2: %pattern_type.6b6 = ref_param_pattern [concrete = %v.param_patt.e9ad17.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %v.patt.5c0: %pattern_type.6b6 = at_binding_pattern v, %v.param_patt.e9ad17.1 [concrete] +// CHECK:STDOUT: %.ae0167.1: %pattern_type.6b6 = ref_return_pattern [concrete] +// CHECK:STDOUT: %inst.ref_return_pattern: = inst_value [concrete] { +// CHECK:STDOUT: %.ae0167.2: %pattern_type.6b6 = ref_return_pattern [concrete = %.ae0167.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %return.patt.c62: %pattern_type.6b6 = return_slot_pattern %.ae0167.1, %i32 [concrete] +// CHECK:STDOUT: %F.specific_fn.0c3: = specific_function %F, @F(%.512) [concrete] +// CHECK:STDOUT: %z.patt: %pattern_type.6b6 = value_binding_pattern z [concrete] +// CHECK:STDOUT: %.c2a: Core.Form = value_form %i32 [concrete] +// CHECK:STDOUT: %v.param_patt.733534.1: %pattern_type.6b6 = value_param_pattern [concrete] +// CHECK:STDOUT: %inst.value_param_pattern: = inst_value [concrete] { +// CHECK:STDOUT: %v.param_patt.733534.2: %pattern_type.6b6 = value_param_pattern [concrete = %v.param_patt.733534.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %v.patt.971: %pattern_type.6b6 = at_binding_pattern v, %v.param_patt.733534.1 [concrete] +// CHECK:STDOUT: %.1a588f.1: %pattern_type.6b6 = value_return_pattern [concrete] +// CHECK:STDOUT: %inst.value_return_pattern: = inst_value [concrete] { +// CHECK:STDOUT: %.1a588f.2: %pattern_type.6b6 = value_return_pattern [concrete = %.1a588f.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %return.patt.45a: %pattern_type.6b6 = return_slot_pattern %.1a588f.1, %i32 [concrete] +// CHECK:STDOUT: %F.specific_fn.2f1: = specific_function %F, @F(%.c2a) [concrete] +// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete] +// CHECK:STDOUT: %Self.0e7: %Destroy.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.d3e: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Self.0e7) [symbolic] +// CHECK:STDOUT: %Destroy.WithSelf.Op.42b: %Destroy.WithSelf.Op.type.d3e = struct_value () [symbolic] +// CHECK:STDOUT: %Destroy.assoc_type: type = assoc_entity_type @Destroy [concrete] +// CHECK:STDOUT: %assoc0.ae8: %Destroy.assoc_type = assoc_entity element0, imports.%Core.import_ref.918 [concrete] +// CHECK:STDOUT: %Destroy.Op.type.1d8f74.2: type = fn_type @Destroy.Op.2 [concrete] +// CHECK:STDOUT: %Destroy.Op.1a2547.2: %Destroy.Op.type.1d8f74.2 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.df9cc1.2: = custom_witness (%Destroy.Op.1a2547.2), @Destroy [concrete] +// CHECK:STDOUT: %Destroy.facet.d07: %Destroy.type = facet_value %i32, (%custom_witness.df9cc1.2) [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.47a: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.d07) [concrete] +// CHECK:STDOUT: %.22e: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.47a, %Destroy.facet.d07 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { // CHECK:STDOUT: .Form = %Core.Form +// CHECK:STDOUT: .Int = %Core.Int +// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs +// CHECK:STDOUT: .Copy = %Core.Copy +// CHECK:STDOUT: .Destroy = %Core.Destroy // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } // CHECK:STDOUT: %Core.Form: type = import_ref Core//prelude/parts/form, Form, loaded [concrete = Core.Form] +// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic] +// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.0ff = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] +// CHECK:STDOUT: %Core.import_ref.edf: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.845)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.b3c = impl_witness_table (%Core.import_ref.edf), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type] +// CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)] +// CHECK:STDOUT: %Copy.impl_witness_table.367 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete] +// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type] +// CHECK:STDOUT: %Core.import_ref.c64: %Destroy.assoc_type = import_ref Core//prelude/parts/destroy, loc{{\d+_\d+}}, loaded [concrete = constants.%assoc0.ae8] +// CHECK:STDOUT: %Core.import_ref.918: @Destroy.WithSelf.%Destroy.WithSelf.Op.type (%Destroy.WithSelf.Op.type.d3e) = import_ref Core//prelude/parts/destroy, loc{{\d+_\d+}}, loaded [symbolic = @Destroy.WithSelf.%Destroy.WithSelf.Op (constants.%Destroy.WithSelf.Op.42b)] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { -// CHECK:STDOUT: %Form.patt.loc4_10.1: %pattern_type.13f = symbolic_binding_pattern Form, 0 [symbolic = %Form.patt.loc4_10.2 (constants.%Form.patt)] -// CHECK:STDOUT: %return.patt.loc4_24.1: @F.%pattern_type (%pattern_type.177) = return_slot_pattern %.loc4_24.6, constants.%.42f [template = %return.patt.loc4_24.2 (constants.%return.patt.5b7)] +// CHECK:STDOUT: %Fm.patt.loc4_8.1: %pattern_type.13f = symbolic_binding_pattern Fm, 0 [symbolic = %Fm.patt.loc4_8.2 (constants.%Fm.patt)] +// CHECK:STDOUT: %v.patt.loc4_23.1: @F.%pattern_type (%pattern_type.177) = at_binding_pattern v, %.loc4_23.5 [template = %v.patt.loc4_23.2 (constants.%v.patt.0b3)] +// CHECK:STDOUT: %return.patt.loc4_30.1: @F.%pattern_type (%pattern_type.177) = return_slot_pattern %.loc4_30.5, %.loc4_34 [template = %return.patt.loc4_30.2 (constants.%return.patt.113)] // CHECK:STDOUT: } { -// CHECK:STDOUT: %Form.ref.loc4_28: Core.Form = name_ref Form, %Form.loc4_10.2 [symbolic = %Form.loc4_10.1 (constants.%Form)] -// CHECK:STDOUT: %.loc4_24.6: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_24.2 [template = %.loc4_24.4 (constants.%.35a)] -// CHECK:STDOUT: %.loc4_17: type = splice_block %Form.ref.loc4_17 [concrete = Core.Form] { +// CHECK:STDOUT: %.loc4_23.5: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_23.2 [template = %.loc4_23.3 (constants.%.f15)] +// CHECK:STDOUT: %Fm.ref.loc4_34: Core.Form = name_ref Fm, %Fm.loc4_8.2 [symbolic = %Fm.loc4_8.1 (constants.%Fm)] +// CHECK:STDOUT: %.loc4_34: type = type_component_of %Fm.ref.loc4_34 [symbolic = %.loc4_26.1 (constants.%.42f)] +// CHECK:STDOUT: %.loc4_30.5: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_30.2 [template = %.loc4_30.3 (constants.%.677)] +// CHECK:STDOUT: %.loc4_15: type = splice_block %Form.ref [concrete = Core.Form] { // CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] // CHECK:STDOUT: %Core.ref: = name_ref Core, imports.%Core [concrete = imports.%Core] -// CHECK:STDOUT: %Form.ref.loc4_17: type = name_ref Form, imports.%Core.Form [concrete = Core.Form] +// CHECK:STDOUT: %Form.ref: type = name_ref Form, imports.%Core.Form [concrete = Core.Form] // CHECK:STDOUT: } -// CHECK:STDOUT: %Form.loc4_10.2: Core.Form = symbolic_binding Form, 0 [symbolic = %Form.loc4_10.1 (constants.%Form)] -// CHECK:STDOUT: %.loc4_24.1: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_24.5 -// CHECK:STDOUT: %return: @F.%.loc4_24.3 (%.42f) = return_slot %.loc4_24.1 +// CHECK:STDOUT: %Fm.loc4_8.2: Core.Form = symbolic_binding Fm, 0 [symbolic = %Fm.loc4_8.1 (constants.%Fm)] +// CHECK:STDOUT: %.loc4_23.1: @F.%.loc4_26.1 (%.42f) = splice_inst %.loc4_23.4 +// CHECK:STDOUT: %.loc4_26.2: Core.Form = splice_block %Fm.ref.loc4_26 [symbolic = %Fm.loc4_8.1 (constants.%Fm)] { +// CHECK:STDOUT: %Fm.ref.loc4_26: Core.Form = name_ref Fm, %Fm.loc4_8.2 [symbolic = %Fm.loc4_8.1 (constants.%Fm)] +// CHECK:STDOUT: %.loc4_26.3: type = type_component_of %Fm.ref.loc4_26 [symbolic = %.loc4_26.1 (constants.%.42f)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %v: @F.%.loc4_26.1 (%.42f) = wrapper_binding v, %.loc4_23.1 +// CHECK:STDOUT: %.loc4_30.1: @F.%.loc4_26.1 (%.42f) = splice_inst %.loc4_30.4 +// CHECK:STDOUT: %return: @F.%.loc4_26.1 (%.42f) = return_slot %.loc4_30.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F(%Fm.loc4_8.2: Core.Form) { +// CHECK:STDOUT: %Fm.patt.loc4_8.2: %pattern_type.13f = symbolic_binding_pattern Fm, 0 [symbolic = %Fm.patt.loc4_8.2 (constants.%Fm.patt)] +// CHECK:STDOUT: %Fm.loc4_8.1: Core.Form = symbolic_binding Fm, 0 [symbolic = %Fm.loc4_8.1 (constants.%Fm)] +// CHECK:STDOUT: %.loc4_26.1: type = type_component_of %Fm.loc4_8.1 [symbolic = %.loc4_26.1 (constants.%.42f)] +// CHECK:STDOUT: %.loc4_23.2: = form_param_pattern_action %Fm.ref.loc4_26, v [template] +// CHECK:STDOUT: %pattern_type: type = pattern_type %.loc4_26.1 [symbolic = %pattern_type (constants.%pattern_type.177)] +// CHECK:STDOUT: %.loc4_23.3: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_23.2 [template = %.loc4_23.3 (constants.%.f15)] +// CHECK:STDOUT: %v.patt.loc4_23.2: @F.%pattern_type (%pattern_type.177) = at_binding_pattern v, %.loc4_23.3 [template = %v.patt.loc4_23.2 (constants.%v.patt.0b3)] +// CHECK:STDOUT: %.loc4_30.2: = out_form_param_pattern_action %Fm.ref.loc4_34 [template] +// CHECK:STDOUT: %.loc4_30.3: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_30.2 [template = %.loc4_30.3 (constants.%.677)] +// CHECK:STDOUT: %return.patt.loc4_30.2: @F.%pattern_type (%pattern_type.177) = return_slot_pattern %.loc4_30.3, %.loc4_26.1 [template = %return.patt.loc4_30.2 (constants.%return.patt.113)] +// CHECK:STDOUT: %.loc4_23.4: = callee_pattern_match_action constants.%.f15, call_param0 [template] +// CHECK:STDOUT: %.loc4_30.4: = callee_pattern_match_action constants.%.677, call_param1 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %require_complete: = require_complete_type %.loc4_26.1 [symbolic = %require_complete (constants.%require_complete.c9b)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%.loc4_23.1: @F.%.loc4_26.1 (%.42f)) -> out %.loc4_30.1:? %Fm { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %v.ref: @F.%.loc4_26.1 (%.42f) = name_ref v, %v +// CHECK:STDOUT: return %v.ref // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F(%Form.loc4_10.2: Core.Form) { -// CHECK:STDOUT: %Form.patt.loc4_10.2: %pattern_type.13f = symbolic_binding_pattern Form, 0 [symbolic = %Form.patt.loc4_10.2 (constants.%Form.patt)] -// CHECK:STDOUT: %Form.loc4_10.1: Core.Form = symbolic_binding Form, 0 [symbolic = %Form.loc4_10.1 (constants.%Form)] -// CHECK:STDOUT: %.loc4_24.2: = out_form_param_pattern_action %Form.ref.loc4_28 [template] -// CHECK:STDOUT: %.loc4_24.3: type = type_component_of %Form.loc4_10.1 [symbolic = %.loc4_24.3 (constants.%.42f)] -// CHECK:STDOUT: %pattern_type: type = pattern_type %.loc4_24.3 [symbolic = %pattern_type (constants.%pattern_type.177)] -// CHECK:STDOUT: %.loc4_24.4: @F.%pattern_type (%pattern_type.177) = splice_inst %.loc4_24.2 [template = %.loc4_24.4 (constants.%.35a)] -// CHECK:STDOUT: %return.patt.loc4_24.2: @F.%pattern_type (%pattern_type.177) = return_slot_pattern %.loc4_24.4, %.loc4_24.3 [template = %return.patt.loc4_24.2 (constants.%return.patt.5b7)] -// CHECK:STDOUT: %.loc4_24.5: = callee_pattern_match_action %.loc4_24.6, call_param0 [template] -// CHECK:STDOUT: -// CHECK:STDOUT: fn() -> out %.loc4_24.1:? %Form; +// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %v.patt: %pattern_type.6b6 = ref_binding_pattern v [concrete = constants.%v.patt.113] +// CHECK:STDOUT: %v.var_patt: %pattern_type.6b6 = var_pattern %v.patt [concrete = constants.%v.var_patt.68d] +// CHECK:STDOUT: } +// CHECK:STDOUT: %v.var.loc11: ref %i32 = var %v.var_patt +// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] +// CHECK:STDOUT: %impl.elem0.loc11: %.1c5 = impl_witness_access constants.%ImplicitAs.impl_witness.a23, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.e39] +// CHECK:STDOUT: %bound_method.loc11_3.1: = bound_method %int_0, %impl.elem0.loc11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc11: = specific_function %impl.elem0.loc11, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc11_3.2: = bound_method %int_0, %specific_fn.loc11 [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc11_3.2(%int_0) [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc11: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: assign %v.var.loc11, %.loc11 +// CHECK:STDOUT: %i32.loc11: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %v: ref %i32 = ref_binding v, %v.var.loc11 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = ref_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %x.var_patt: %pattern_type.6b6 = var_pattern %x.patt [concrete = constants.%x.var_patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x.var: ref %i32 = var %x.var_patt +// CHECK:STDOUT: %F.ref.loc13: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %i32.loc13_34: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc13_30: Core.Form = init_form %i32.loc13_34 [concrete = constants.%.795] +// CHECK:STDOUT: %v.ref.loc13: ref %i32 = name_ref v, %v +// CHECK:STDOUT: %F.specific_fn.loc13: = specific_function %F.ref.loc13, @F(constants.%.795) [concrete = constants.%F.specific_fn.8ea] +// CHECK:STDOUT: %.loc13_40: %i32 = acquire_value %v.ref.loc13 +// CHECK:STDOUT: %impl.elem0.loc13: %.7a6 = impl_witness_access constants.%Copy.impl_witness.0e0, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] +// CHECK:STDOUT: %bound_method.loc13_40.1: = bound_method %.loc13_40, %impl.elem0.loc13 +// CHECK:STDOUT: %specific_fn.loc13: = specific_function %impl.elem0.loc13, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] +// CHECK:STDOUT: %bound_method.loc13_40.2: = bound_method %.loc13_40, %specific_fn.loc13 +// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc13_40.2(%.loc13_40) +// CHECK:STDOUT: %v.var.1: ref %i32 = var constants.%v.var_patt.13561f.1 +// CHECK:STDOUT: assign %v.var.1, %Int.as.Copy.impl.Op.call +// CHECK:STDOUT: %F.call.loc13: init %i32 = call %F.specific_fn.loc13(%v.var.1) +// CHECK:STDOUT: assign %x.var, %F.call.loc13 +// CHECK:STDOUT: %i32.loc13_17: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %x: ref %i32 = ref_binding x, %x.var +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %y.patt: %pattern_type.6b6 = ref_binding_pattern y [concrete = constants.%y.patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.ref.loc14: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %i32.loc14_38: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc14_34: Core.Form = ref_form %i32.loc14_38 [concrete = constants.%.512] +// CHECK:STDOUT: %v.ref.loc14: ref %i32 = name_ref v, %v +// CHECK:STDOUT: %.loc14_44: %i32 = ref_tag %v.ref.loc14 +// CHECK:STDOUT: %F.specific_fn.loc14: = specific_function %F.ref.loc14, @F(constants.%.512) [concrete = constants.%F.specific_fn.0c3] +// CHECK:STDOUT: %F.call.loc14: ref %i32 = call %F.specific_fn.loc14(%v.ref.loc14) +// CHECK:STDOUT: %i32.loc14_21: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %y: ref %i32 = ref_binding y, %F.call.loc14 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %z.patt: %pattern_type.6b6 = value_binding_pattern z [concrete = constants.%z.patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.ref.loc15: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %i32.loc15_34: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc15_30: Core.Form = value_form %i32.loc15_34 [concrete = constants.%.c2a] +// CHECK:STDOUT: %v.ref.loc15: ref %i32 = name_ref v, %v +// CHECK:STDOUT: %F.specific_fn.loc15: = specific_function %F.ref.loc15, @F(constants.%.c2a) [concrete = constants.%F.specific_fn.2f1] +// CHECK:STDOUT: %.loc15_40: %i32 = acquire_value %v.ref.loc15 +// CHECK:STDOUT: %F.call.loc15: %i32 = call %F.specific_fn.loc15(%.loc15_40) +// CHECK:STDOUT: %i32.loc15_17: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %z: %i32 = value_binding z, %F.call.loc15 +// CHECK:STDOUT: %Op.ref: %Destroy.assoc_type = name_ref Op, imports.%Core.import_ref.c64 [concrete = constants.%assoc0.ae8] +// CHECK:STDOUT: %impl.elem0.1: %.22e = impl_witness_access constants.%custom_witness.df9cc1.2, element0 [concrete = constants.%Destroy.Op.1a2547.2] +// CHECK:STDOUT: %bound_method.1: = bound_method %v.var.1, %impl.elem0.1 +// CHECK:STDOUT: %Destroy.Op.call.1: init %empty_tuple.type = call %bound_method.1(%v.var.1) +// CHECK:STDOUT: %Destroy.Op.bound.loc13: = bound_method %x.var, constants.%Destroy.Op.1a2547.2 +// CHECK:STDOUT: %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%x.var) +// CHECK:STDOUT: %Destroy.Op.bound.loc11: = bound_method %v.var.loc11, constants.%Destroy.Op.1a2547.2 +// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%v.var.loc11) +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F(constants.%Form) { -// CHECK:STDOUT: %Form.patt.loc4_10.2 => constants.%Form.patt -// CHECK:STDOUT: %Form.loc4_10.1 => constants.%Form -// CHECK:STDOUT: %.loc4_24.2 => constants.%.94f -// CHECK:STDOUT: %.loc4_24.3 => constants.%.42f +// CHECK:STDOUT: fn @Destroy.Op.1(%self.param: ref %i32.builtin) = "no_op"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Destroy.Op.2(%self.param: ref %i32) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%Fm) { +// CHECK:STDOUT: %Fm.patt.loc4_8.2 => constants.%Fm.patt +// CHECK:STDOUT: %Fm.loc4_8.1 => constants.%Fm +// CHECK:STDOUT: %.loc4_26.1 => constants.%.42f +// CHECK:STDOUT: %.loc4_23.2 => constants.%.cfa // CHECK:STDOUT: %pattern_type => constants.%pattern_type.177 -// CHECK:STDOUT: %.loc4_24.4 => constants.%.1ac -// CHECK:STDOUT: %return.patt.loc4_24.2 => constants.%return.patt.333 -// CHECK:STDOUT: %.loc4_24.5 => constants.%.82b +// CHECK:STDOUT: %.loc4_23.3 => constants.%.26b +// CHECK:STDOUT: %v.patt.loc4_23.2 => constants.%v.patt.cda +// CHECK:STDOUT: %.loc4_30.2 => constants.%.94f +// CHECK:STDOUT: %.loc4_30.3 => constants.%.1ac +// CHECK:STDOUT: %return.patt.loc4_30.2 => constants.%return.patt.333 +// CHECK:STDOUT: %.loc4_23.4 => constants.%.095 +// CHECK:STDOUT: %.loc4_30.4 => constants.%.efc +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.795) { +// CHECK:STDOUT: %Fm.patt.loc4_8.2 => constants.%Fm.patt +// CHECK:STDOUT: %Fm.loc4_8.1 => constants.%.795 +// CHECK:STDOUT: %.loc4_26.1 => constants.%i32 +// CHECK:STDOUT: %.loc4_23.2 => constants.%inst.splice_block +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6b6 +// CHECK:STDOUT: %.loc4_23.3 => constants.%v.var_patt.13561f.1 +// CHECK:STDOUT: %v.patt.loc4_23.2 => constants.%v.patt.b2b +// CHECK:STDOUT: %.loc4_30.2 => constants.%inst.out_param_pattern +// CHECK:STDOUT: %.loc4_30.3 => constants.%return.param_patt.a9a4c7.1 +// CHECK:STDOUT: %return.patt.loc4_30.2 => constants.%return.patt.e1b +// CHECK:STDOUT: %.loc4_23.4 => constants.%.095 +// CHECK:STDOUT: %.loc4_30.4 => constants.%.efc +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %require_complete => constants.%complete_type.f8a +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.512) { +// CHECK:STDOUT: %Fm.patt.loc4_8.2 => constants.%Fm.patt +// CHECK:STDOUT: %Fm.loc4_8.1 => constants.%.512 +// CHECK:STDOUT: %.loc4_26.1 => constants.%i32 +// CHECK:STDOUT: %.loc4_23.2 => constants.%inst.ref_param_pattern +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6b6 +// CHECK:STDOUT: %.loc4_23.3 => constants.%v.param_patt.e9ad17.1 +// CHECK:STDOUT: %v.patt.loc4_23.2 => constants.%v.patt.5c0 +// CHECK:STDOUT: %.loc4_30.2 => constants.%inst.ref_return_pattern +// CHECK:STDOUT: %.loc4_30.3 => constants.%.ae0167.1 +// CHECK:STDOUT: %return.patt.loc4_30.2 => constants.%return.patt.c62 +// CHECK:STDOUT: %.loc4_23.4 => constants.%.095 +// CHECK:STDOUT: %.loc4_30.4 => constants.%.efc +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %require_complete => constants.%complete_type.f8a +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F(constants.%.c2a) { +// CHECK:STDOUT: %Fm.patt.loc4_8.2 => constants.%Fm.patt +// CHECK:STDOUT: %Fm.loc4_8.1 => constants.%.c2a +// CHECK:STDOUT: %.loc4_26.1 => constants.%i32 +// CHECK:STDOUT: %.loc4_23.2 => constants.%inst.value_param_pattern +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6b6 +// CHECK:STDOUT: %.loc4_23.3 => constants.%v.param_patt.733534.1 +// CHECK:STDOUT: %v.patt.loc4_23.2 => constants.%v.patt.971 +// CHECK:STDOUT: %.loc4_30.2 => constants.%inst.value_return_pattern +// CHECK:STDOUT: %.loc4_30.3 => constants.%.1a588f.1 +// CHECK:STDOUT: %return.patt.loc4_30.2 => constants.%return.patt.45a +// CHECK:STDOUT: %.loc4_23.4 => constants.%.095 +// CHECK:STDOUT: %.loc4_30.4 => constants.%.efc +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %require_complete => constants.%complete_type.f8a // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_todo_form_thunk.carbon b/toolchain/check/testdata/impl/fail_todo_form_thunk.carbon deleted file mode 100644 index 96f7ab6de071..000000000000 --- a/toolchain/check/testdata/impl/fail_todo_form_thunk.carbon +++ /dev/null @@ -1,27 +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 -// -// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/form.carbon -// -// AUTOUPDATE -// TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_todo_form_thunk.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_todo_form_thunk.carbon - -interface I { - let T:! type; - let Fm:! Core.Form; - // CHECK:STDERR: fail_todo_form_thunk.carbon:[[@LINE+4]]:8: error: semantics TODO: `Support symbolic form bindings` [SemanticsTodo] - // CHECK:STDERR: fn F(x:? Fm, y: T); - // CHECK:STDERR: ^~~~~~ - // CHECK:STDERR: - fn F(x:? Fm, y: T); -} - -class C { - impl as I where .T = () and .Fm = form(ref ()) { - fn F(x:? form(ref ()), ()); - } -} diff --git a/toolchain/check/testdata/impl/impl_thunk.carbon b/toolchain/check/testdata/impl/impl_thunk.carbon index f335c8a437ce..605fa9029626 100644 --- a/toolchain/check/testdata/impl/impl_thunk.carbon +++ b/toolchain/check/testdata/impl/impl_thunk.carbon @@ -125,6 +125,22 @@ impl B as X { //@dump-sem-ir-end } +// --- form_parameter.carbon + +interface I { + let T:! type; + let Fm:! Core.Form; + fn F(x:? Fm, y: {.a: (), .b: ()}); +} + +class C { + impl as I where .T = () and .Fm = form(ref ()) { + //@dump-sem-ir-begin + fn F(x:? form(ref ()), y: {.b: (), .a: ()}); + //@dump-sem-ir-end + } +} + // --- fail_inheritance_value_conversion_copy_return.carbon library "[[@TEST_NAME]]"; @@ -330,7 +346,6 @@ impl () as I({}) { //@dump-sem-ir-end } - // CHECK:STDOUT: --- struct_conversion.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -871,6 +886,87 @@ impl () as I({}) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- form_parameter.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %empty_tuple.type, .b: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %.9f9: Core.Form = ref_form %empty_tuple.type [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.param_patt.363cc0.1: %pattern_type.cb1 = ref_param_pattern [concrete] +// CHECK:STDOUT: %x.patt.b18d0b.1: %pattern_type.cb1 = at_binding_pattern x, %x.param_patt.363cc0.1 [concrete] +// CHECK:STDOUT: %struct_type.b.a: type = struct_type {.b: %empty_tuple.type, .a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.120: type = pattern_type %struct_type.b.a [concrete] +// CHECK:STDOUT: %y.param_patt.618: %pattern_type.120 = value_param_pattern [concrete] +// CHECK:STDOUT: %y.patt.b7b: %pattern_type.120 = at_binding_pattern y, %y.param_patt.618 [concrete] +// CHECK:STDOUT: %C.as.I.impl.F.type.a24f58.1: type = fn_type @C.as.I.impl.F.loc11_48.1 [concrete] +// CHECK:STDOUT: %C.as.I.impl.F.4c1488.1: %C.as.I.impl.F.type.a24f58.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %C.as.I.impl.F.type.a24f58.2: type = fn_type @C.as.I.impl.F.loc11_48.2 [concrete] +// CHECK:STDOUT: %C.as.I.impl.F.4c1488.2: %C.as.I.impl.F.type.a24f58.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @C.as.I.impl: %Self.ref as %.loc9_13 { +// CHECK:STDOUT: %C.as.I.impl.F.decl.loc11_48.1: %C.as.I.impl.F.type.a24f58.1 = fn_decl @C.as.I.impl.F.loc11_48.1 [concrete = constants.%C.as.I.impl.F.4c1488.1] { +// CHECK:STDOUT: %x.param_patt: %pattern_type.cb1 = ref_param_pattern [concrete = constants.%x.param_patt.363cc0.1] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = at_binding_pattern x, %x.param_patt [concrete = constants.%x.patt.b18d0b.1] +// CHECK:STDOUT: %y.param_patt: %pattern_type.120 = value_param_pattern [concrete = constants.%y.param_patt.618] +// CHECK:STDOUT: %y.patt: %pattern_type.120 = at_binding_pattern y, %y.param_patt [concrete = constants.%y.patt.b7b] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: ref %empty_tuple.type = ref_param call_param0 +// CHECK:STDOUT: %.loc11_19.1: Core.Form = splice_block %.loc11_19.2 [concrete = constants.%.9f9] { +// CHECK:STDOUT: %.loc11_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc11_24.2: type = converted %.loc11_24.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %.loc11_19.2: Core.Form = ref_form %.loc11_24.2 [concrete = constants.%.9f9] +// CHECK:STDOUT: %.loc11_19.3: type = type_component_of %.loc11_19.2 [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x: ref %empty_tuple.type = ref_binding x, %x.param +// CHECK:STDOUT: %y.param: %struct_type.b.a = value_param call_param1 +// CHECK:STDOUT: %.loc11_46: type = splice_block %struct_type.b.a [concrete = constants.%struct_type.b.a] { +// CHECK:STDOUT: %.loc11_37.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc11_37.2: type = converted %.loc11_37.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %.loc11_45.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc11_45.2: type = converted %.loc11_45.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %struct_type.b.a: type = struct_type {.b: %empty_tuple.type, .a: %empty_tuple.type} [concrete = constants.%struct_type.b.a] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y: %struct_type.b.a = value_binding y, %y.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.as.I.impl.F.decl.loc11_48.2: %C.as.I.impl.F.type.a24f58.2 = fn_decl @C.as.I.impl.F.loc11_48.2 [concrete = constants.%C.as.I.impl.F.4c1488.2] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %C.as.I.impl.F.decl.loc11_48.1 +// CHECK:STDOUT: extend %.loc9_13 +// CHECK:STDOUT: witness = %I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .I = +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @C.as.I.impl.F.loc11_48.1(%x.param: ref %empty_tuple.type, %y.param: %struct_type.b.a); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @C.as.I.impl.F.loc11_48.2(%x.param: ref %empty_tuple.type, %y.param: %struct_type.a.b) [thunk @C.as.I.impl.%C.as.I.impl.F.decl.loc11_48.1 for @I.WithSelf.%I.WithSelf.F.decl, @I.WithSelf.F(constants.%I.facet)] { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %C.as.I.impl.F.type.a24f58.1 = name_ref F, @C.as.I.impl.%C.as.I.impl.F.decl.loc11_48.1 [concrete = constants.%C.as.I.impl.F.4c1488.1] +// CHECK:STDOUT: +// CHECK:STDOUT: %C.as.I.impl.F.call: init %empty_tuple.type = call %F.ref(%x.param, %.5) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_inheritance_value_conversion_copy_return.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/lower/handle.cpp b/toolchain/lower/handle.cpp index 37ee1a29c523..fee05f20ed13 100644 --- a/toolchain/lower/handle.cpp +++ b/toolchain/lower/handle.cpp @@ -120,6 +120,11 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, context.SetLocal(inst_id, context.GetValue(inst.value_id)); } +auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, + SemIR::WrapperBinding inst) -> void { + context.SetLocal(inst_id, context.GetValue(inst.value_id)); +} + auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, SemIR::BlockArg inst) -> void { context.SetLocal( diff --git a/toolchain/sem_ir/expr_info.cpp b/toolchain/sem_ir/expr_info.cpp index c55e2f751f36..e6e93d66593b 100644 --- a/toolchain/sem_ir/expr_info.cpp +++ b/toolchain/sem_ir/expr_info.cpp @@ -22,8 +22,15 @@ static auto AsAnyInstId(IdAndKind arg) -> InstId { return arg.As(); } +struct ExprCategoryResult { + ExprCategory category; + InstId inner_inst_id; +}; + +// Returns the expression category of `inst_id`, and the ID of the innermost +// inst visited while determining that category. static auto GetExprCategoryImpl(const File* ir, InstId inst_id) - -> ExprCategory { + -> ExprCategoryResult { // The overall expression category if the current instruction is a value // expression. ExprCategory value_category = ExprCategory::Value; @@ -34,8 +41,10 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id) // If this instruction kind has a fixed category, return it. if (auto fixed_category = category_from_kind.TryAsFixedCategory()) { - return *fixed_category == ExprCategory::Value ? value_category - : *fixed_category; + return {.category = *fixed_category == ExprCategory::Value + ? value_category + : *fixed_category, + .inner_inst_id = inst_id}; } // Handle any special cases that use @@ -107,8 +116,10 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id) // operand. switch (*category_from_kind.TryAsComputedCategory()) { case ComputedExprCategory::ValueIfHasType: { - return untyped_inst.kind().has_type() ? value_category - : ExprCategory::NotExpr; + return {.category = untyped_inst.kind().has_type() + ? value_category + : ExprCategory::NotExpr, + .inner_inst_id = inst_id}; } case ComputedExprCategory::SameAsFirstOperand: { @@ -127,7 +138,7 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id) case TypedInstT::Kind: { \ auto category = handle_special_case(untyped_inst.As()); \ if (category.has_value()) { \ - return *category; \ + return {.category = *category, .inner_inst_id = inst_id}; \ } \ break; \ } @@ -139,7 +150,7 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id) } auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory { - return GetExprCategoryImpl(&file, inst_id); + return GetExprCategoryImpl(&file, inst_id).category; } auto FindStorageArgForInitializer(const File& sem_ir, InstId init_id, @@ -258,11 +269,11 @@ static auto GetDecomposedFormKindForType(const File& sem_ir, TypeId type_id) return FormInfo::Primitive; } -auto GetFormInfo(const File& sem_ir, InstId inst_id) -> FormInfo { +auto GetFormInfo(const File& sem_ir, SemIR::InstId inst_id) -> FormInfo { auto inst = sem_ir.insts().Get(inst_id); - ExprCategory category = GetExprCategory(sem_ir, inst_id); - if (inst.type_id() == ErrorInst::TypeId) { + auto [category, inner_inst_id] = GetExprCategoryImpl(&sem_ir, inst_id); + if (inst.type_id() == SemIR::ErrorInst::TypeId) { // TODO: Should `GetExprCategory` do this? category = ExprCategory::Error; } @@ -275,10 +286,25 @@ auto GetFormInfo(const File& sem_ir, InstId inst_id) -> FormInfo { sem_ir.types().GetAsInst(inst.type_id())); } + auto form_inst_id = InstId::None; + if (category == ExprCategory::Dependent) { + kind = FormInfo::Dependent; + // TODO: Generalize this logic to handle other kinds of form-dependent insts + // besides references to `:?` bindings. + auto splice = sem_ir.insts().GetAs(inner_inst_id); + auto param_action = + sem_ir.insts().GetAs(splice.inst_id); + auto args = sem_ir.bundles().Get(param_action.args_id); + splice = sem_ir.insts().GetAs(args.pattern_id); + auto pattern = sem_ir.insts().GetAs(splice.inst_id); + form_inst_id = pattern.form_id; + } + return {.kind = kind, .category = category, .type_id = inst.type_id(), .constant_id = sem_ir.constant_values().Get(inst_id), + .form_inst_id = form_inst_id, .loc_id = LocId(inst_id), .inst_id = inst_id}; } @@ -324,12 +350,15 @@ auto VisitTupleElementForms(const File& sem_ir, FormInfo form, for (auto [type_inst_id, const_inst_id] : llvm::zip_longest(element_type_inst_ids, tuple_const_inst_ids)) { + // TODO: figure out how to update the category if it's `Mixed`, and + // how to populate `form_inst_id` if the updated category is `Dependent`. visitor({.kind = FormInfo::Primitive, .category = form.category, .type_id = sem_ir.types().GetTypeIdForTypeInstId(*type_inst_id), .constant_id = const_inst_id ? sem_ir.constant_values().Get(*const_inst_id) : ConstantId::NotConstant, + .form_inst_id = InstId::None, .loc_id = form.loc_id, .inst_id = InstId::None}); } @@ -357,6 +386,8 @@ auto VisitStructElementForms(const File& sem_ir, FormInfo form, for (auto [field, const_inst_id] : llvm::zip_longest(fields, struct_const_inst_ids)) { + // TODO: figure out how to update the category if it's `Mixed`, and + // how to populate `form_inst_id` if the updated category is `Dependent`. visitor( {.kind = FormInfo::Primitive, .category = form.category, @@ -364,6 +395,7 @@ auto VisitStructElementForms(const File& sem_ir, FormInfo form, .constant_id = const_inst_id ? sem_ir.constant_values().Get(*const_inst_id) : ConstantId::NotConstant, + .form_inst_id = InstId::None, .loc_id = form.loc_id, .inst_id = InstId::None}); } diff --git a/toolchain/sem_ir/expr_info.h b/toolchain/sem_ir/expr_info.h index 4f52aea09bee..47a95fe09763 100644 --- a/toolchain/sem_ir/expr_info.h +++ b/toolchain/sem_ir/expr_info.h @@ -42,9 +42,15 @@ auto FindStorageArgForInitializer(const File& sem_ir, InstId init_id, // Information about the form of an expression. struct FormInfo { enum Kind : int8_t { + // A primitive form (which has independent type, category, phase, and + // value). Primitive, + // A tuple form. Tuple, + // A struct form. Struct, + // A form whose kind depends on the value of one or more symbolic bindings. + Dependent, }; // The kind of the form. @@ -57,6 +63,9 @@ struct FormInfo { SemIR::TypeId type_id; // The constant value component of the form. SemIR::ConstantId constant_id; + // For a Dependent form, this is an inst whose constant value represents + // the form. Otherwise, it is None. + SemIR::InstId form_inst_id; // The location of the expression whose form this is. SemIR::LocId loc_id; // The underlying instruction, if there is one. This is only present in order diff --git a/toolchain/sem_ir/id_kind.h b/toolchain/sem_ir/id_kind.h index ac89838db70c..a05eafaea3b6 100644 --- a/toolchain/sem_ir/id_kind.h +++ b/toolchain/sem_ir/id_kind.h @@ -33,6 +33,7 @@ using IdKind = TypeEnum< AssociatedConstantId, BoolValue, BundleId, + BundleId, CallParamIndex, CharId, ClangDeclId, diff --git a/toolchain/sem_ir/inst_categories.h b/toolchain/sem_ir/inst_categories.h index 9bddb5acfdae..2acd4253f765 100644 --- a/toolchain/sem_ir/inst_categories.h +++ b/toolchain/sem_ir/inst_categories.h @@ -143,7 +143,8 @@ struct AnyBindingPattern { X(::Carbon::SemIR::AliasBinding) Sep() \ X(::Carbon::SemIR::RefBinding) Sep() \ X(::Carbon::SemIR::SymbolicBinding) Sep() \ - X(::Carbon::SemIR::ValueBinding) + X(::Carbon::SemIR::ValueBinding) Sep() \ + X(::Carbon::SemIR::WrapperBinding) // clang-format on #define AnyBinding_CARBON_KIND_ANY_EXPAND \ @@ -160,6 +161,7 @@ struct AnyBinding { // The value is inline in the inst so that value access doesn't require an // indirection. + // TODO: rename to `result_id` since it's not necessarily a value. InstId value_id; }; diff --git a/toolchain/sem_ir/inst_kind.def b/toolchain/sem_ir/inst_kind.def index 3ed1c1f64b91..0e980220a21e 100644 --- a/toolchain/sem_ir/inst_kind.def +++ b/toolchain/sem_ir/inst_kind.def @@ -44,6 +44,7 @@ CARBON_SEM_IR_INST_KIND(BranchIf) CARBON_SEM_IR_INST_KIND(BranchWithArg) CARBON_SEM_IR_INST_KIND(Call) CARBON_SEM_IR_INST_KIND(CalleePatternMatchAction) +CARBON_SEM_IR_INST_KIND(CallerPatternMatchAction) CARBON_SEM_IR_INST_KIND(CharLiteralType) CARBON_SEM_IR_INST_KIND(CharLiteralValue) CARBON_SEM_IR_INST_KIND(ClassDecl) @@ -183,6 +184,7 @@ CARBON_SEM_IR_INST_KIND(VtableType) CARBON_SEM_IR_INST_KIND(VtablePtr) CARBON_SEM_IR_INST_KIND(WhereExpr) CARBON_SEM_IR_INST_KIND(WitnessType) +CARBON_SEM_IR_INST_KIND(WrapperBinding) CARBON_SEM_IR_INST_KIND(WrapperBindingPattern) #undef CARBON_SEM_IR_INST_KIND diff --git a/toolchain/sem_ir/inst_kind.h b/toolchain/sem_ir/inst_kind.h index f74b2e334e7b..1c5cdf244b2f 100644 --- a/toolchain/sem_ir/inst_kind.h +++ b/toolchain/sem_ir/inst_kind.h @@ -439,7 +439,9 @@ class InstKind::Definition : public InstKind { // kind is always symbolic when it's a value, then it's always symbolic when // it's a type. return is_type() != InstIsType::Never && - (constant_kind() == InstConstantKind::SymbolicOnly || + (constant_kind() == InstConstantKind::Indirect || + constant_kind() == InstConstantKind::ConstantInstAction || + constant_kind() == InstConstantKind::SymbolicOnly || constant_kind() == InstConstantKind::SymbolicOrReference); } diff --git a/toolchain/sem_ir/stringify.cpp b/toolchain/sem_ir/stringify.cpp index 1ff0b397759e..bca0e460c999 100644 --- a/toolchain/sem_ir/stringify.cpp +++ b/toolchain/sem_ir/stringify.cpp @@ -453,6 +453,11 @@ class Stringifier { ">"); } + auto StringifyInst(InstId /*inst_id*/, SpliceInst inst) -> void { + *out_ << "Push(inst.inst_id, ">"); + } + // Determine the specific interface that an impl witness instruction provides // an implementation of. // TODO: Should we track this in the type? diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index e38814b3abad..1c3a2573c911 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -388,11 +388,13 @@ struct Call { InstBlockId args_id; }; +// An action that performs callee-side pattern matching for a single syntactic +// parameter. struct CalleePatternMatchAction { static constexpr auto Kind = InstKind::CalleePatternMatchAction.Define( {.ir_name = "callee_pattern_match_action", - .expr_category = ExprCategory::Value, + .expr_category = ExprCategory::Dependent, .constant_kind = InstConstantKind::InstAction, .is_lowered = false}); @@ -400,7 +402,9 @@ struct CalleePatternMatchAction { // a bundle to validate `BundleStore` until a followup PR introduces a // "real" use case. struct Args { + // The parameter pattern to be matched. MetaInstId pattern_id; + // The index of the parameter in the `Call` parameter list. CallParamIndex parent_index; }; @@ -408,6 +412,29 @@ struct CalleePatternMatchAction { BundleId args_id; }; +// An action that performs caller-side pattern matching for a single syntactic +// parameter. +struct CallerPatternMatchAction { + static constexpr auto Kind = + InstKind::CallerPatternMatchAction.Define( + {.ir_name = "caller_pattern_match_action", + .expr_category = ExprCategory::Dependent, + .constant_kind = InstConstantKind::InstAction, + .is_lowered = false}); + + TypeId type_id; + + struct Args { + // The parameter pattern to be matched. + MetaInstId pattern_id; + // The corresponding syntactic argument. + MetaInstId arg_id; + // The specific to substitute into the parameter pattern. + SpecificId callee_specific_id; + }; + BundleId args_id; +}; + // A unicode code point character literal. This type only provides compile-time // operations, and is represented as an empty type at runtime. // @@ -2062,12 +2089,11 @@ struct TupleValue { // Extracts the type component of `form_inst_id`, which must have type // `Core.Form`. struct TypeComponentOf { - static constexpr auto Kind = - InstKind::TypeComponentOf.Define( - {.ir_name = "type_component_of", - .is_type = InstIsType::Always, - .constant_kind = InstConstantKind::SymbolicOnly, - .is_lowered = false}); + static constexpr auto Kind = InstKind::TypeComponentOf.Define( + {.ir_name = "type_component_of", + .is_type = InstIsType::Always, + .constant_kind = InstConstantKind::SymbolicOnly, + .is_lowered = false}); // Always TypeType. TypeId type_id; @@ -2382,6 +2408,20 @@ struct WhereExpr { // standard type and be removed. using WitnessType = SingletonTypeInst">; +// Binds a name to a result (which must not be an initializing expression), +// forwarding its type and category. See `AnyBinding` for member documentation. +// +// TODO: replace RefBinding and ValueBinding (and possibly SymbolicBinding) with +// WrapperBinding. +struct WrapperBinding { + static constexpr auto Kind = InstKind::WrapperBinding.Define( + {.ir_name = "wrapper_binding", + .expr_category = ComputedExprCategory::SameAsSecondOperand}); + TypeId type_id; + EntityNameId entity_name_id; + InstId value_id; +}; + // A binding pattern that binds a name to the result of matching // `subpattern_id` against this pattern's scrutinee. Currently there is no // explicit syntax for such a pattern, but it arises implicitly when handling