Basic support for symbolic forms (#7408)

This commit is contained in:
Geoff Romer
2026-06-25 22:46:48 +00:00
committed by GitHub
parent 5aae6a1ca5
commit 8158d4ffd4
24 changed files with 836 additions and 204 deletions
+11 -1
View File
@@ -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 <typename IdT>
requires SemIR::Internal::IsIdKindType<IdT>
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();
}
+4
View File
@@ -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;
+6 -2
View File
@@ -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};
+8
View File
@@ -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;
}
+1
View File
@@ -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:
+10
View File
@@ -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;
+4 -5
View File
@@ -384,7 +384,7 @@ auto CheckFunctionDefinitionSignature(Context& context,
// The parameter types need to be complete.
RequireCompleteType(
context, context.insts().GetAs<SemIR::AnyParam>(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<SemIR::AnyParam>(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));
}
}
}
@@ -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<SemIR::TypeComponentOf>()) {
return context.TODO(node_id, "Support symbolic form bindings");
}
SemIR::ExprRegionId type_expr_region_id =
ConsumeSubpatternExpr(context, type_expr.inst_id);
+3
View File
@@ -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);
+39 -5
View File
@@ -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<SemIR::CallerPatternMatchAction::Args>(
{.pattern_id = specific_pattern_id,
.arg_id = scrutinee_id,
.callee_specific_id = specific_id_stack_.back()});
caller_state->call_args.push_back(
HandleAction<SemIR::CallerPatternMatchAction>(
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<SemIR::CalleePatternMatchAction>(
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<SemIR::CalleePatternMatchAction::Args>(
{.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);
+26 -2
View File
@@ -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);
}
+86 -84
View File
@@ -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<none>, has_error: false, extended_scopes: [], names: {name(Core): inst70000011, name0: inst7000002F}}
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, 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<none>, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
// CHECK:STDOUT: entity_name70000001: {name: name1, parent_scope: name_scope70000001, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
// CHECK:STDOUT: entity_name70000002: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
// 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<none>}
// CHECK:STDOUT: generic70000000: {decl: inst70000030, bindings: inst_block7000000B, self_specific_id: specific70000000, decl_block_id: inst_block7000000D, definition_block_id: inst_block<none>}
// 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<none>, 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<none>, type: type(inst(FormType))}
// CHECK:STDOUT: inst7000001E: {kind: SymbolicBinding, arg0: entity_name70000002, arg1: inst<none>, 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<none>, 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<none>, 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: {}
+424 -53
View File
@@ -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 <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: <instruction> = 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: <instruction> = 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: <instruction> = 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: <instruction> = callee_pattern_match_action %.1ac, call_param0 [template]
// CHECK:STDOUT: %.095: <instruction> = callee_pattern_match_action %.f15, call_param0 [template]
// CHECK:STDOUT: %.efc: <instruction> = 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: <witness> = 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: <witness> = 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: <witness> = 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> = 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> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <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: <instruction> = 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: <instruction> = 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> = 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: <witness> = 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> = 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: <instruction> = 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: <instruction> = 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> = 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: <instruction> = 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: <instruction> = 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> = 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: <witness> = 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> = 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> = 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: <namespace> = 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: <instruction> = 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: <instruction> = 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: <instruction> = callee_pattern_match_action constants.%.f15, call_param0 [template]
// CHECK:STDOUT: %.loc4_30.4: <instruction> = callee_pattern_match_action constants.%.677, call_param1 [template]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete: <witness> = 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: <instruction> = 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: <instruction> = 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> = bound_method %int_0, %impl.elem0.loc11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %specific_fn.loc11: <specific function> = 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> = 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> = 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> = bound_method %.loc13_40, %impl.elem0.loc13
// CHECK:STDOUT: %specific_fn.loc13: <specific function> = 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> = 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> = 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> = 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> = 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> = 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> = 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:
@@ -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 ()), ());
}
}
+97 -1
View File
@@ -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: <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: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: <elided>
// 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: <elided>
// CHECK:STDOUT: complete_type_witness = %complete_type
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C
// CHECK:STDOUT: .I = <poisoned>
// 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: <elided>
// 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 {
+5
View File
@@ -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(
+42 -10
View File
@@ -22,8 +22,15 @@ static auto AsAnyInstId(IdAndKind arg) -> InstId {
return arg.As<SemIR::AbsoluteInstId>();
}
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<TypedInstT>()); \
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<SpliceInst>(inner_inst_id);
auto param_action =
sem_ir.insts().GetAs<CalleePatternMatchAction>(splice.inst_id);
auto args = sem_ir.bundles().Get(param_action.args_id);
splice = sem_ir.insts().GetAs<SpliceInst>(args.pattern_id);
auto pattern = sem_ir.insts().GetAs<FormParamPatternAction>(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});
}
+9
View File
@@ -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
+1
View File
@@ -33,6 +33,7 @@ using IdKind = TypeEnum<
AssociatedConstantId,
BoolValue,
BundleId<CalleePatternMatchAction::Args>,
BundleId<CallerPatternMatchAction::Args>,
CallParamIndex,
CharId,
ClangDeclId,
+3 -1
View File
@@ -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;
};
+2
View File
@@ -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
+3 -1
View File
@@ -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);
}
+5
View File
@@ -453,6 +453,11 @@ class Stringifier {
">");
}
auto StringifyInst(InstId /*inst_id*/, SpliceInst inst) -> void {
*out_ << "<splice of ";
step_stack_->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?
+47 -7
View File
@@ -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<Parse::NodeId>(
{.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> args_id;
};
// An action that performs caller-side pattern matching for a single syntactic
// parameter.
struct CallerPatternMatchAction {
static constexpr auto Kind =
InstKind::CallerPatternMatchAction.Define<Parse::NodeId>(
{.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> 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<Parse::NoneNodeId>(
{.ir_name = "type_component_of",
.is_type = InstIsType::Always,
.constant_kind = InstConstantKind::SymbolicOnly,
.is_lowered = false});
static constexpr auto Kind = InstKind::TypeComponentOf.Define<Parse::NodeId>(
{.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<InstKind::WitnessType, "<witness>">;
// 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<Parse::NodeId>(
{.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