diff --git a/toolchain/common/index_base.h b/toolchain/common/index_base.h index 1fd70b4f937e..2d5f7cd48049 100644 --- a/toolchain/common/index_base.h +++ b/toolchain/common/index_base.h @@ -8,9 +8,6 @@ #include #include "common/ostream.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator.h" -#include "llvm/Support/Format.h" namespace Carbon { diff --git a/toolchain/lowering/lowering_handle.cpp b/toolchain/lowering/lowering_handle.cpp index 54fece4c0e9e..38793926f773 100644 --- a/toolchain/lowering/lowering_handle.cpp +++ b/toolchain/lowering/lowering_handle.cpp @@ -215,6 +215,18 @@ auto LoweringHandleStructType(LoweringFunctionContext& /*context*/, // No action to take. } +auto LoweringHandleTupleValue(LoweringFunctionContext& /*context*/, + SemanticsNodeId /*node_id*/, SemanticsNode node) + -> void { + CARBON_FATAL() << "TODO: Add support: " << node; +} + +auto LoweringHandleTupleType(LoweringFunctionContext& /*context*/, + SemanticsNodeId /*node_id*/, + SemanticsNode /*node*/) -> void { + // No action to take. +} + auto LoweringHandleStructTypeField(LoweringFunctionContext& /*context*/, SemanticsNodeId /*node_id*/, SemanticsNode /*node*/) -> void { diff --git a/toolchain/parser/parse_node_kind.def b/toolchain/parser/parse_node_kind.def index 1ad77a699aec..ea69a4eafc04 100644 --- a/toolchain/parser/parse_node_kind.def +++ b/toolchain/parser/parse_node_kind.def @@ -208,12 +208,12 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileConditionStart, 0) CARBON_PARSE_NODE_KIND_BRACKET(WhileCondition, WhileConditionStart) CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileStatement, 2) -// Parenthesized expressions: +// Parenthesized expressions, such as `(2)`: // ParenExpressionOrTupleLiteralStart // _external_: expression // ParenExpression - -// Tuples: +// +// Tuples, such as `(1, 2)`: // ParenExpressionOrTupleLiteralStart // _external_: expression // TupleLiteralComma diff --git a/toolchain/semantics/BUILD b/toolchain/semantics/BUILD index abcfc43d87bf..f21dc058fbca 100644 --- a/toolchain/semantics/BUILD +++ b/toolchain/semantics/BUILD @@ -74,6 +74,7 @@ cc_library( deps = [ ":semantics_builtin_kind", ":semantics_node", + ":semantics_node_kind", ":semantics_node_stack", "//common:check", "//common:ostream", diff --git a/toolchain/semantics/semantics_context.cpp b/toolchain/semantics/semantics_context.cpp index 9fffdd829013..69e8c4c32346 100644 --- a/toolchain/semantics/semantics_context.cpp +++ b/toolchain/semantics/semantics_context.cpp @@ -6,6 +6,7 @@ #include +#include "common/check.h" #include "common/vlog.h" #include "toolchain/diagnostics/diagnostic_kind.h" #include "toolchain/lexer/tokenized_buffer.h" @@ -14,6 +15,7 @@ #include "toolchain/semantics/semantics_ir.h" #include "toolchain/semantics/semantics_node.h" #include "toolchain/semantics/semantics_node_block_stack.h" +#include "toolchain/semantics/semantics_node_kind.h" namespace Carbon { @@ -372,11 +374,29 @@ auto SemanticsContext::ImplicitAsImpl(SemanticsNodeId value_id, // Type doesn't need to change. return ImplicitAsKind::Identical; } - if (as_type_id == SemanticsTypeId::TypeType) { - // TODO: When converting `()` to a type, the result is `() as Type`. - // Right now there is no tuple value support. - + if (value.kind() == SemanticsNodeKind::TupleValue) { + auto tuple_block_id = value.GetAsTupleValue(); + llvm::SmallVector type_ids; + // If it is empty tuple type, we don't fetch anything. + if (tuple_block_id != SemanticsNodeBlockId::Empty) { + const auto& tuple_block = semantics_ir_->GetNodeBlock(tuple_block_id); + for (auto tuple_node_id : tuple_block) { + // TODO: Eventually ExpressionAsType will insert implicit cast + // instructions. When that happens, this will need to verify the full + // tuple conversion will work before calling it. + type_ids.push_back( + ExpressionAsType(value.parse_node(), tuple_node_id)); + } + } + auto tuple_type_id = + CanonicalizeTupleType(value.parse_node(), std::move(type_ids)); + if (output_value_id != nullptr) { + *output_value_id = + semantics_ir_->GetTypeAllowBuiltinTypes(tuple_type_id); + } + return ImplicitAsKind::Compatible; + } // When converting `{}` to a type, the result is `{} as Type`. if (value.kind() == SemanticsNodeKind::StructValue && value.GetAsStructValue() == SemanticsNodeBlockId::Empty) { @@ -439,6 +459,14 @@ auto SemanticsContext::ParamOrArgSave(bool for_args) -> void { auto SemanticsContext::CanonicalizeType(SemanticsNodeId node_id) -> SemanticsTypeId { + auto node = semantics_ir_->GetNode(node_id); + if (node.kind() == SemanticsNodeKind::StubReference) { + node_id = node.GetAsStubReference(); + CARBON_CHECK(semantics_ir_->GetNode(node_id).kind() != + SemanticsNodeKind::StubReference) + << "Stub reference should not point to another stub reference"; + } + auto it = canonical_types_.find(node_id); if (it != canonical_types_.end()) { return it->second; @@ -474,13 +502,42 @@ auto SemanticsContext::CanonicalizeStructType(ParseTree::Node parse_node, parse_node, SemanticsTypeId::TypeType, refs_id)); auto type_id = semantics_ir_->AddType(node_id); CARBON_CHECK(canonical_types_.insert({node_id, type_id}).second); - canonical_struct_types_nodes_.push_back( - std::make_unique(canonical_id, type_id)); - canonical_struct_types_.InsertNode(canonical_struct_types_nodes_.back().get(), + canonical_types_nodes_.push_back( + std::make_unique(canonical_id, type_id)); + canonical_struct_types_.InsertNode(canonical_types_nodes_.back().get(), insert_pos); return type_id; } +auto SemanticsContext::CanonicalizeTupleType( + ParseTree::Node parse_node, llvm::SmallVector&& type_ids) + -> SemanticsTypeId { + llvm::FoldingSetNodeID canonical_id; + for (const auto& type_id : type_ids) { + canonical_id.AddInteger(type_id.index); + } + // If a tuple with matching fields was already created, reuse it. + void* insert_pos; + auto* node = + canonical_tuple_types_.FindNodeOrInsertPos(canonical_id, insert_pos); + if (node != nullptr) { + return node->type_id(); + } + // The tuple type doesn't already exist, so create and store it as canonical. + auto type_block_id = semantics_ir_->AddTypeBlock(); + auto& type_block = semantics_ir_->GetTypeBlock(type_block_id); + type_block = std::move(type_ids); + auto node_id = AddNode(SemanticsNode::TupleType::Make( + parse_node, SemanticsTypeId::TypeType, type_block_id)); + auto type_id = semantics_ir_->AddType(node_id); + CARBON_CHECK(canonical_types_.insert({node_id, type_id}).second); + canonical_types_nodes_.push_back( + std::make_unique(canonical_id, type_id)); + canonical_tuple_types_.InsertNode(canonical_types_nodes_.back().get(), + insert_pos); + return type_id; +} + auto SemanticsContext::PrintForStackDump(llvm::raw_ostream& output) const -> void { node_stack_.PrintForStackDump(output); diff --git a/toolchain/semantics/semantics_context.h b/toolchain/semantics/semantics_context.h index de99d46e95f3..52f633d438c4 100644 --- a/toolchain/semantics/semantics_context.h +++ b/toolchain/semantics/semantics_context.h @@ -147,10 +147,24 @@ class SemanticsContext { auto CanonicalizeStructType(ParseTree::Node parse_node, SemanticsNodeBlockId refs_id) -> SemanticsTypeId; + // Handles canonicalization of tuple types. This may create a new tuple type + // if the `type_ids` doesn't match an existing tuple type. + auto CanonicalizeTupleType(ParseTree::Node parse_node, + llvm::SmallVector&& type_ids) + -> SemanticsTypeId; + // Converts an expression for use as a type. // TODO: This should eventually return a type ID. auto ExpressionAsType(ParseTree::Node parse_node, SemanticsNodeId value_id) -> SemanticsTypeId { + auto node = semantics_ir_->GetNode(value_id); + if (node.kind() == SemanticsNodeKind::StubReference) { + value_id = node.GetAsStubReference(); + CARBON_CHECK(semantics_ir_->GetNode(value_id).kind() != + SemanticsNodeKind::StubReference) + << "Stub reference should not point to another stub reference"; + } + return CanonicalizeType( ImplicitAsRequired(parse_node, value_id, SemanticsTypeId::TypeType)); } @@ -215,11 +229,11 @@ class SemanticsContext { Compatible, }; - // A FoldingSet node for a struct type. - class StructTypeNode : public llvm::FastFoldingSetNode { + // A FoldingSet node for a struct or tuple type. + class TypeNode : public llvm::FastFoldingSetNode { public: - explicit StructTypeNode(const llvm::FoldingSetNodeID& node_id, - SemanticsTypeId type_id) + explicit TypeNode(const llvm::FoldingSetNodeID& node_id, + SemanticsTypeId type_id) : llvm::FastFoldingSetNode(node_id), type_id_(type_id) {} auto type_id() -> SemanticsTypeId { return type_id_; } @@ -308,12 +322,16 @@ class SemanticsContext { // Tracks struct type literals which have been defined, so that they aren't // repeatedly redefined. - llvm::FoldingSet canonical_struct_types_; + llvm::FoldingSet canonical_struct_types_; - // Storage for the nodes in canonical_struct_types_. This stores in pointers - // so that canonical_struct_types_ can have stable pointers. - llvm::SmallVector> - canonical_struct_types_nodes_; + // Tracks tuple type literals which have been defined, so that they aren't + // repeatedly redefined. + llvm::FoldingSet canonical_tuple_types_; + + // Storage for the nodes in canonical_struct_types_ and + // canonical_tuple_types_. This stores in pointers so that FoldingSet can have + // stable pointers. + llvm::SmallVector> canonical_types_nodes_; }; // Parse node handlers. Returns false for unrecoverable errors. diff --git a/toolchain/semantics/semantics_handle_codeblock.cpp b/toolchain/semantics/semantics_handle_codeblock.cpp index 19e137896473..6987423eb909 100644 --- a/toolchain/semantics/semantics_handle_codeblock.cpp +++ b/toolchain/semantics/semantics_handle_codeblock.cpp @@ -3,7 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "toolchain/semantics/semantics_context.h" -#include "toolchain/semantics/semantics_node.h" namespace Carbon { diff --git a/toolchain/semantics/semantics_handle_paren.cpp b/toolchain/semantics/semantics_handle_paren.cpp index 5d69d60e5496..6cec1fc0108a 100644 --- a/toolchain/semantics/semantics_handle_paren.cpp +++ b/toolchain/semantics/semantics_handle_paren.cpp @@ -2,6 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include + #include "toolchain/semantics/semantics_context.h" namespace Carbon { @@ -9,6 +11,10 @@ namespace Carbon { auto SemanticsHandleParenExpression(SemanticsContext& context, ParseTree::Node parse_node) -> bool { auto value_id = context.node_stack().PopExpression(); + // ParamOrArgStart was called for tuple handling; clean up the ParamOrArg + // support for non-tuple cases. + context.ParamOrArgEnd( + /*for_args=*/true, ParseNodeKind::ParenExpressionOrTupleLiteralStart); context.node_stack() .PopAndDiscardSoloParseNode< ParseNodeKind::ParenExpressionOrTupleLiteralStart>(); @@ -19,17 +25,36 @@ auto SemanticsHandleParenExpression(SemanticsContext& context, auto SemanticsHandleParenExpressionOrTupleLiteralStart( SemanticsContext& context, ParseTree::Node parse_node) -> bool { context.node_stack().Push(parse_node); + context.ParamOrArgStart(); + return true; +} + +auto SemanticsHandleTupleLiteralComma(SemanticsContext& context, + ParseTree::Node /*parse_node*/) -> bool { + context.ParamOrArgComma(/*for_args=*/true); return true; } auto SemanticsHandleTupleLiteral(SemanticsContext& context, ParseTree::Node parse_node) -> bool { - return context.TODO(parse_node, "HandleTupleLiteral"); -} + auto refs_id = context.ParamOrArgEnd( + /*for_args=*/true, ParseNodeKind::ParenExpressionOrTupleLiteralStart); -auto SemanticsHandleTupleLiteralComma(SemanticsContext& context, - ParseTree::Node parse_node) -> bool { - return context.TODO(parse_node, "HandleTupleLiteralComma"); + context.node_stack() + .PopAndDiscardSoloParseNode< + ParseNodeKind::ParenExpressionOrTupleLiteralStart>(); + const auto& node_block = context.semantics_ir().GetNodeBlock(refs_id); + llvm::SmallVector type_ids; + type_ids.reserve(node_block.size()); + for (auto node : node_block) { + type_ids.push_back(context.semantics_ir().GetNode(node).type_id()); + } + auto type_id = context.CanonicalizeTupleType(parse_node, std::move(type_ids)); + + auto value_id = context.AddNode( + SemanticsNode::TupleValue::Make(parse_node, type_id, refs_id)); + context.node_stack().Push(parse_node, value_id); + return true; } } // namespace Carbon diff --git a/toolchain/semantics/semantics_handle_variable.cpp b/toolchain/semantics/semantics_handle_variable.cpp index 77c3bde94d7e..cd81a74c281b 100644 --- a/toolchain/semantics/semantics_handle_variable.cpp +++ b/toolchain/semantics/semantics_handle_variable.cpp @@ -26,7 +26,6 @@ auto SemanticsHandleVariableDeclaration(SemanticsContext& context, auto binding = context.semantics_ir().GetNode(binding_id); auto [name_id, storage_id] = binding.GetAsBindName(); context.AddNameToLookup(binding.parse_node(), name_id, storage_id); - // If there was an initializer, assign it to storage. if (has_init) { auto cast_value_id = context.ImplicitAsRequired( diff --git a/toolchain/semantics/semantics_ir.cpp b/toolchain/semantics/semantics_ir.cpp index f8a1f9a8533f..98d4cdd07ce2 100644 --- a/toolchain/semantics/semantics_ir.cpp +++ b/toolchain/semantics/semantics_ir.cpp @@ -10,6 +10,7 @@ #include "toolchain/semantics/semantics_builtin_kind.h" #include "toolchain/semantics/semantics_context.h" #include "toolchain/semantics/semantics_node.h" +#include "toolchain/semantics/semantics_node_kind.h" namespace Carbon { @@ -241,6 +242,29 @@ auto SemanticsIR::StringifyType(SemanticsTypeId type_id) -> std::string { steps.push_back({.node_id = GetTypeAllowBuiltinTypes(node.type_id())}); break; } + case SemanticsNodeKind::TupleType: { + auto refs = GetTypeBlock(node.GetAsTupleType()); + if (refs.empty()) { + out << "() as type"; + break; + } else if (step.index == 0) { + out << "("; + } else if (step.index < static_cast(refs.size())) { + out << ", "; + } else { + // A tuple of one element has a comma to disambiguate from an + // expression. + if (step.index == 1) { + out << ","; + } + out << ") as type"; + break; + } + steps.push_back({.node_id = step.node_id, .index = step.index + 1}); + steps.push_back( + {.node_id = GetTypeAllowBuiltinTypes(refs[step.index])}); + break; + } case SemanticsNodeKind::Assign: case SemanticsNodeKind::BinaryOperatorAdd: case SemanticsNodeKind::BindName: @@ -262,6 +286,7 @@ auto SemanticsIR::StringifyType(SemanticsTypeId type_id) -> std::string { case SemanticsNodeKind::StructMemberAccess: case SemanticsNodeKind::StructValue: case SemanticsNodeKind::StubReference: + case SemanticsNodeKind::TupleValue: case SemanticsNodeKind::UnaryOperatorNot: case SemanticsNodeKind::VarStorage: // We don't need to handle stringification for nodes that don't show up diff --git a/toolchain/semantics/semantics_ir.h b/toolchain/semantics/semantics_ir.h index 37d4dcf323be..98260a26af8b 100644 --- a/toolchain/semantics/semantics_ir.h +++ b/toolchain/semantics/semantics_ir.h @@ -90,8 +90,7 @@ class SemanticsIR { } // Returns the requested callable. - auto GetFunction(SemanticsFunctionId function_id) const - -> const SemanticsFunction& { + auto GetFunction(SemanticsFunctionId function_id) const -> SemanticsFunction { return functions_[function_id.index]; } @@ -225,11 +224,11 @@ class SemanticsIR { return type_id; } - // Gets the node ID for a type. This doesn't handle TypeType or Error in + // Gets the node ID for a type. This doesn't handle TypeType or InvalidType in // order to avoid a check; callers that need that should use // GetTypeAllowBuiltinTypes. auto GetType(SemanticsTypeId type_id) const -> SemanticsNodeId { - // Double-check it's not called with TypeType or Error. + // Double-check it's not called with TypeType or InvalidType. CARBON_CHECK(type_id.index >= 0) << "Invalid argument for GetType: " << type_id; return types_[type_id.index]; @@ -246,6 +245,25 @@ class SemanticsIR { } } + // Adds an empty type block, returning an ID to reference it. + auto AddTypeBlock() -> SemanticsTypeBlockId { + SemanticsTypeBlockId id(type_blocks_.size()); + type_blocks_.push_back({}); + return id; + } + + // Returns the requested type block. + auto GetTypeBlock(SemanticsTypeBlockId block_id) const + -> const llvm::SmallVector& { + return type_blocks_[block_id.index]; + } + + // Returns the requested type block. + auto GetTypeBlock(SemanticsTypeBlockId block_id) + -> llvm::SmallVector& { + return type_blocks_[block_id.index]; + } + // Produces a string version of a type. auto StringifyType(SemanticsTypeId type_id) -> std::string; @@ -308,6 +326,9 @@ class SemanticsIR { // by lowering. llvm::SmallVector types_; + // Storage for blocks within the IR. These reference entries in types_. + llvm::SmallVector> type_blocks_; + // The type of the empty tuple. This is special-cased due to its use in // implicit function returns. SemanticsTypeId empty_tuple_type_id_ = SemanticsTypeId::Invalid; diff --git a/toolchain/semantics/semantics_node.cpp b/toolchain/semantics/semantics_node.cpp index 8d6123858086..189e40d01c82 100644 --- a/toolchain/semantics/semantics_node.cpp +++ b/toolchain/semantics/semantics_node.cpp @@ -4,8 +4,6 @@ #include "toolchain/semantics/semantics_node.h" -#include "toolchain/semantics/semantics_builtin_kind.h" - namespace Carbon { static auto PrintArgs(llvm::raw_ostream& /*out*/, diff --git a/toolchain/semantics/semantics_node.h b/toolchain/semantics/semantics_node.h index 4a098fcde7de..0aafd73b3b85 100644 --- a/toolchain/semantics/semantics_node.h +++ b/toolchain/semantics/semantics_node.h @@ -194,6 +194,15 @@ constexpr SemanticsTypeId SemanticsTypeId::Error = constexpr SemanticsTypeId SemanticsTypeId::Invalid = SemanticsTypeId(SemanticsTypeId::InvalidIndex); +// The ID of a type block. +struct SemanticsTypeBlockId : public IndexBase { + using IndexBase::IndexBase; + auto Print(llvm::raw_ostream& out) const -> void { + out << "typeBlock"; + IndexBase::Print(out); + } +}; + // An index for member access. struct SemanticsMemberIndex : public IndexBase { using IndexBase::IndexBase; @@ -400,11 +409,16 @@ class SemanticsNode { using StubReference = Factory; + using TupleType = + Factory; + + using TupleValue = + Factory; + using UnaryOperatorNot = Factory; using VarStorage = Factory; - SemanticsNode() : SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Invalid, SemanticsTypeId::Invalid) {} diff --git a/toolchain/semantics/semantics_node_kind.def b/toolchain/semantics/semantics_node_kind.def index 5f3a54eb04fc..a5cd5748a482 100644 --- a/toolchain/semantics/semantics_node_kind.def +++ b/toolchain/semantics/semantics_node_kind.def @@ -49,6 +49,8 @@ CARBON_SEMANTICS_NODE_KIND(StructType) CARBON_SEMANTICS_NODE_KIND(StructTypeField) CARBON_SEMANTICS_NODE_KIND(StructValue) CARBON_SEMANTICS_NODE_KIND(StubReference) +CARBON_SEMANTICS_NODE_KIND(TupleType) +CARBON_SEMANTICS_NODE_KIND(TupleValue) CARBON_SEMANTICS_NODE_KIND(UnaryOperatorNot) CARBON_SEMANTICS_NODE_KIND(VarStorage) diff --git a/toolchain/semantics/semantics_node_stack.h b/toolchain/semantics/semantics_node_stack.h index ad2e2b6c2b31..8b719b686845 100644 --- a/toolchain/semantics/semantics_node_stack.h +++ b/toolchain/semantics/semantics_node_stack.h @@ -256,6 +256,8 @@ class SemanticsNodeStack { case Carbon::ParseNodeKind::StructLiteral: case Carbon::ParseNodeKind::StructTypeLiteral: return IdKind::SemanticsNodeId; + case Carbon::ParseNodeKind::TupleLiteral: + return IdKind::SemanticsNodeId; case Carbon::ParseNodeKind::IfExpressionThen: case Carbon::ParseNodeKind::IfStatementElse: case Carbon::ParseNodeKind::ParameterList: diff --git a/toolchain/semantics/testdata/function/call/empty_tuple.carbon b/toolchain/semantics/testdata/function/call/empty_tuple.carbon new file mode 100644 index 000000000000..c8616e4bc89d --- /dev/null +++ b/toolchain/semantics/testdata/function/call/empty_tuple.carbon @@ -0,0 +1,75 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type0, body: {block4}}}, +// CHECK:STDOUT: {name: str2, param_refs: block0, body: {block5}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: Echo, +// CHECK:STDOUT: a, +// CHECK:STDOUT: Main, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: nodeEmptyTupleType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type0}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+2, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0}, +// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0, type: type0}, +// CHECK:STDOUT: {kind: Return}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Echo(a: ()) -> () { + return a; +} + +fn Main() { + Echo(()); +} diff --git a/toolchain/semantics/testdata/function/call/return_implicit.carbon b/toolchain/semantics/testdata/function/call/return_implicit.carbon new file mode 100644 index 000000000000..c7455ad21086 --- /dev/null +++ b/toolchain/semantics/testdata/function/call/return_implicit.carbon @@ -0,0 +1,27 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// TODO test if builtin implicit empty tuple type is treated as being the same type as an explicitly-created empty tuple type. +// Currently crashes due to call expression. +// fn MakeImplicitEmptyTuple() {} +// var v: () = MakeImplicitEmptyTuple(); diff --git a/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon b/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon index 5847198f3a23..5b99324bb18c 100644 --- a/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon +++ b/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon @@ -5,6 +5,7 @@ // AUTOUPDATE // CHECK:STDOUT: cross_reference_irs_size: 1 // CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -14,14 +15,25 @@ // CHECK:STDOUT: F, // CHECK:STDOUT: ] // CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+0, // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], // CHECK:STDOUT: ] -// CHECK:STDERR: fail_missing_return_empty_tuple.carbon:[[@LINE+1]]:12: Semantics TODO: HandleTupleLiteral fn F() -> () { +// CHECK:STDERR: fail_missing_return_empty_tuple.carbon:[[@LINE+1]]:1: Missing `return` at end of function with declared return type. } diff --git a/toolchain/semantics/testdata/return/tuple.carbon b/toolchain/semantics/testdata/return/tuple.carbon new file mode 100644 index 000000000000..d84e8db530c8 --- /dev/null +++ b/toolchain/semantics/testdata/return/tuple.carbon @@ -0,0 +1,70 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type2, body: {block3}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 15, +// CHECK:STDOUT: 35, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: Main, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type1}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block4, type: type2}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+10, type: type2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + + +fn Main() -> (i32, i32) { + return (15, 35); +} diff --git a/toolchain/semantics/testdata/struct/tuple_as_element.carbon b/toolchain/semantics/testdata/struct/tuple_as_element.carbon new file mode 100644 index 000000000000..366f7ad29983 --- /dev/null +++ b/toolchain/semantics/testdata/struct/tuple_as_element.carbon @@ -0,0 +1,112 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 2, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: a, +// CHECK:STDOUT: b, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type1}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str2, type: type2}, +// CHECK:STDOUT: {kind: StructType, arg0: block2, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type3}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+7, type: type3}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: type0}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block6, type: type2}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str2, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+14, type: type2}, +// CHECK:STDOUT: {kind: StructValue, arg0: block5, type: type3}, +// CHECK:STDOUT: {kind: Assign, arg0: node+7, arg1: node+17, type: type3}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block8, type: type1}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str2, type: type2}, +// CHECK:STDOUT: {kind: VarStorage, type: type3}, +// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+23, type: type3}, +// CHECK:STDOUT: {kind: Assign, arg0: node+23, arg1: node+7, type: type3}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: node+23, +// CHECK:STDOUT: node+24, +// CHECK:STDOUT: node+25, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: {.a: i32, .b: (i32,)} = {.a = 1, .b = (2,)}; +var y: {.a: i32, .b: (i32,)} = x; diff --git a/toolchain/semantics/testdata/tuples/empty.carbon b/toolchain/semantics/testdata/tuples/empty.carbon new file mode 100644 index 000000000000..d164952cf802 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/empty.carbon @@ -0,0 +1,50 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+2, type: type0}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+4, type: type0}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+7, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+7, arg1: node+2, type: type0}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: () = (); +var y: () = x; diff --git a/toolchain/semantics/testdata/tuples/fail_assign_empty.carbon b/toolchain/semantics/testdata/tuples/fail_assign_empty.carbon new file mode 100644 index 000000000000..02ffdc63d8c8 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_assign_empty.carbon @@ -0,0 +1,53 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+4, type: type2}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock2, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type3}, +// CHECK:STDOUT: {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_assign_empty.carbon:[[@LINE+1]]:19: Cannot implicitly convert from `() as type` to `(i32,) as type`. +var x: (i32,) = (); diff --git a/toolchain/semantics/testdata/tuples/fail_assign_to_empty.carbon b/toolchain/semantics/testdata/tuples/fail_assign_to_empty.carbon new file mode 100644 index 000000000000..ee541c8eb2e8 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_assign_to_empty.carbon @@ -0,0 +1,43 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 66, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block0, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+2, type: type0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeError, type: typeError}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_assign_to_empty.carbon:[[@LINE+1]]:17: Cannot implicitly convert from `i32` to `() as type`. +var x: () = (66); diff --git a/toolchain/semantics/testdata/tuples/fail_element_type_mismatch.carbon b/toolchain/semantics/testdata/tuples/fail_element_type_mismatch.carbon new file mode 100644 index 000000000000..186fd2b74db4 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_element_type_mismatch.carbon @@ -0,0 +1,71 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 2, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: {mantissa: 6589, exponent: -2, is_decimal: 1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: nodeFloatingPointType, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+5, type: type2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type1}, +// CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type3}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type3}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock2, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type4}, +// CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: nodeError, type: typeError}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_element_type_mismatch.carbon:[[@LINE+1]]:31: Cannot implicitly convert from `(i32, f64) as type` to `(i32, i32) as type`. +var x: (i32, i32) = (2, 65.89); diff --git a/toolchain/semantics/testdata/tuples/fail_too_few_element.carbon b/toolchain/semantics/testdata/tuples/fail_too_few_element.carbon new file mode 100644 index 000000000000..d1757d5c03c5 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_too_few_element.carbon @@ -0,0 +1,64 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 2, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+5, type: type2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type1}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock2, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type3}, +// CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: nodeError, type: typeError}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_too_few_element.carbon:[[@LINE+1]]:26: Cannot implicitly convert from `(i32,) as type` to `(i32, i32) as type`. +var x: (i32, i32) = (2, ); diff --git a/toolchain/semantics/testdata/tuples/fail_type_assign.carbon b/toolchain/semantics/testdata/tuples/fail_type_assign.carbon new file mode 100644 index 000000000000..bb40fdddc4d7 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_type_assign.carbon @@ -0,0 +1,55 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+4, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_type_assign.carbon:[[@LINE+1]]:25: Cannot implicitly convert from `(Type,) as type` to `(i32,) as type`. +var x: (i32, ) = (i32, ); diff --git a/toolchain/semantics/testdata/tuples/fail_value_as_type.carbon b/toolchain/semantics/testdata/tuples/fail_value_as_type.carbon new file mode 100644 index 000000000000..f35c99cac0d7 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/fail_value_as_type.carbon @@ -0,0 +1,49 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+0, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type1}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+5, type: type2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_value_as_type.carbon:[[@LINE+1]]:12: Cannot implicitly convert from `i32` to `Type`. +var x: (1, ); diff --git a/toolchain/semantics/testdata/tuples/nested_tuple.carbon b/toolchain/semantics/testdata/tuples/nested_tuple.carbon new file mode 100644 index 000000000000..db8c154d2406 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/nested_tuple.carbon @@ -0,0 +1,95 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 12, +// CHECK:STDOUT: 76, +// CHECK:STDOUT: 6, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+3, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type1}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock2, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock3, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type4}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+10, type: type4}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: type2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+14, type: type2}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block4, type: type3}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+16, type: type3}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+18, type: type2}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block5, type: type4}, +// CHECK:STDOUT: {kind: Assign, arg0: node+10, arg1: node+20, type: type4}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: ((i32, i32), i32) = ((12, 76), 6); diff --git a/toolchain/semantics/testdata/tuples/one_element.carbon b/toolchain/semantics/testdata/tuples/one_element.carbon new file mode 100644 index 000000000000..1bb1e525270b --- /dev/null +++ b/toolchain/semantics/testdata/tuples/one_element.carbon @@ -0,0 +1,72 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 4, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+4, type: type2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type1}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type2}, +// CHECK:STDOUT: {kind: Assign, arg0: node+4, arg1: node+8, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block4, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+12, type: type2}, +// CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: node+4, type: type2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: (i32,) = (4,); +var y: (i32,) = x; diff --git a/toolchain/semantics/testdata/tuples/two_elements.carbon b/toolchain/semantics/testdata/tuples/two_elements.carbon new file mode 100644 index 000000000000..db30e6b17ba4 --- /dev/null +++ b/toolchain/semantics/testdata/tuples/two_elements.carbon @@ -0,0 +1,84 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 4, +// CHECK:STDOUT: 102, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: x, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock0, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block2, type: type0}, +// CHECK:STDOUT: {kind: TupleType, arg0: typeBlock1, type: typeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+5, type: type2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type1}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block3, type: type2}, +// CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+11, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeIntegerType, type: typeTypeType}, +// CHECK:STDOUT: {kind: TupleValue, arg0: block4, type: type0}, +// CHECK:STDOUT: {kind: VarStorage, type: type2}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+16, type: type2}, +// CHECK:STDOUT: {kind: Assign, arg0: node+16, arg1: node+5, type: type2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: (i32, i32) = (4, 102); +var y: (i32, i32) = x;