diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 901d3dabd10c..c560a86c035d 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -73,6 +73,7 @@ cc_library( "require_impls_stack.cpp", "return.cpp", "scope_stack.cpp", + "struct.cpp", "subst.cpp", "thunk.cpp", "type.cpp", @@ -147,6 +148,7 @@ cc_library( "return.h", "scope_index.h", "scope_stack.h", + "struct.h", "subst.h", "thunk.h", "type.h", diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 913112cf1f47..cfd699858c74 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -518,7 +518,8 @@ class Context { // - The associated entries witness table, while parsing an interface. InstBlockStack args_type_info_stack_; - // The stack of StructTypeFields for in-progress StructTypeLiterals. + // The stack of StructTypeFields for in-progress StructTypeLiterals, + // StructLiteral values, and StructPatterns. ArrayStack struct_type_fields_stack_; // The stack of FieldDecls for in-progress Class definitions. diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 034e3cfb8d11..892270a13bc1 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -42,9 +42,11 @@ static auto GetLeafBindingPatternInstKind(Parse::NodeKind node_kind, case Parse::NodeKind::CompileTimeBindingPattern: return SemIR::InstKind::SymbolicBindingPattern; case Parse::NodeKind::LetBindingPattern: + case Parse::NodeKind::StructPatternFieldLetBindingPattern: return is_ref ? SemIR::InstKind::RefBindingPattern : SemIR::InstKind::ValueBindingPattern; case Parse::NodeKind::VarBindingPattern: + case Parse::NodeKind::StructPatternFieldVarBindingPattern: return SemIR::InstKind::RefBindingPattern; default: CARBON_FATAL("Unexpected node kind: {0}", node_kind); @@ -421,7 +423,9 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, case FullPatternStack::Kind::ExplicitParamList: { bool is_deduced = context.full_pattern_stack().CurrentKind() == FullPatternStack::Kind::ImplicitParamList; - bool is_var = node_kind == Parse::NodeKind::VarBindingPattern; + bool is_var = + node_kind == Parse::NodeKind::VarBindingPattern || + node_kind == Parse::NodeKind::StructPatternFieldVarBindingPattern; if (!IsValidParamForIntroducer(context, node_id, name_id, introducer.kind, is_generic, is_deduced, is_var)) { if (name_id != SemIR::NameId::Underscore) { @@ -435,7 +439,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, // Using `AsConcreteType` here causes `fn F[var self: Self]();` // to fail since `Self` is an incomplete type. - if (node_kind == Parse::NodeKind::VarBindingPattern) { + if (is_var) { auto [unqualified_type_id, qualifiers] = context.types().GetUnqualifiedTypeAndQualifiers( type_expr.type_component_id); @@ -463,6 +467,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, // enclosing `var` pattern is), or it's a compile-time binding pattern // (because then it's not passed to the `Call` inst). case Parse::NodeKind::LetBindingPattern: + case Parse::NodeKind::StructPatternFieldLetBindingPattern: case Parse::NodeKind::FormBindingPattern: { auto param_pattern_id = SemIR::InstId::None; auto pattern_type_id = @@ -497,6 +502,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, break; } case Parse::NodeKind::VarBindingPattern: + case Parse::NodeKind::StructPatternFieldVarBindingPattern: result_inst_id = make_binding_pattern(SemIR::RefBindingPattern::Kind); break; case Parse::NodeKind::CompileTimeBindingPattern: @@ -506,6 +512,20 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, default: CARBON_FATAL("Unexpected node kind {0}", node_kind); } + + if (node_kind == Parse::NodeKind::StructPatternFieldLetBindingPattern || + node_kind == Parse::NodeKind::StructPatternFieldVarBindingPattern) { + auto type_inst_id = + context.types().GetTypeInstId(type_expr.type_component_id); + + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_inst_id = type_inst_id}); + + // Put the name node back on the stack for inspection when handling the + // struct pattern. + context.node_stack().Push(name_node, name_id); + } + context.node_stack().Push(node_id, result_inst_id); break; } @@ -524,7 +544,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, builder.Attach(type_expr.node_id, IncompleteTypeInBindingDecl, type_expr.inst_id); }; - if (node_kind == Parse::NodeKind::VarBindingPattern) { + if (node_kind == Parse::NodeKind::VarBindingPattern || + node_kind == Parse::NodeKind::StructPatternFieldVarBindingPattern) { if (!RequireConcreteType( context, type_expr.type_component_id, type_expr.node_id, incomplete_diagnostic_context, abstract_diagnostic_context)) { @@ -540,7 +561,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, auto binding_pattern_id = make_binding_pattern( GetLeafBindingPatternInstKind(node_kind, is_ref)); - if (node_kind == Parse::NodeKind::VarBindingPattern) { + if (node_kind == Parse::NodeKind::VarBindingPattern || + node_kind == Parse::NodeKind::StructPatternFieldVarBindingPattern) { CARBON_CHECK(!is_generic); if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Returned)) { @@ -555,6 +577,18 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, type_expr.node_id, type_expr.type_component_id, bind_id, name_id); } } + if (node_kind == Parse::NodeKind::StructPatternFieldLetBindingPattern || + node_kind == Parse::NodeKind::StructPatternFieldVarBindingPattern) { + auto type_inst_id = + context.types().GetTypeInstId(type_expr.type_component_id); + + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_inst_id = type_inst_id}); + + // Put the name node back on the stack for inspection when handling the + // struct pattern. + context.node_stack().Push(name_node, name_id); + } context.node_stack().Push(node_id, binding_pattern_id); break; } @@ -579,6 +613,22 @@ auto HandleParseNode(Context& context, Parse::LetBindingPatternId node_id) Parse::NodeKind::BindingPatternTypeStart); } +auto HandleParseNode(Context& context, + Parse::StructPatternFieldLetBindingPatternId node_id) + -> bool { + return HandleAnyBindingPattern( + context, node_id, Parse::NodeKind::StructPatternFieldLetBindingPattern, + Parse::NodeKind::BindingPatternTypeStart); +} + +auto HandleParseNode(Context& context, + Parse::StructPatternFieldVarBindingPatternId node_id) + -> bool { + return HandleAnyBindingPattern( + context, node_id, Parse::NodeKind::StructPatternFieldVarBindingPattern, + Parse::NodeKind::BindingPatternTypeStart); +} + auto HandleParseNode(Context& context, Parse::SelfBindingPatternId node_id) -> bool { // A `self` binding with an omitted type behaves like `self: Self`. There is diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index 17c2f4deae1f..9f2e7391e756 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -9,8 +9,10 @@ #include "toolchain/check/handle.h" #include "toolchain/check/inst.h" #include "toolchain/check/pattern.h" +#include "toolchain/check/struct.h" #include "toolchain/check/type.h" #include "toolchain/diagnostics/emitter.h" +#include "toolchain/diagnostics/format_providers.h" namespace Carbon::Check { @@ -39,7 +41,12 @@ auto HandleParseNode(Context& context, Parse::TuplePatternStartId node_id) auto HandleParseNode(Context& context, Parse::StructPatternStartId node_id) -> bool { - return context.TODO(node_id, "struct pattern start"); + EndEmptyExprRegionForPattern(context); + context.node_stack().Push(node_id); + context.struct_type_fields_stack().PushArray(); + context.param_and_arg_refs_stack().Push(); + BeginExprRegionForPattern(context); + return true; } auto HandleParseNode(Context& context, Parse::ExplicitParamListStartId node_id) @@ -137,12 +144,101 @@ auto HandleParseNode(Context& context, Parse::TuplePatternId node_id) -> bool { } auto HandleParseNode(Context& context, Parse::StructPatternId node_id) -> bool { - return context.TODO(node_id, "struct pattern"); + if (context.node_stack().PeekIs(Parse::NodeKind::StructPatternStart)) { + // End the pending region started by a trailing comma, or the opening + // delimiter of an empty list. + EndEmptyExprRegionForPattern(context); + } else { + // End the pending region for the last pattern in the list. + EndExprRegionForPattern(context, context.node_stack()); + } + + // TODO: Reject StructPatterns in classes during Parse, or treat patterns in a + // class scope as patterns and generate the FieldDecl insts in a later + // pattern-matching step. + if (context.scope_stack().TryGetCurrentScopeAs()) { + bool is_var = context.full_pattern_stack().IsCurrentKindClassScopeVarDecl(); + CARBON_DIAGNOSTIC( + FieldWithStructPattern, Error, + "found struct pattern in class member {0:var|let} declaration", + Diagnostics::BoolAsSelect); + context.emitter().Emit(node_id, FieldWithStructPattern, is_var); + + return false; + } + + if (context.node_stack().PeekIs(Parse::NodeKind::UnderscoreName)) { + return context.TODO(node_id, "Struct pattern underscore field"); + } + + if (!context.node_stack().PeekIs(Parse::NodeCategory::MemberName)) { + // Remove the last parameter from the node stack before collecting names. + context.param_and_arg_refs_stack().EndNoPop( + Parse::NodeKind::StructPatternStart); + } + + auto fields = context.struct_type_fields_stack().PeekArray(); + + llvm::SmallVector field_name_nodes = + PopStructFieldNameNodes(context, fields.size()); + + auto refs_id = context.param_and_arg_refs_stack().EndAndPop( + Parse::NodeKind::StructPatternStart); + + context.node_stack() + .PopAndDiscardSoloNodeId(); + + if (DiagnoseDuplicateNames(context, field_name_nodes, fields, + StructKind::StructPattern)) { + context.node_stack().Push(node_id, SemIR::ErrorInst::InstId); + } else { + auto type_id = GetPatternType( + context, + GetStructType(context, + context.struct_type_fields().AddCanonical(fields))); + + context.node_stack().Push( + node_id, + AddInst( + context, node_id, {.type_id = type_id, .elements_id = refs_id})); + } + + context.struct_type_fields_stack().PopArray(); + BeginExprRegionForPattern(context); + return true; } auto HandleParseNode(Context& context, Parse::StructPatternDesignatedFieldId node_id) -> bool { - return context.TODO(node_id, "struct pattern field"); + EndExprRegionForPattern(context, context.node_stack()); + + auto pattern_id = context.node_stack().PopPattern(); + auto pattern_type_id = context.insts().Get(pattern_id).type_id(); + auto name_id = context.node_stack().Peek(); + + // NOTE: This check is required for the case when the struct pattern is found + // in a class field, so the node_stack contains FieldDecls instead of + // Patterns. See the TODO in the HandleParseNode function for the + // StructPatternId. + if (context.sem_ir().types().TryGetAs(pattern_type_id)) { + auto type_id = ExtractScrutineeType(context.sem_ir(), pattern_type_id); + + auto type_inst = context.types().GetTypeInstId(type_id); + + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_inst_id = type_inst}); + + context.node_stack().Push(node_id, pattern_id); + } else { + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_inst_id = SemIR::ErrorInst::TypeInstId}); + context.node_stack().Push(node_id, pattern_id); + } + + // Start a new pending `ExprRegion`, to maintain the invariant that one is + // pending at the end of handling for a pattern. + BeginExprRegionForPattern(context); + return true; } auto HandleParseNode(Context& context, Parse::PatternListCommaId /*node_id*/) diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 7df96f3106a7..07c6da82e44e 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -2,11 +2,11 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include "common/map.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" #include "toolchain/check/inst.h" +#include "toolchain/check/struct.h" #include "toolchain/check/type.h" #include "toolchain/check/unused.h" #include "toolchain/diagnostics/format_providers.h" @@ -77,47 +77,6 @@ auto HandleParseNode(Context& context, return true; } -// Diagnoses and returns true if there's a duplicate name. -static auto DiagnoseDuplicateNames( - Context& context, llvm::ArrayRef field_name_nodes, - llvm::ArrayRef fields, bool is_struct_type_literal) - -> bool { - Map names; - for (auto [field_name_node, field] : - llvm::zip_equal(field_name_nodes, fields)) { - auto result = names.Insert(field.name_id, field_name_node); - if (!result.is_inserted()) { - CARBON_DIAGNOSTIC(StructNameDuplicate, Error, - "duplicated field name `{1}` in " - "{0:struct type literal|struct literal}", - Diagnostics::BoolAsSelect, SemIR::NameId); - CARBON_DIAGNOSTIC_LABEL(StructNamePrevious, Info, - "field with the same name here"); - context.emitter() - .Build(result.value(), StructNameDuplicate, is_struct_type_literal, - field.name_id) - .Attach(field_name_node, StructNamePrevious) - .Emit(); - return true; - } - } - return false; -} - -// Pops the names of each field from the stack. These will have been left while -// handling struct fields. -static auto PopFieldNameNodes(Context& context, size_t field_count) - -> llvm::SmallVector { - llvm::SmallVector nodes; - nodes.reserve(field_count); - for ([[maybe_unused]] auto i : llvm::seq(field_count)) { - auto [name_node, _] = - context.node_stack().PopWithNodeId(); - nodes.push_back(name_node); - } - return nodes; -} - auto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool { if (!context.node_stack().PeekIs(Parse::NodeCategory::MemberName)) { // Remove the last parameter from the node stack before collecting names. @@ -127,7 +86,7 @@ auto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool { auto fields = context.struct_type_fields_stack().PeekArray(); llvm::SmallVector field_name_nodes = - PopFieldNameNodes(context, fields.size()); + PopStructFieldNameNodes(context, fields.size()); auto elements_id = context.param_and_arg_refs_stack().EndAndPop( Parse::NodeKind::StructLiteralStart); @@ -137,7 +96,7 @@ auto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool { .PopAndDiscardSoloNodeId(); if (DiagnoseDuplicateNames(context, field_name_nodes, fields, - /*is_struct_type_literal=*/false)) { + StructKind::StructLiteral)) { context.node_stack().Push(node_id, SemIR::ErrorInst::InstId); } else { auto type_id = GetStructType( @@ -156,14 +115,14 @@ auto HandleParseNode(Context& context, Parse::StructTypeLiteralId node_id) -> bool { auto fields = context.struct_type_fields_stack().PeekArray(); llvm::SmallVector field_name_nodes = - PopFieldNameNodes(context, fields.size()); + PopStructFieldNameNodes(context, fields.size()); context.scope_stack().Pop(/*check_unused=*/true); context.node_stack() .PopAndDiscardSoloNodeId(); if (DiagnoseDuplicateNames(context, field_name_nodes, fields, - /*is_struct_type_literal=*/true)) { + StructKind::StructTypeLiteral)) { context.node_stack().Push(node_id, SemIR::ErrorInst::InstId); } else { auto fields_id = context.struct_type_fields().AddCanonical(fields); diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 48700c56c630..bf27bdfc52bc 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -422,6 +422,7 @@ class NodeStack { case Parse::NodeKind::ShortCircuitOperandAnd: case Parse::NodeKind::ShortCircuitOperandOr: case Parse::NodeKind::StructLiteralField: + case Parse::NodeKind::StructPatternDesignatedField: return Id::KindFor(); case Parse::NodeKind::ExplicitParamList: case Parse::NodeKind::IfCondition: @@ -477,7 +478,6 @@ class NodeStack { case Parse::NodeKind::ReturnStatementStart: case Parse::NodeKind::StructLiteralStart: case Parse::NodeKind::StructPatternStart: - case Parse::NodeKind::StructPatternDesignatedField: case Parse::NodeKind::StructTypeLiteralField: case Parse::NodeKind::StructTypeLiteralStart: case Parse::NodeKind::TemplateBindingName: diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index 9ee455ed09ee..1f778acc5db9 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -23,6 +23,7 @@ #include "toolchain/check/type.h" #include "toolchain/diagnostics/format_providers.h" #include "toolchain/sem_ir/expr_info.h" +#include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst_kind.h" #include "toolchain/sem_ir/pattern.h" @@ -200,6 +201,8 @@ class MatchContext { SemIR::InstId scrutinee_id, WorkItem entry) -> void; auto DoPreWork(State state, SemIR::TuplePattern tuple_pattern, SemIR::InstId scrutinee_id, WorkItem entry) -> void; + auto DoPreWork(State state, SemIR::StructPattern struct_pattern, + SemIR::InstId scrutinee_id, WorkItem entry) -> void; auto DoPreWork(State state, SemIR::SpliceInst splice, SemIR::InstId scrutinee_id, WorkItem entry) -> void; auto DoPreWork(State state, SemIR::SpecificConstant specific_constant, @@ -223,6 +226,8 @@ class MatchContext { WorkItem entry) -> void; auto DoPostWork(State state, SemIR::TuplePattern tuple_pattern, WorkItem entry) -> void; + auto DoPostWork(State state, SemIR::StructPattern struct_pattern, + WorkItem entry) -> void; auto DoPostWork(State state, SemIR::SpecificConstant specific_constant, WorkItem entry) -> void; auto DoPostWork(State state, SemIR::ImportRefLoaded import_ref, @@ -819,6 +824,105 @@ auto MatchContext::DoPostWork(State /*state*/, results_stack_.AppendToTop(tuple_value_id); } +auto MatchContext::DoPreWork(State state, SemIR::StructPattern struct_pattern, + SemIR::InstId scrutinee_id, WorkItem entry) + -> void { + if (struct_pattern.type_id == SemIR::ErrorInst::TypeId) { + return; + } + auto subpattern_ids = context_.inst_blocks().Get(struct_pattern.elements_id); + if (need_subpattern_results()) { + results_stack_.PushArray(); + AddAsPostWork(entry); + } + + if (!scrutinee_id.has_value()) { + CARBON_CHECK(std::holds_alternative(state) || + std::holds_alternative(state)); + for (auto subpattern_id : llvm::reverse(subpattern_ids)) { + AddWork({.pattern_id = subpattern_id, + .work = PreWork{.scrutinee_id = SemIR::InstId::None}, + .allow_unmarked_ref = entry.allow_unmarked_ref}); + } + return; + } + + // TODO: Handle `_` fields in the pattern struct. If the final field is `_`, + // then number of fields in the expected type will be less than, or equal to, + // the number of fields in the scrutinee. Unmatched fields in the scrutinee + // should be discarded. + auto expected_type_id = GetScrutineeTypeInSpecific(context_, entry.pattern_id, + specific_id_stack_.back()); + + // TODO: This conversion is required to convert a StructLiteral into a + // StructValue, because a StructLiteral scrutinee will produce a + // StructAccess inst with a `Mixed` expression category, which can fail when + // performing type conversions on fields (E.g., let {.a = b: i32} = {.a = 1} + // needs to convert the IntLiteral `1` to an i32). If we can compute the + // category of a StructAccess, where the struct being accessed as a `Mixed` + // category, then we should be able to remove this conversion. + scrutinee_id = ConvertToValueOrRefOfType( + context_, SemIR::LocId(entry.pattern_id), scrutinee_id, expected_type_id); + + if (scrutinee_id == SemIR::ErrorInst::InstId) { + return; + } + + auto scrutinee = context_.insts().GetWithLocId(scrutinee_id); + + auto pattern_struct_type_inst = + context_.types().GetAs(expected_type_id); + + auto pattern_struct_fields = + context_.struct_type_fields().Get(pattern_struct_type_inst.fields_id); + + auto scrutinee_struct_type_inst = context_.insts().GetAs( + context_.types().GetTypeInstId(scrutinee.inst.type_id())); + + auto scrutinee_struct_fields = + context_.struct_type_fields().Get(scrutinee_struct_type_inst.fields_id); + + llvm::SmallVector field_access_insts; + field_access_insts.reserve(subpattern_ids.size()); + + // TODO: This loop is O(m*n) for the number of fields in the + // pattern/scrutinee. The nested looping should be removed once struct field + // lookup is improved (see related TODO in PerformActionHelper in + // member_access.cpp) + for (auto field : pattern_struct_fields) { + for (auto [i, s_field] : llvm::enumerate(scrutinee_struct_fields)) { + if (field.name_id == s_field.name_id) { + field_access_insts.push_back(GetOrAddInst( + context_, scrutinee.loc_id, + {.type_id = + context_.types().GetTypeIdForTypeInstId(s_field.type_inst_id), + .struct_id = scrutinee_id, + .index = SemIR::ElementIndex(i)})); + break; + } + } + } + for (auto [subpattern_id, subscrutinee_id] : + llvm::reverse(llvm::zip_equal(subpattern_ids, field_access_insts))) { + AddWork({.pattern_id = subpattern_id, + .work = PreWork{.scrutinee_id = subscrutinee_id}, + .allow_unmarked_ref = entry.allow_unmarked_ref}); + } +} + +auto MatchContext::DoPostWork(State /*state*/, + SemIR::StructPattern /*struct_pattern*/, + WorkItem entry) -> void { + auto elements_id = context_.inst_blocks().Add(results_stack_.PeekArray()); + results_stack_.PopArray(); + auto struct_value_id = AddInst( + context_, SemIR::LocId(entry.pattern_id), + {.type_id = GetScrutineeTypeInSpecific(context_, entry.pattern_id, + specific_id_stack_.back()), + .elements_id = elements_id}); + results_stack_.AppendToTop(struct_value_id); +} + // TODO: There is a cycle through pattern matching with an action. // NOLINTNEXTLINE(misc-no-recursion) auto MatchContext::DoPreWork(State state, SemIR::SpliceInst /*splice*/, @@ -1019,6 +1123,10 @@ auto MatchContext::Dispatch(State state, WorkItem entry) -> void { DoPreWork(state, tuple_pattern, work.scrutinee_id, entry); break; } + case CARBON_KIND(SemIR::StructPattern struct_pattern): { + DoPreWork(state, struct_pattern, work.scrutinee_id, entry); + break; + } case CARBON_KIND(SemIR::SpliceInst splice_inst): { DoPreWork(state, splice_inst, work.scrutinee_id, entry); break; @@ -1067,6 +1175,10 @@ auto MatchContext::Dispatch(State state, WorkItem entry) -> void { DoPostWork(state, tuple_pattern, entry); break; } + case CARBON_KIND(SemIR::StructPattern struct_pattern): { + DoPostWork(state, struct_pattern, entry); + break; + } case CARBON_KIND(SemIR::SpecificConstant specific_constant): { DoPostWork(state, specific_constant, entry); break; diff --git a/toolchain/check/struct.cpp b/toolchain/check/struct.cpp new file mode 100644 index 000000000000..1264a41d9ff7 --- /dev/null +++ b/toolchain/check/struct.cpp @@ -0,0 +1,52 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/struct.h" + +#include "common/map.h" +#include "toolchain/check/context.h" +#include "toolchain/diagnostics/format_providers.h" + +namespace Carbon::Check { +auto PopStructFieldNameNodes(Context& context, size_t field_count) + -> llvm::SmallVector { + llvm::SmallVector nodes; + nodes.reserve(field_count); + for ([[maybe_unused]] auto i : llvm::seq(field_count)) { + auto [name_node, _] = + context.node_stack().PopWithNodeId(); + nodes.push_back(name_node); + } + return nodes; +} + +// Diagnoses and returns true if there's a duplicate name. +auto DiagnoseDuplicateNames(Context& context, + llvm::ArrayRef field_name_nodes, + llvm::ArrayRef fields, + StructKind struct_kind_for_diagnostic) -> bool { + Map names; + for (auto [field_name_node, field] : + llvm::zip_equal(field_name_nodes, fields)) { + auto result = names.Insert(field.name_id, field_name_node); + if (!result.is_inserted()) { + CARBON_DIAGNOSTIC( + StructNameDuplicate, Error, + "duplicated field name `{1}` in " + "{0:=0:struct literal|=1:struct type literal|=2:struct pattern}", + Diagnostics::IntAsSelect, SemIR::NameId); + CARBON_DIAGNOSTIC_LABEL(StructNamePrevious, Info, + "field with the same name here"); + context.emitter() + .Build(result.value(), StructNameDuplicate, + static_cast(struct_kind_for_diagnostic), field.name_id) + .Attach(field_name_node, StructNamePrevious) + .Emit(); + return true; + } + } + return false; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/struct.h b/toolchain/check/struct.h new file mode 100644 index 000000000000..537f577868ab --- /dev/null +++ b/toolchain/check/struct.h @@ -0,0 +1,36 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_STRUCT_H_ +#define CARBON_TOOLCHAIN_CHECK_STRUCT_H_ + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "toolchain/check/context.h" +#include "toolchain/parse/node_ids.h" +#include "toolchain/sem_ir/struct_type_field.h" + +namespace Carbon::Check { + +// Struct kinds, for diagnostics. Converted to an int for a format select. +enum class StructKind : uint8_t { + StructLiteral = 0, + StructTypeLiteral = 1, + StructPattern = 2 +}; + +// Pops the names of each field from the stack. These will have been left while +// handling struct fields. +auto PopStructFieldNameNodes(Context& context, size_t field_count) + -> llvm::SmallVector; + +// Diagnoses and returns true if there's a duplicate name. +auto DiagnoseDuplicateNames(Context& context, + llvm::ArrayRef field_name_nodes, + llvm::ArrayRef fields, + StructKind struct_kind_for_diagnostic) -> bool; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_STRUCT_H_ diff --git a/toolchain/check/testdata/patterns/struct.carbon b/toolchain/check/testdata/patterns/struct.carbon new file mode 100644 index 000000000000..20e57a8fbf44 --- /dev/null +++ b/toolchain/check/testdata/patterns/struct.carbon @@ -0,0 +1,1288 @@ +// 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/primitives.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/patterns/struct.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/patterns/struct.carbon + +// --- empty.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {} = {}; +//@dump-sem-ir-end + +// --- literal.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {.a = b: ()} = {.a = ()}; +//@dump-sem-ir-end + +// --- literal_two_fields.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {.a = b: i32, .c = d: bool} = {.a = 1, .c = true}; +//@dump-sem-ir-end + +// --- literal_shorthand.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {a: ()} = {.a = ()}; +//@dump-sem-ir-end + +// --- literal_shorthand_two_fields.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {a: i32, b: bool} = {.a = 1, .b = true}; +//@dump-sem-ir-end + +// --- literal_mixed_syntax.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {.a = b: (), c: ()} = {.a = (), .c = ()}; +//@dump-sem-ir-end + +// --- nested.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {.a = x: i32, .b = {.i = m: f32, .j = n: bool}} = {.a = 1, .b = {.i = 2.0, .j = true}}; +//@dump-sem-ir-end + +// --- init_expr.carbon + +library "[[@TEST_NAME]]"; + +fn F() -> {.a: i32, .b: bool}; + +//@dump-sem-ir-begin +let {.a = x: i32, .b = y: bool} = F(); +//@dump-sem-ir-end + +// --- init_expr_shorthand.carbon + +library "[[@TEST_NAME]]"; + +fn F() -> {.a: i32, .b: bool}; + +//@dump-sem-ir-begin +let {a: i32, b: bool} = F(); +//@dump-sem-ir-end + +// --- ref_expr.carbon + +library "[[@TEST_NAME]]"; + +var s: {.a: i32, .b: bool} = {.a = 1, .b = true}; + +//@dump-sem-ir-begin +let {.a = x: i32, .b = y: bool} = s; +//@dump-sem-ir-end + +// --- ref_expr_shorthand.carbon + +library "[[@TEST_NAME]]"; + +var s: {.a: i32, .b: bool} = {.a = 1, .b = true}; + +//@dump-sem-ir-begin +let {a: i32, b: bool} = s; +//@dump-sem-ir-end + +// --- unordered.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {.a = b: i32, .c = d: bool} = {.c = true, .a = 1}; +//@dump-sem-ir-end + +// --- unordered_shorthand.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {a: i32, b: bool} = {.b = true, .a = 1}; +//@dump-sem-ir-end + +// --- unordered_mixed_syntax.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +let {a: i32, .b = c: bool} = {.b = true, .a = 1}; +//@dump-sem-ir-end + +// --- fail_todo_underscore.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_todo_underscore.carbon:[[@LINE+2]]:5-20: error: semantics TODO: `Struct pattern underscore field` [SemanticsTodo] +// CHECK:STDERR: +let {.a = x: i32, _} = {.a = 1, .b = ()}; +//@dump-sem-ir-end + +// --- fail_no_matching_field.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_no_matching_field.carbon:[[@LINE+2]]:20-28: error: struct `{.a: ()}` has no field named `b` [StructInitUnexpectedFieldInLiteral] +// CHECK:STDERR: +let {.a = x: ()} = {.b = ()}; +//@dump-sem-ir-end + +// --- fail_no_matching_field_ref.carbon + +library "[[@TEST_NAME]]"; +var s: {.a: (), .b: ()} = {.a = (), .b = ()}; +//@dump-sem-ir-begin +// CHECK:STDERR: fail_no_matching_field_ref.carbon:[[@LINE+2]]:20: error: cannot convert from struct type `{.a: (), .b: ()}` to `{.c: ()}`: unexpected field `a` in source type [StructInitUnexpectedFieldInConversion] +// CHECK:STDERR: +let {.c = x: ()} = s; +//@dump-sem-ir-end + + +// --- fail_unhandled_field.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_unhandled_field.carbon:[[@LINE+2]]:20-39: error: struct `{.a: ()}` has no field named `b` [StructInitUnexpectedFieldInLiteral] +// CHECK:STDERR: +let {.a = x: ()} = {.a = (), .b = true}; +//@dump-sem-ir-end + +// --- fail_duplicate_field_name.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_duplicate_field_name.carbon:[[@LINE+3]]:19: error: duplicated field name `a` in struct pattern [StructNameDuplicate] +// CHECK:STDERR: fail_duplicate_field_name.carbon:[[@LINE+2]]:7: note: field with the same name here [StructNamePrevious] +// CHECK:STDERR: +let {.a = b: (), .a = c: ()} = {.a = ()}; +//@dump-sem-ir-end + +// --- fail_duplicate_field_name_shorthand.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_duplicate_field_name_shorthand.carbon:[[@LINE+6]]:13: error: duplicate name `a` being declared in the same scope [NameDeclDuplicate] +// CHECK:STDERR: fail_duplicate_field_name_shorthand.carbon:[[@LINE+5]]:6-10: note: name is previously declared here [NameDeclPrevious] +// CHECK:STDERR: +// CHECK:STDERR: fail_duplicate_field_name_shorthand.carbon:[[@LINE+3]]:13: error: duplicated field name `a` in struct pattern [StructNameDuplicate] +// CHECK:STDERR: fail_duplicate_field_name_shorthand.carbon:[[@LINE+2]]:6: note: field with the same name here [StructNamePrevious] +// CHECK:STDERR: +let {a: (), a: ()} = {.a = ()}; +//@dump-sem-ir-end + +// --- fail_duplicate_field_name_mixed_syntax.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +// CHECK:STDERR: fail_duplicate_field_name_mixed_syntax.carbon:[[@LINE+3]]:18: error: duplicated field name `a` in struct pattern [StructNameDuplicate] +// CHECK:STDERR: fail_duplicate_field_name_mixed_syntax.carbon:[[@LINE+2]]:7: note: field with the same name here [StructNamePrevious] +// CHECK:STDERR: +let {.a = b: (), a: ()} = {.a = ()}; +//@dump-sem-ir-end + +// --- fail_in_class_var.carbon + +library "[[@TEST_NAME]]"; + +//@dump-sem-ir-begin +class C{ + // CHECK:STDERR: fail_in_class_var.carbon:[[@LINE+2]]:9-20: error: found struct pattern in class member var declaration [FieldWithStructPattern] + // CHECK:STDERR: + var {.a = x: ()}; +} +//@dump-sem-ir-end + +// --- fail_in_class_let.carbon + +library "[[@TEST_NAME]]"; +//@dump-sem-ir-begin +class C{ + // CHECK:STDERR: fail_in_class_let.carbon:[[@LINE+2]]:9-20: error: found struct pattern in class member let declaration [FieldWithStructPattern] + // CHECK:STDERR: + let {.a = x: ()} = {.a = ()}; +} +//@dump-sem-ir-end + +// --- fail_incorrect_field_type.carbon + +library "[[@TEST_NAME]]"; +//@dump-sem-ir-begin +// CHECK:STDERR: fail_incorrect_field_type.carbon:[[@LINE+3]]:20-28: error: cannot implicitly convert expression of type `{}` to `()` [ConversionFailure] +// CHECK:STDERR: fail_incorrect_field_type.carbon:[[@LINE+2]]:20-28: note: type `{}` does not implement interface `Core.ImplicitAs(())` [MissingImplInMemberAccessInContext] +// CHECK:STDERR: +let {.a = x: ()} = {.a = {}}; +//@dump-sem-ir-end + +// --- fail_incorrect_scrutinee_type.carbon + +library "[[@TEST_NAME]]"; +//@dump-sem-ir-begin +// CHECK:STDERR: fail_incorrect_scrutinee_type.carbon:[[@LINE+3]]:5-16: error: cannot implicitly convert expression of type `((), ())` to `{.a: ()}` [ConversionFailure] +// CHECK:STDERR: fail_incorrect_scrutinee_type.carbon:[[@LINE+2]]:5-16: note: type `((), ())` does not implement interface `Core.ImplicitAs({.a: ()})` [MissingImplInMemberAccessInContext] +// CHECK:STDERR: +let {.a = x: ()} = ((), ()); +//@dump-sem-ir-end + +// CHECK:STDOUT: --- empty.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_struct_type [concrete] +// CHECK:STDOUT: %.931: %pattern_type = struct_pattern () [concrete] +// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc5_6.1: %empty_struct_type = converted @__global_init.%.loc5, %empty_struct [concrete = constants.%empty_struct] +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %.loc5_6.2: %pattern_type = struct_pattern () [concrete = constants.%.931] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- literal.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %.140: %pattern_type.e85 = struct_pattern (%b.patt) [concrete] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_28: %empty_tuple.type = converted @__global_init.%.loc5_27, %empty_tuple [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%.loc5_28) [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_16.1: %struct_type.a = converted @__global_init.%.loc5_28, %struct [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_16.2: %empty_tuple.type = struct_access %.loc5_16.1, element0 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_15.1: type = splice_block %.loc5_15.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc5_15.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_15.3: type = converted %.loc5_15.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %b: %empty_tuple.type = wrapper_binding b, %.loc5_16.2 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %.loc5_16.3: %pattern_type.e85 = struct_pattern (%b.patt) [concrete = constants.%.140] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_27: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_28: %struct_type.a = struct_literal (%.loc5_27) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- literal_two_fields.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.d94 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %d.patt: %pattern_type.831 = value_binding_pattern d [concrete] +// CHECK:STDOUT: %struct_type.a.c.11f: type = struct_type {.a: %i32, .c: bool} [concrete] +// CHECK:STDOUT: %pattern_type.e6b: type = pattern_type %struct_type.a.c.11f [concrete] +// CHECK:STDOUT: %.d0e: %pattern_type.e6b = struct_pattern (%b.patt, %d.patt) [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %struct_type.a.c.bbc: type = struct_type {.a: Core.IntLiteral, .c: bool} [concrete] +// CHECK:STDOUT: %struct.7e6: %struct_type.a.c.bbc = struct_value (%int_1.5b8, %true) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %struct.78d: %struct_type.a.c.11f = struct_value (%int_1.68a, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_53.1: = bound_method @__global_init.%int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_53.2: = bound_method @__global_init.%int_1, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_53.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_53.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_53.2: %i32 = converted @__global_init.%int_1, %.loc5_53.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %struct: %struct_type.a.c.11f = struct_value (%.loc5_53.2, @__global_init.%true) [concrete = constants.%struct.78d] +// CHECK:STDOUT: %.loc5_31.1: %struct_type.a.c.11f = converted @__global_init.%.loc5, %struct [concrete = constants.%struct.78d] +// CHECK:STDOUT: %.loc5_31.2: %i32 = struct_access %.loc5_31.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_31.3: bool = struct_access %.loc5_31.1, element1 [concrete = constants.%true] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %b: %i32 = wrapper_binding b, %.loc5_31.2 +// CHECK:STDOUT: %.loc5_27: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %d: bool = wrapper_binding d, %.loc5_31.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type.d94 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %d.patt: %pattern_type.831 = value_binding_pattern d [concrete = constants.%d.patt] +// CHECK:STDOUT: %.loc5_31.4: %pattern_type.e6b = struct_pattern (%b.patt, %d.patt) [concrete = constants.%.d0e] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %.loc5: %struct_type.a.c.bbc = struct_literal (%int_1, %true) [concrete = constants.%struct.7e6] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- literal_shorthand.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.cb1 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %.e73: %pattern_type.e85 = struct_pattern (%a.patt) [concrete] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_23: %empty_tuple.type = converted @__global_init.%.loc5_22, %empty_tuple [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%.loc5_23) [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_11.1: %struct_type.a = converted @__global_init.%.loc5_23, %struct [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_11.2: %empty_tuple.type = struct_access %.loc5_11.1, element0 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_10.1: type = splice_block %.loc5_10.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc5_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_10.3: type = converted %.loc5_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %empty_tuple.type = wrapper_binding a, %.loc5_11.2 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.cb1 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %.loc5_11.3: %pattern_type.e85 = struct_pattern (%a.patt) [concrete = constants.%.e73] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_22: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_23: %struct_type.a = struct_literal (%.loc5_22) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- literal_shorthand_two_fields.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %struct_type.a.b.214: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b.214 [concrete] +// CHECK:STDOUT: %.4eb: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %struct_type.a.b.f6e: type = struct_type {.a: Core.IntLiteral, .b: bool} [concrete] +// CHECK:STDOUT: %struct.1e1: %struct_type.a.b.f6e = struct_value (%int_1.5b8, %true) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %struct.75c: %struct_type.a.b.214 = struct_value (%int_1.68a, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_43.1: = bound_method @__global_init.%int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_43.2: = bound_method @__global_init.%int_1, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_43.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_43.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_43.2: %i32 = converted @__global_init.%int_1, %.loc5_43.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %struct: %struct_type.a.b.214 = struct_value (%.loc5_43.2, @__global_init.%true) [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_21.1: %struct_type.a.b.214 = converted @__global_init.%.loc5, %struct [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_21.2: %i32 = struct_access %.loc5_21.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_21.3: bool = struct_access %.loc5_21.1, element1 [concrete = constants.%true] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %.loc5_21.2 +// CHECK:STDOUT: %.loc5_17: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %b: bool = wrapper_binding b, %.loc5_21.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %.loc5_21.4: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete = constants.%.4eb] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %.loc5: %struct_type.a.b.f6e = struct_literal (%int_1, %true) [concrete = constants.%struct.1e1] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- literal_mixed_syntax.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %c.patt: %pattern_type.cb1 = value_binding_pattern c [concrete] +// CHECK:STDOUT: %struct_type.a.c: type = struct_type {.a: %empty_tuple.type, .c: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.f10: type = pattern_type %struct_type.a.c [concrete] +// CHECK:STDOUT: %.fcd: %pattern_type.f10 = struct_pattern (%b.patt, %c.patt) [concrete] +// CHECK:STDOUT: %struct: %struct_type.a.c = struct_value (%empty_tuple, %empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %empty_tuple.loc5_34: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_44.1: %empty_tuple.type = converted @__global_init.%.loc5_34, %empty_tuple.loc5_34 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %empty_tuple.loc5_43: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_44.2: %empty_tuple.type = converted @__global_init.%.loc5_43, %empty_tuple.loc5_43 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %struct: %struct_type.a.c = struct_value (%.loc5_44.1, %.loc5_44.2) [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_23.1: %struct_type.a.c = converted @__global_init.%.loc5_44, %struct [concrete = constants.%struct] +// CHECK:STDOUT: %.loc5_23.2: %empty_tuple.type = struct_access %.loc5_23.1, element0 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_23.3: %empty_tuple.type = struct_access %.loc5_23.1, element1 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_15.1: type = splice_block %.loc5_15.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc5_15.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_15.3: type = converted %.loc5_15.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %b: %empty_tuple.type = wrapper_binding b, %.loc5_23.2 +// CHECK:STDOUT: %.loc5_22.1: type = splice_block %.loc5_22.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc5_22.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_22.3: type = converted %.loc5_22.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %c: %empty_tuple.type = wrapper_binding c, %.loc5_23.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %c.patt: %pattern_type.cb1 = value_binding_pattern c [concrete = constants.%c.patt] +// CHECK:STDOUT: %.loc5_23.4: %pattern_type.f10 = struct_pattern (%b.patt, %c.patt) [concrete = constants.%.fcd] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_34: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_43: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc5_44: %struct_type.a.c = struct_literal (%.loc5_34, %.loc5_43) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- nested.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %f32.3bc: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.239: type = pattern_type %f32.3bc [concrete] +// CHECK:STDOUT: %m.patt: %pattern_type.239 = value_binding_pattern m [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %n.patt: %pattern_type.831 = value_binding_pattern n [concrete] +// CHECK:STDOUT: %struct_type.i.j.e5d: type = struct_type {.i: %f32.3bc, .j: bool} [concrete] +// CHECK:STDOUT: %pattern_type.0af: type = pattern_type %struct_type.i.j.e5d [concrete] +// CHECK:STDOUT: %.5ed: %pattern_type.0af = struct_pattern (%m.patt, %n.patt) [concrete] +// CHECK:STDOUT: %struct_type.a.b.5f4: type = struct_type {.a: %i32, .b: %struct_type.i.j.e5d} [concrete] +// CHECK:STDOUT: %pattern_type.04b: type = pattern_type %struct_type.a.b.5f4 [concrete] +// CHECK:STDOUT: %.cc7: %pattern_type.04b = struct_pattern (%x.patt, %.5ed) [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %float.cce: Core.FloatLiteral = float_literal_value 20e-1 [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %struct_type.i.j.e80: type = struct_type {.i: Core.FloatLiteral, .j: bool} [concrete] +// CHECK:STDOUT: %struct.050: %struct_type.i.j.e80 = struct_value (%float.cce, %true) [concrete] +// CHECK:STDOUT: %struct_type.a.b.1a6: type = struct_type {.a: Core.IntLiteral, .b: %struct_type.i.j.e80} [concrete] +// CHECK:STDOUT: %struct.293: %struct_type.a.b.1a6 = struct_value (%int_1.5b8, %struct.050) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet.fc6: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.fc6) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet.fc6 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method.3bd: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6bb: type = facet_type <@ImplicitAs, @ImplicitAs(%f32.3bc)> [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.c1a: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.48f: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.c1a = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.409: = impl_witness imports.%ImplicitAs.impl_witness_table.f2e, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.587: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.d9b: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.587 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet.253: %ImplicitAs.type.6bb = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.409) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.049: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f32.3bc, %ImplicitAs.facet.253) [concrete] +// CHECK:STDOUT: %.f72: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.049, %ImplicitAs.facet.253 [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %float.cce, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.d9b [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.d9b, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method.6df: = bound_method %float.cce, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %float.b6c: %f32.3bc = float_value 2 [concrete] +// CHECK:STDOUT: %struct.3be: %struct_type.i.j.e5d = struct_value (%float.b6c, %true) [concrete] +// CHECK:STDOUT: %struct.431: %struct_type.a.b.5f4 = struct_value (%int_1.68a, %struct.3be) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %Core.import_ref.0c7: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.c1a) = import_ref Core//prelude/parts/float, loc{{\d+_\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.48f)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f2e = impl_witness_table (%Core.import_ref.0c7), @Core.FloatLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0.loc5_90: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_90.1: = bound_method @__global_init.%int_1, %impl.elem0.loc5_90 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc5_90: = specific_function %impl.elem0.loc5_90, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_90.2: = bound_method @__global_init.%int_1, %specific_fn.loc5_90 [concrete = constants.%bound_method.3bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_90.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_90.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_90.2: %i32 = converted @__global_init.%int_1, %.loc5_90.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %impl.elem0.loc5_89: %.f72 = impl_witness_access constants.%ImplicitAs.impl_witness.409, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.d9b] +// CHECK:STDOUT: %bound_method.loc5_89.1: = bound_method @__global_init.%float, %impl.elem0.loc5_89 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc5_89: = specific_function %impl.elem0.loc5_89, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_89.2: = bound_method @__global_init.%float, %specific_fn.loc5_89 [concrete = constants.%bound_method.6df] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f32.3bc = call %bound_method.loc5_89.2(@__global_init.%float) [concrete = constants.%float.b6c] +// CHECK:STDOUT: %.loc5_89.1: %f32.3bc = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.b6c] +// CHECK:STDOUT: %.loc5_89.2: %f32.3bc = converted @__global_init.%float, %.loc5_89.1 [concrete = constants.%float.b6c] +// CHECK:STDOUT: %struct.loc5_89: %struct_type.i.j.e5d = struct_value (%.loc5_89.2, @__global_init.%true) [concrete = constants.%struct.3be] +// CHECK:STDOUT: %.loc5_90.3: %struct_type.i.j.e5d = converted @__global_init.%.loc5_89, %struct.loc5_89 [concrete = constants.%struct.3be] +// CHECK:STDOUT: %struct.loc5_90: %struct_type.a.b.5f4 = struct_value (%.loc5_90.2, %.loc5_90.3) [concrete = constants.%struct.431] +// CHECK:STDOUT: %.loc5_51.1: %struct_type.a.b.5f4 = converted @__global_init.%.loc5_90, %struct.loc5_90 [concrete = constants.%struct.431] +// CHECK:STDOUT: %.loc5_51.2: %i32 = struct_access %.loc5_51.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_51.3: %struct_type.i.j.e5d = struct_access %.loc5_51.1, element1 [concrete = constants.%struct.3be] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %.loc5_51.2 +// CHECK:STDOUT: %.loc5_51.4: %f32.3bc = struct_access %.loc5_51.3, element0 [concrete = constants.%float.b6c] +// CHECK:STDOUT: %.loc5_51.5: bool = struct_access %.loc5_51.3, element1 [concrete = constants.%true] +// CHECK:STDOUT: %f32: type = type_literal constants.%f32.3bc [concrete = constants.%f32.3bc] +// CHECK:STDOUT: %m: %f32.3bc = wrapper_binding m, %.loc5_51.4 +// CHECK:STDOUT: %.loc5_46: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %n: bool = wrapper_binding n, %.loc5_51.5 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %m.patt: %pattern_type.239 = value_binding_pattern m [concrete = constants.%m.patt] +// CHECK:STDOUT: %n.patt: %pattern_type.831 = value_binding_pattern n [concrete = constants.%n.patt] +// CHECK:STDOUT: %.loc5_50: %pattern_type.0af = struct_pattern (%m.patt, %n.patt) [concrete = constants.%.5ed] +// CHECK:STDOUT: %.loc5_51.6: %pattern_type.04b = struct_pattern (%x.patt, %.loc5_50) [concrete = constants.%.cc7] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 20e-1 [concrete = constants.%float.cce] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %.loc5_89: %struct_type.i.j.e80 = struct_literal (%float, %true) [concrete = constants.%struct.050] +// CHECK:STDOUT: %.loc5_90: %struct_type.a.b.1a6 = struct_literal (%int_1, %.loc5_89) [concrete = constants.%struct.293] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- init_expr.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type.831 = value_binding_pattern y [concrete] +// CHECK:STDOUT: %.e3b: %pattern_type.269 = struct_pattern (%x.patt, %y.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_37.1: ref %struct_type.a.b = temporary @__global_init.%.loc7, @__global_init.%F.call +// CHECK:STDOUT: %.loc7_37.2: ref %i32 = struct_access %.loc7_37.1, element0 +// CHECK:STDOUT: %.loc7_37.3: ref bool = struct_access %.loc7_37.1, element1 +// CHECK:STDOUT: %.loc7_37.4: %i32 = acquire_value %.loc7_37.2 +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %.loc7_37.4 +// CHECK:STDOUT: %.loc7_37.5: bool = acquire_value %.loc7_37.3 +// CHECK:STDOUT: %.loc7_27: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %y: bool = wrapper_binding y, %.loc7_37.5 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %y.patt: %pattern_type.831 = value_binding_pattern y [concrete = constants.%y.patt] +// CHECK:STDOUT: %.loc7_31: %pattern_type.269 = struct_pattern (%x.patt, %y.patt) [concrete = constants.%.e3b] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %.loc7: ref %struct_type.a.b = temporary_storage +// CHECK:STDOUT: %F.call: init %struct_type.a.b to %.loc7 = call %F.ref() +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- init_expr_shorthand.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %.4eb: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_27.1: ref %struct_type.a.b = temporary @__global_init.%.loc7, @__global_init.%F.call +// CHECK:STDOUT: %.loc7_27.2: ref %i32 = struct_access %.loc7_27.1, element0 +// CHECK:STDOUT: %.loc7_27.3: ref bool = struct_access %.loc7_27.1, element1 +// CHECK:STDOUT: %.loc7_27.4: %i32 = acquire_value %.loc7_27.2 +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %.loc7_27.4 +// CHECK:STDOUT: %.loc7_27.5: bool = acquire_value %.loc7_27.3 +// CHECK:STDOUT: %.loc7_17: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %b: bool = wrapper_binding b, %.loc7_27.5 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %.loc7_21: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete = constants.%.4eb] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %.loc7: ref %struct_type.a.b = temporary_storage +// CHECK:STDOUT: %F.call: init %struct_type.a.b to %.loc7 = call %F.ref() +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- ref_expr.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %struct_type.a.b.214: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b.214 [concrete] +// CHECK:STDOUT: %.872: ref %i32 = struct_access file.%s.var, element0 [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %.d8b: ref bool = struct_access file.%s.var, element1 [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type.831 = value_binding_pattern y [concrete] +// CHECK:STDOUT: %.e3b: %pattern_type.269 = struct_pattern (%x.patt, %y.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_35.1: ref %i32 = struct_access @__global_init.%s.ref, element0 [concrete = constants.%.872] +// CHECK:STDOUT: %.loc7_35.2: ref bool = struct_access @__global_init.%s.ref, element1 [concrete = constants.%.d8b] +// CHECK:STDOUT: %.loc7_35.3: %i32 = acquire_value %.loc7_35.1 +// CHECK:STDOUT: %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %x: %i32 = wrapper_binding x, %.loc7_35.3 +// CHECK:STDOUT: %.loc7_35.4: bool = acquire_value %.loc7_35.2 +// CHECK:STDOUT: %.loc7_27: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %y: bool = wrapper_binding y, %.loc7_35.4 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.d94 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %y.patt: %pattern_type.831 = value_binding_pattern y [concrete = constants.%y.patt] +// CHECK:STDOUT: %.loc7_31: %pattern_type.269 = struct_pattern (%x.patt, %y.patt) [concrete = constants.%.e3b] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: +// CHECK:STDOUT: %s.ref: ref %struct_type.a.b.214 = name_ref s, file.%s [concrete = file.%s.var] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- ref_expr_shorthand.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %struct_type.a.b.214: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b.214 [concrete] +// CHECK:STDOUT: %.872: ref %i32 = struct_access file.%s.var, element0 [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %.d8b: ref bool = struct_access file.%s.var, element1 [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %.4eb: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_25.1: ref %i32 = struct_access @__global_init.%s.ref, element0 [concrete = constants.%.872] +// CHECK:STDOUT: %.loc7_25.2: ref bool = struct_access @__global_init.%s.ref, element1 [concrete = constants.%.d8b] +// CHECK:STDOUT: %.loc7_25.3: %i32 = acquire_value %.loc7_25.1 +// CHECK:STDOUT: %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %.loc7_25.3 +// CHECK:STDOUT: %.loc7_25.4: bool = acquire_value %.loc7_25.2 +// CHECK:STDOUT: %.loc7_17: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %b: bool = wrapper_binding b, %.loc7_25.4 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %.loc7_21: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete = constants.%.4eb] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: +// CHECK:STDOUT: %s.ref: ref %struct_type.a.b.214 = name_ref s, file.%s [concrete = file.%s.var] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- unordered.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.d94 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %d.patt: %pattern_type.831 = value_binding_pattern d [concrete] +// CHECK:STDOUT: %struct_type.a.c: type = struct_type {.a: %i32, .c: bool} [concrete] +// CHECK:STDOUT: %pattern_type.e6b: type = pattern_type %struct_type.a.c [concrete] +// CHECK:STDOUT: %.d0e: %pattern_type.e6b = struct_pattern (%b.patt, %d.patt) [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %struct_type.c.a: type = struct_type {.c: bool, .a: Core.IntLiteral} [concrete] +// CHECK:STDOUT: %struct.da6: %struct_type.c.a = struct_value (%true, %int_1.5b8) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %struct.78d: %struct_type.a.c = struct_value (%int_1.68a, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_53.1: = bound_method @__global_init.%int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_53.2: = bound_method @__global_init.%int_1, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_53.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_53.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_53.2: %i32 = converted @__global_init.%int_1, %.loc5_53.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %struct: %struct_type.a.c = struct_value (%.loc5_53.2, @__global_init.%true) [concrete = constants.%struct.78d] +// CHECK:STDOUT: %.loc5_31.1: %struct_type.a.c = converted @__global_init.%.loc5, %struct [concrete = constants.%struct.78d] +// CHECK:STDOUT: %.loc5_31.2: %i32 = struct_access %.loc5_31.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_31.3: bool = struct_access %.loc5_31.1, element1 [concrete = constants.%true] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %b: %i32 = wrapper_binding b, %.loc5_31.2 +// CHECK:STDOUT: %.loc5_27: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %d: bool = wrapper_binding d, %.loc5_31.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type.d94 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %d.patt: %pattern_type.831 = value_binding_pattern d [concrete = constants.%d.patt] +// CHECK:STDOUT: %.loc5_31.4: %pattern_type.e6b = struct_pattern (%b.patt, %d.patt) [concrete = constants.%.d0e] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %.loc5: %struct_type.c.a = struct_literal (%true, %int_1) [concrete = constants.%struct.da6] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- unordered_shorthand.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b [concrete] +// CHECK:STDOUT: %.4eb: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %struct_type.b.a: type = struct_type {.b: bool, .a: Core.IntLiteral} [concrete] +// CHECK:STDOUT: %struct.a63: %struct_type.b.a = struct_value (%true, %int_1.5b8) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %struct.75c: %struct_type.a.b = struct_value (%int_1.68a, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_43.1: = bound_method @__global_init.%int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_43.2: = bound_method @__global_init.%int_1, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_43.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_43.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_43.2: %i32 = converted @__global_init.%int_1, %.loc5_43.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %struct: %struct_type.a.b = struct_value (%.loc5_43.2, @__global_init.%true) [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_21.1: %struct_type.a.b = converted @__global_init.%.loc5, %struct [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_21.2: %i32 = struct_access %.loc5_21.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_21.3: bool = struct_access %.loc5_21.1, element1 [concrete = constants.%true] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %.loc5_21.2 +// CHECK:STDOUT: %.loc5_17: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %b: bool = wrapper_binding b, %.loc5_21.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %.loc5_21.4: %pattern_type.269 = struct_pattern (%a.patt, %b.patt) [concrete = constants.%.4eb] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %.loc5: %struct_type.b.a = struct_literal (%true, %int_1) [concrete = constants.%struct.a63] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- unordered_mixed_syntax.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.d94: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %c.patt: %pattern_type.831 = value_binding_pattern c [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %i32, .b: bool} [concrete] +// CHECK:STDOUT: %pattern_type.269: type = pattern_type %struct_type.a.b [concrete] +// CHECK:STDOUT: %.3b7: %pattern_type.269 = struct_pattern (%a.patt, %c.patt) [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %struct_type.b.a: type = struct_type {.b: bool, .a: Core.IntLiteral} [concrete] +// CHECK:STDOUT: %struct.a63: %struct_type.b.a = struct_value (%true, %int_1.5b8) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.6b0: 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.3c6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.6f2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.d73: = impl_witness imports.%ImplicitAs.impl_witness_table.f53, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766: 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.f60: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.766 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.6b0 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.d73) [concrete] +// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.58f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete] +// CHECK:STDOUT: %.33a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.58f, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.f60, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.68a: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %struct.75c: %struct_type.a.b = struct_value (%int_1.68a, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core.import_ref.e47: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3c6) = 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.6f2)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.f53 = impl_witness_table (%Core.import_ref.e47), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %impl.elem0: %.33a = impl_witness_access constants.%ImplicitAs.impl_witness.d73, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f60] +// CHECK:STDOUT: %bound_method.loc5_48.1: = bound_method @__global_init.%int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc5_48.2: = bound_method @__global_init.%int_1, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_48.2(@__global_init.%int_1) [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_48.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_48.2: %i32 = converted @__global_init.%int_1, %.loc5_48.1 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %struct: %struct_type.a.b = struct_value (%.loc5_48.2, @__global_init.%true) [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_26.1: %struct_type.a.b = converted @__global_init.%.loc5, %struct [concrete = constants.%struct.75c] +// CHECK:STDOUT: %.loc5_26.2: %i32 = struct_access %.loc5_26.1, element0 [concrete = constants.%int_1.68a] +// CHECK:STDOUT: %.loc5_26.3: bool = struct_access %.loc5_26.1, element1 [concrete = constants.%true] +// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %.loc5_26.2 +// CHECK:STDOUT: %.loc5_22: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %c: bool = wrapper_binding c, %.loc5_26.3 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.d94 = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %c.patt: %pattern_type.831 = value_binding_pattern c [concrete = constants.%c.patt] +// CHECK:STDOUT: %.loc5_26.4: %pattern_type.269 = struct_pattern (%a.patt, %c.patt) [concrete = constants.%.3b7] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %.loc5: %struct_type.b.a = struct_literal (%true, %int_1) [concrete = constants.%struct.a63] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_underscore.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_matching_field.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %.298: %pattern_type.e85 = struct_pattern (%x.patt) [concrete] +// CHECK:STDOUT: %struct_type.b: type = struct_type {.b: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %struct: %struct_type.b = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %.loc7: %pattern_type.e85 = struct_pattern (%x.patt) [concrete = constants.%.298] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_27: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc7_28: %struct_type.b = struct_literal (%.loc7_27) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_no_matching_field_ref.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %empty_tuple.type, .b: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %struct_type.c: type = struct_type {.c: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.810: type = pattern_type %struct_type.c [concrete] +// CHECK:STDOUT: %.9cb: %pattern_type.810 = struct_pattern (%x.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %.loc7: %pattern_type.810 = struct_pattern (%x.patt) [concrete = constants.%.9cb] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: +// CHECK:STDOUT: %s.ref: ref %struct_type.a.b = name_ref s, file.%s [concrete = file.%s.var] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_unhandled_field.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %.298: %pattern_type.e85 = struct_pattern (%x.patt) [concrete] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %empty_tuple.type, .b: bool} [concrete] +// CHECK:STDOUT: %struct: %struct_type.a.b = struct_value (%empty_tuple, %true) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %.loc7: %pattern_type.e85 = struct_pattern (%x.patt) [concrete = constants.%.298] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_27: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true] +// CHECK:STDOUT: %.loc7_39: %struct_type.a.b = struct_literal (%.loc7_27, %true) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_duplicate_field_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type = value_binding_pattern b [concrete] +// CHECK:STDOUT: %c.patt: %pattern_type = value_binding_pattern c [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %c.patt: %pattern_type = value_binding_pattern c [concrete = constants.%c.patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_39: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc8_40: %struct_type.a = struct_literal (%.loc8_39) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_duplicate_field_name_shorthand.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type = value_binding_pattern a [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt.loc11_7: %pattern_type = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: %a.patt.loc11_14: %pattern_type = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc11_29: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc11_30: %struct_type.a = struct_literal (%.loc11_29) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_duplicate_field_name_mixed_syntax.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type = value_binding_pattern b [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type = value_binding_pattern a [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %struct: %struct_type.a = struct_value (%empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type = value_binding_pattern b [concrete = constants.%b.patt] +// CHECK:STDOUT: %a.patt: %pattern_type = value_binding_pattern a [concrete = constants.%a.patt] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_34: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc8_35: %struct_type.a = struct_literal (%.loc8_34) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_in_class_var.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: complete_type_witness = invalid +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .x = .inst{{[0-9A-F]+}}.loc8_16 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_in_class_let.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: complete_type_witness = invalid +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .x = .inst{{[0-9A-F]+}}.loc7_16 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_incorrect_field_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %struct_type.a.715: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a.715 [concrete] +// CHECK:STDOUT: %.298: %pattern_type.e85 = struct_pattern (%x.patt) [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] +// CHECK:STDOUT: %struct_type.a.225: type = struct_type {.a: %empty_struct_type} [concrete] +// CHECK:STDOUT: %struct: %struct_type.a.225 = struct_value (%empty_struct) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_28: %empty_tuple.type = converted @__global_init.%.loc7_27, [concrete = ] +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %.loc7_16: %pattern_type.e85 = struct_pattern (%x.patt) [concrete = constants.%.298] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_27: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc7_28: %struct_type.a.225 = struct_literal (%.loc7_27) [concrete = constants.%struct] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_incorrect_scrutinee_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete] +// CHECK:STDOUT: %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %.298: %pattern_type.e85 = struct_pattern (%x.patt) [concrete] +// CHECK:STDOUT: %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type) [concrete] +// CHECK:STDOUT: %tuple: %tuple.type = tuple_value (%empty_tuple, %empty_tuple) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %.loc7_16.1: %struct_type.a = converted @__global_init.%.loc7_27, [concrete = ] +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete = constants.%x.patt] +// CHECK:STDOUT: %.loc7_16.2: %pattern_type.e85 = struct_pattern (%x.patt) [concrete = constants.%.298] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_22: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc7_26: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc7_27: %tuple.type = tuple_literal (%.loc7_22, %.loc7_26) [concrete = constants.%tuple] +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index 9d06dd09aefd..86def1e56012 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -303,6 +303,7 @@ CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclOutsideClass) CARBON_DIAGNOSTIC_KIND(ClassForwardDeclaredHere) CARBON_DIAGNOSTIC_KIND(ClassIncompleteWithinDefinition) CARBON_DIAGNOSTIC_KIND(FieldNamedUnderscore) +CARBON_DIAGNOSTIC_KIND(FieldWithStructPattern) CARBON_DIAGNOSTIC_KIND(FieldWithTuplePattern) CARBON_DIAGNOSTIC_KIND(FriendNotAllowedInScope) CARBON_DIAGNOSTIC_KIND(FriendNotNameScope) diff --git a/toolchain/parse/handle_binding_pattern.cpp b/toolchain/parse/handle_binding_pattern.cpp index abc93e9442ef..06209479c14a 100644 --- a/toolchain/parse/handle_binding_pattern.cpp +++ b/toolchain/parse/handle_binding_pattern.cpp @@ -281,7 +281,9 @@ static auto HandleBindingPatternFinish(Context& context, StateKind finish_kind) auto node_kind = NodeKind::InvalidParse; if (state.in_var_pattern) { - node_kind = NodeKind::VarBindingPattern; + node_kind = state.in_field_shorthand_pattern + ? NodeKind::StructPatternFieldVarBindingPattern + : NodeKind::VarBindingPattern; if (finish_kind != StateKind::BindingPatternFinishAsRegular) { CARBON_DIAGNOSTIC(NonRegularBindingInVarDecl, Error, "found {0:generic|`:?`} binding inside `var` pattern", @@ -297,7 +299,9 @@ static auto HandleBindingPatternFinish(Context& context, StateKind finish_kind) node_kind = NodeKind::CompileTimeBindingPattern; break; case StateKind::BindingPatternFinishAsRegular: - node_kind = NodeKind::LetBindingPattern; + node_kind = state.in_field_shorthand_pattern + ? NodeKind::StructPatternFieldLetBindingPattern + : NodeKind::LetBindingPattern; break; case StateKind::BindingPatternFinishAsForm: node_kind = NodeKind::FormBindingPattern; diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index ae9d09ab63fc..5154e9fef7cf 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -220,6 +220,8 @@ CARBON_PARSE_NODE_KIND_PATTERN(ParenPattern) CARBON_PARSE_NODE_KIND_PATTERN(TuplePattern) CARBON_PARSE_NODE_KIND_PATTERN(StructPatternStart) +CARBON_PARSE_NODE_KIND_PATTERN(StructPatternFieldLetBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(StructPatternFieldVarBindingPattern) CARBON_PARSE_NODE_KIND_PATTERN(StructPatternDesignatedField) CARBON_PARSE_NODE_KIND_PATTERN(StructPattern) diff --git a/toolchain/parse/testdata/let/fail_let_struct_identifier_only.carbon b/toolchain/parse/testdata/let/fail_let_struct_identifier_only.carbon index 7022f2138573..59d4f5ea45bf 100644 --- a/toolchain/parse/testdata/let/fail_let_struct_identifier_only.carbon +++ b/toolchain/parse/testdata/let/fail_let_struct_identifier_only.carbon @@ -19,7 +19,7 @@ let {s}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 's' // CHECK:STDOUT: │ │ │ ├─InvalidParse '}' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '}' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern 's' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern 's' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: ├─LetDecl ';' // CHECK:STDOUT: ├─FileEnd '' diff --git a/toolchain/parse/testdata/let/let_struct.carbon b/toolchain/parse/testdata/let/let_struct.carbon index 24151f91cd0d..94e1852d59ca 100644 --- a/toolchain/parse/testdata/let/let_struct.carbon +++ b/toolchain/parse/testdata/let/let_struct.carbon @@ -70,12 +70,12 @@ let {ref s: str, i: i32} = {.s = "hello ref shorthand", .i = 4}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 's' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─StringTypeLiteral 'str' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'i' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -107,7 +107,7 @@ let {ref s: str, i: i32} = {.s = "hello ref shorthand", .i = 4}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'i' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -168,12 +168,12 @@ let {ref s: str, i: i32} = {.s = "hello ref shorthand", .i = 4}; // CHECK:STDOUT: │ │ │ ╭─RefBindingName 'ref' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─StringTypeLiteral 'str' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'i' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' diff --git a/toolchain/parse/testdata/struct/struct_pattern.carbon b/toolchain/parse/testdata/struct/struct_pattern.carbon index becd4f88a191..2519e51111c7 100644 --- a/toolchain/parse/testdata/struct/struct_pattern.carbon +++ b/toolchain/parse/testdata/struct/struct_pattern.carbon @@ -370,12 +370,12 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -391,12 +391,12 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─RefBindingName 'ref' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -419,7 +419,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'm' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -434,7 +434,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ╭─StructFieldDesignator '.' @@ -464,7 +464,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ╭─StructFieldDesignator '.' @@ -472,12 +472,12 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'a' // CHECK:STDOUT: │ │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'b' // CHECK:STDOUT: │ │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ │ ├─StructPattern '}' // CHECK:STDOUT: │ │ ├─StructPatternDesignatedField '=' // CHECK:STDOUT: │ ├─StructPattern '}' @@ -494,7 +494,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature ',' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse ',' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse ',' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern ',' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ',' has_error // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' @@ -510,7 +510,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature '=' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '=' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '=' has_error -// CHECK:STDOUT: │ │ │ ╭─LetBindingPattern '=' has_error +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldLetBindingPattern '=' has_error // CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '=' // CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'y' // CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error @@ -599,7 +599,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature ',' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse ',' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse ',' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern ',' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ',' has_error // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' @@ -650,7 +650,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature ':' has_error // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' has_error // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -665,7 +665,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─InvalidParse '}' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -680,7 +680,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -785,7 +785,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'foo' // CHECK:STDOUT: │ │ │ ├─InvalidParse '.' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '.' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern 'foo' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern 'foo' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -800,12 +800,12 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -820,12 +820,12 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'foo' // CHECK:STDOUT: │ │ │ ├─InvalidParse 'y' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse 'y' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern 'foo' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern 'foo' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -840,7 +840,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature '!' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '!' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '!' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern '!' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern '!' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -917,7 +917,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature '"foo"' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '"foo"' has_error // CHECK:STDOUT: │ │ │ ├─InvalidParse '"foo"' has_error -// CHECK:STDOUT: │ │ ├─LetBindingPattern '"foo"' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern '"foo"' has_error // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ╭─StructFieldDesignator '.' @@ -941,13 +941,13 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─TuplePatternStart '(' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'z' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' @@ -969,13 +969,13 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─TuplePatternStart '(' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'z' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' @@ -997,18 +997,18 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─StructPatternStart '{' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'z' // CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' @@ -1024,7 +1024,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─UnderscoreName '_' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' has_error // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' has_error // CHECK:STDOUT: │ │ ╭─StructPattern '}' has_error // CHECK:STDOUT: │ ├─VariablePattern 'var' // CHECK:STDOUT: │ ├─VariableInitializer '=' @@ -1037,7 +1037,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─RefBindingName 'ref' has_error // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' has_error // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' has_error +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' // CHECK:STDOUT: │ │ ╭─StructLiteralStart '{' @@ -1048,7 +1048,7 @@ let {var _: i32} = {}; // CHECK:STDOUT: │ │ │ ╭─UnderscoreName '_' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' has_error // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':' has_error +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldVarBindingPattern ':' has_error // CHECK:STDOUT: │ │ ├─VariablePattern 'var' has_error // CHECK:STDOUT: │ ├─StructPattern '}' has_error // CHECK:STDOUT: │ ├─LetInitializer '=' diff --git a/toolchain/parse/testdata/var/unused.carbon b/toolchain/parse/testdata/var/unused.carbon index 3c1a93a1fc97..c0768d8c7239 100644 --- a/toolchain/parse/testdata/var/unused.carbon +++ b/toolchain/parse/testdata/var/unused.carbon @@ -316,7 +316,7 @@ var unused (unused y: i32) = (0,); // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ │ ╭─UnusedPattern 'unused' // CHECK:STDOUT: │ │ ├─VariablePattern 'var' // CHECK:STDOUT: │ ├─StructPattern '}' @@ -337,7 +337,7 @@ var unused (unused y: i32) = (0,); // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ │ ╭─VariablePattern 'var' // CHECK:STDOUT: │ │ ├─UnusedPattern 'unused' // CHECK:STDOUT: │ ├─StructPattern '}' @@ -350,12 +350,12 @@ var unused (unused y: i32) = (0,); // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─LetBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldLetBindingPattern ':' // CHECK:STDOUT: │ │ ╭─StructPattern '}' // CHECK:STDOUT: │ ├─UnusedPattern 'unused' // CHECK:STDOUT: │ ├─LetInitializer '=' @@ -367,12 +367,12 @@ var unused (unused y: i32) = (0,); // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─UnusedPattern 'unused' // CHECK:STDOUT: │ │ ╭─StructPattern '}' // CHECK:STDOUT: │ ├─VariablePattern 'var' @@ -385,12 +385,12 @@ var unused (unused y: i32) = (0,); // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ╭─StructPattern '}' // CHECK:STDOUT: │ │ ╭─UnusedPattern 'unused' // CHECK:STDOUT: │ ├─VariablePattern 'var' diff --git a/toolchain/parse/testdata/var/var_pattern.carbon b/toolchain/parse/testdata/var/var_pattern.carbon index de244781f703..3a3561b4c840 100644 --- a/toolchain/parse/testdata/var/var_pattern.carbon +++ b/toolchain/parse/testdata/var/var_pattern.carbon @@ -131,7 +131,7 @@ let (x: (), var (y: (), var z: ())) = ((), ((), ())); // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ │ ╭─TupleLiteralStart '(' // CHECK:STDOUT: │ │ │ ├─TupleLiteral ')' -// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ╭─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─VariablePattern 'var' // CHECK:STDOUT: │ ├─StructPattern '}' // CHECK:STDOUT: │ ├─LetInitializer '=' diff --git a/toolchain/parse/testdata/var/var_struct.carbon b/toolchain/parse/testdata/var/var_struct.carbon index afcd5ba268d9..67d9887145a3 100644 --- a/toolchain/parse/testdata/var/var_struct.carbon +++ b/toolchain/parse/testdata/var/var_struct.carbon @@ -63,12 +63,12 @@ var {.s = s: str, i: 32} = {.s = "hello mixed", .i = 1}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 's' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─StringTypeLiteral 'str' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ├─PatternListComma ',' // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'i' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntLiteral '32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ╭─StructPattern '}' // CHECK:STDOUT: │ ├─VariablePattern 'var' // CHECK:STDOUT: │ ├─VariableInitializer '=' @@ -101,7 +101,7 @@ var {.s = s: str, i: 32} = {.s = "hello mixed", .i = 1}; // CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'i' // CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':' // CHECK:STDOUT: │ │ │ ├─IntLiteral '32' -// CHECK:STDOUT: │ │ ├─VarBindingPattern ':' +// CHECK:STDOUT: │ │ ├─StructPatternFieldVarBindingPattern ':' // CHECK:STDOUT: │ │ ╭─StructPattern '}' // CHECK:STDOUT: │ ├─VariablePattern 'var' // CHECK:STDOUT: │ ├─VariableInitializer '=' diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index a8acb6ac063a..ffacfc9e3271 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -1594,6 +1594,36 @@ struct StructTypeLiteral { using StructPatternStart = LeafNode; +// shorthand let binding in a struct pattern such as `let {a: i32}`. +struct StructPatternFieldLetBindingPattern { + static constexpr auto Kind = + NodeKind::StructPatternFieldLetBindingPattern.Define( + {.category = NodeCategory::Pattern, .child_count = 3}); + + // TODO: is there some way to reuse AnyRuntimeBindingPatternName here? + NodeIdOneOf + name; + BindingPatternTypeStartId introducer; + Lex::ColonTokenIndex token; + AnyExprId type; +}; + +// shorthand var binding in a struct pattern such as `var {a: i32}`. +struct StructPatternFieldVarBindingPattern { + static constexpr auto Kind = + NodeKind::StructPatternFieldVarBindingPattern.Define( + {.category = NodeCategory::Pattern, .child_count = 3}); + + // TODO: is there some way to reuse AnyRuntimeBindingPatternName here? + NodeIdOneOf + name; + BindingPatternTypeStartId introducer; + Lex::ColonTokenIndex token; + AnyExprId type; +}; + // `.a = pattern` struct StructPatternDesignatedField { static constexpr auto Kind = NodeKind::StructPatternDesignatedField.Define( @@ -1605,8 +1635,9 @@ struct StructPatternDesignatedField { }; using StructPatternFieldId = - NodeIdOneOf; struct StructPattern { diff --git a/toolchain/sem_ir/inst_kind.def b/toolchain/sem_ir/inst_kind.def index 2e9a170bc7a4..18742cbc57e2 100644 --- a/toolchain/sem_ir/inst_kind.def +++ b/toolchain/sem_ir/inst_kind.def @@ -160,6 +160,7 @@ CARBON_SEM_IR_INST_KIND(StringLiteral) CARBON_SEM_IR_INST_KIND(StructAccess) CARBON_SEM_IR_INST_KIND(StructInit) CARBON_SEM_IR_INST_KIND(StructLiteral) +CARBON_SEM_IR_INST_KIND(StructPattern) CARBON_SEM_IR_INST_KIND(StructType) CARBON_SEM_IR_INST_KIND(StructValue) CARBON_SEM_IR_INST_KIND(SymbolicBinding) diff --git a/toolchain/sem_ir/pattern.cpp b/toolchain/sem_ir/pattern.cpp index fc46d6d25c63..e23da497b1e2 100644 --- a/toolchain/sem_ir/pattern.cpp +++ b/toolchain/sem_ir/pattern.cpp @@ -65,7 +65,11 @@ auto GetFirstBindingNameFromPatternId(const File& sem_ir, InstId pattern_id) continue; } - // TODO: Look through struct patterns. + if (auto struct_patt = inst.TryAs()) { + auto block = sem_ir.inst_blocks().Get(struct_patt->elements_id); + work_list.append(block.rbegin(), block.rend()); + continue; + } if (auto ref_pattern = inst.TryAs()) { // TODO: This introduces a name, but we don't model it as a binding. diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index b1ec8077ff3a..6d2169f1b494 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -2177,6 +2177,21 @@ struct StructLiteral { InstBlockId elements_id; }; +// A struct pattern, such as `{.x = y: i32, z: i32}`. +struct StructPattern { + static constexpr auto Kind = + InstKind::StructPattern.Define( + {.ir_name = "struct_pattern", + .expr_category = ExprCategory::Pattern, + .constant_kind = InstConstantKind::Always, + .is_lowered = false}); + + // Always a PatternType whose scrutinee type is a struct of the scrutinee + // types of the elements. + TypeId type_id; + InstBlockId elements_id; +}; + // The type of a struct. struct StructType { static constexpr auto Kind = InstKind::StructType.Define<