From 2eef8c751b9f685d2dca7c8394bda4d4cdf0d30e Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Thu, 30 Mar 2023 10:15:11 -0700 Subject: [PATCH] Add semantics for struct type and value literals. (#2709) This handles the basics of type and value for structs. Structurally, these look like parameters and arguments (respectively) because expressions/generics may result in multiple IR nodes being generated. Because `{}` needs to be cast to a type for storage, I'm also adding some validation that's not specific to `{}`, e.g. that `1` shouldn't be valid as a type for storage (previously, nothing errored for that). This adds more stringification of types, particularly literals, because they come up in value errors now. ImplicitAs is the result of me mulling whether I'm taking the right approach on type conversions. I think it needs to return a value so that if the implicit cast rewrites the value, the result is accessible to the caller. I may reorient the current TryTypeConversion logic to be more based on the ImplicitAs logic. --- toolchain/diagnostics/diagnostic_kind.def | 1 + toolchain/lowering/lowering.cpp | 20 + .../semantics/semantics_builtin_kind.def | 6 + toolchain/semantics/semantics_ir.cpp | 19 + toolchain/semantics/semantics_ir.h | 6 + toolchain/semantics/semantics_node.h | 14 + toolchain/semantics/semantics_node_kind.def | 4 + toolchain/semantics/semantics_node_stack.cpp | 9 +- toolchain/semantics/semantics_node_stack.h | 12 +- .../semantics_parse_tree_handler.cpp | 380 ++++++++++++------ .../semantics/semantics_parse_tree_handler.h | 43 +- .../testdata/basics/builtin_nodes.carbon | 2 + .../function/call/empty_struct.carbon | 66 +++ .../function/call/fail_param_count.carbon | 40 +- .../function/call/fail_param_type.carbon | 10 +- .../function/call/more_param_ir.carbon | 24 +- .../testdata/function/call/params_one.carbon | 10 +- .../function/call/params_one_comma.carbon | 20 +- .../testdata/function/call/params_two.carbon | 16 +- .../function/call/params_two_comma.carbon | 34 +- .../semantics/testdata/struct/empty.carbon | 42 ++ .../testdata/struct/fail_assign_empty.carbon | 45 +++ .../struct/fail_assign_to_empty.carbon | 54 +++ .../struct/fail_field_name_mismatch.carbon | 64 +++ .../struct/fail_field_type_mismatch.carbon | 64 +++ .../struct/fail_too_few_values.carbon | 67 +++ .../testdata/struct/fail_type_assign.carbon | 54 +++ .../testdata/struct/fail_value_as_type.carbon | 52 +++ .../testdata/struct/one_entry.carbon | 79 ++++ .../testdata/struct/two_entries.carbon | 94 +++++ .../var/fail_init_type_mismatch.carbon | 4 +- .../var/fail_storage_is_literal.carbon | 51 +++ 32 files changed, 1200 insertions(+), 206 deletions(-) create mode 100644 toolchain/semantics/testdata/function/call/empty_struct.carbon create mode 100644 toolchain/semantics/testdata/struct/empty.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_assign_empty.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_too_few_values.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_type_assign.carbon create mode 100644 toolchain/semantics/testdata/struct/fail_value_as_type.carbon create mode 100644 toolchain/semantics/testdata/struct/one_entry.carbon create mode 100644 toolchain/semantics/testdata/struct/two_entries.carbon create mode 100644 toolchain/semantics/testdata/var/fail_storage_is_literal.carbon diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 97889bd1fe80..a3a2c3cad9e4 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -102,6 +102,7 @@ CARBON_DIAGNOSTIC_KIND(ReturnStatementDisallowExpression) CARBON_DIAGNOSTIC_KIND(ReturnStatementImplicitNote) CARBON_DIAGNOSTIC_KIND(ReturnStatementMissingExpression) CARBON_DIAGNOSTIC_KIND(ReturnStatementTypeMismatch) +CARBON_DIAGNOSTIC_KIND(ImplicitAsConversionFailure) // ============================================================================ // Other diagnostics diff --git a/toolchain/lowering/lowering.cpp b/toolchain/lowering/lowering.cpp index 1e3bd1689570..7803e379aeeb 100644 --- a/toolchain/lowering/lowering.cpp +++ b/toolchain/lowering/lowering.cpp @@ -176,6 +176,26 @@ auto Lowering::HandleStringLiteralNode(SemanticsNodeId /*node_id*/, CARBON_FATAL() << "TODO: Add support: " << node; } +auto Lowering::HandleStructTypeNode(SemanticsNodeId /*node_id*/, + SemanticsNode node) -> void { + CARBON_FATAL() << "TODO: Add support: " << node; +} + +auto Lowering::HandleStructTypeFieldNode(SemanticsNodeId /*node_id*/, + SemanticsNode node) -> void { + CARBON_FATAL() << "TODO: Add support: " << node; +} + +auto Lowering::HandleStructValueNode(SemanticsNodeId /*node_id*/, + SemanticsNode node) -> void { + CARBON_FATAL() << "TODO: Add support: " << node; +} + +auto Lowering::HandleStubReferenceNode(SemanticsNodeId /*node_id*/, + SemanticsNode node) -> void { + CARBON_FATAL() << "TODO: Add support: " << node; +} + auto Lowering::HandleVarStorageNode(SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { CARBON_FATAL() << "TODO: Add support: " << node; diff --git a/toolchain/semantics/semantics_builtin_kind.def b/toolchain/semantics/semantics_builtin_kind.def index 036f1c7c29fd..b4eafcaad79a 100644 --- a/toolchain/semantics/semantics_builtin_kind.def +++ b/toolchain/semantics/semantics_builtin_kind.def @@ -60,6 +60,12 @@ CARBON_SEMANTICS_BUILTIN_KIND(FloatingPointType, TypeType, "f64") // The type of string values and String literals. CARBON_SEMANTICS_BUILTIN_KIND(StringType, TypeType, "String") +// The canonical empty struct type. +CARBON_SEMANTICS_BUILTIN_KIND(EmptyStructType, TypeType, "{} as Type") + +// The canonical empty struct. +CARBON_SEMANTICS_BUILTIN_KIND(EmptyStruct, EmptyStructType, "{}") + // The canonical empty tuple type. CARBON_SEMANTICS_BUILTIN_KIND(EmptyTupleType, TypeType, "() as Type") diff --git a/toolchain/semantics/semantics_ir.cpp b/toolchain/semantics/semantics_ir.cpp index fa00d3401f7f..5649935e4cd4 100644 --- a/toolchain/semantics/semantics_ir.cpp +++ b/toolchain/semantics/semantics_ir.cpp @@ -128,6 +128,23 @@ auto SemanticsIR::StringifyNodeImpl(llvm::raw_ostream& out, auto node = GetNode(node_id); switch (node.kind()) { + case SemanticsNodeKind::StructType: { + out << "{"; + auto refs = GetNodeBlock(node.GetAsStructType().second); + llvm::ListSeparator sep; + for (const auto& ref_id : refs) { + out << sep; + // TODO: Bound recursion depth or remove recursive step. + StringifyNodeImpl(out, ref_id); + } + out << "}"; + break; + } + case SemanticsNodeKind::StructTypeField: { + out << "." << GetString(node.GetAsStructTypeField()) << ": "; + StringifyNodeImpl(out, node.type_id()); + break; + } case SemanticsNodeKind::Assign: case SemanticsNodeKind::BinaryOperatorAdd: case SemanticsNodeKind::BindName: @@ -142,6 +159,8 @@ auto SemanticsIR::StringifyNodeImpl(llvm::raw_ostream& out, case SemanticsNodeKind::Return: case SemanticsNodeKind::ReturnExpression: case SemanticsNodeKind::StringLiteral: + case SemanticsNodeKind::StructValue: + case SemanticsNodeKind::StubReference: case SemanticsNodeKind::VarStorage: // We don't need to handle stringification for nodes that don't show up in // errors, but make it clear what's going on so that it's clearer when diff --git a/toolchain/semantics/semantics_ir.h b/toolchain/semantics/semantics_ir.h index 70f0b617655b..780053a34b2b 100644 --- a/toolchain/semantics/semantics_ir.h +++ b/toolchain/semantics/semantics_ir.h @@ -106,6 +106,12 @@ class SemanticsIR { return node_blocks_[block_id.index]; } + // Returns the requested real literal. + auto GetRealLiteral(SemanticsRealLiteralId int_id) const + -> const SemanticsRealLiteral& { + return real_literals_[int_id.index]; + } + // Returns the requested string. auto GetString(SemanticsStringId string_id) const -> llvm::StringRef { return strings_[string_id.index]; diff --git a/toolchain/semantics/semantics_node.h b/toolchain/semantics/semantics_node.h index 70cdfe8dd6cb..504c51b8eda6 100644 --- a/toolchain/semantics/semantics_node.h +++ b/toolchain/semantics/semantics_node.h @@ -299,6 +299,20 @@ class SemanticsNode { SemanticsBuiltinKind::StringType.AsInt(), SemanticsStringId /*string_id*/>; + using StructType = FactoryPreTyped< + SemanticsNodeKind::StructType, SemanticsBuiltinKind::TypeType.AsInt(), + SemanticsNodeBlockId /*ir_id*/, SemanticsNodeBlockId /*refs_id*/>; + + using StructTypeField = Factory; + + using StructValue = + Factory; + + using StubReference = + Factory; + using VarStorage = Factory; SemanticsNode() diff --git a/toolchain/semantics/semantics_node_kind.def b/toolchain/semantics/semantics_node_kind.def index 417c199b4003..d9cac417859f 100644 --- a/toolchain/semantics/semantics_node_kind.def +++ b/toolchain/semantics/semantics_node_kind.def @@ -33,6 +33,10 @@ CARBON_SEMANTICS_NODE_KIND(RealLiteral) CARBON_SEMANTICS_NODE_KIND(Return) CARBON_SEMANTICS_NODE_KIND(ReturnExpression) CARBON_SEMANTICS_NODE_KIND(StringLiteral) +CARBON_SEMANTICS_NODE_KIND(StructType) +CARBON_SEMANTICS_NODE_KIND(StructTypeField) +CARBON_SEMANTICS_NODE_KIND(StructValue) +CARBON_SEMANTICS_NODE_KIND(StubReference) CARBON_SEMANTICS_NODE_KIND(VarStorage) #undef CARBON_SEMANTICS_NODE_KIND diff --git a/toolchain/semantics/semantics_node_stack.cpp b/toolchain/semantics/semantics_node_stack.cpp index 9a3650e7e86e..c3f4bbc19e63 100644 --- a/toolchain/semantics/semantics_node_stack.cpp +++ b/toolchain/semantics/semantics_node_stack.cpp @@ -130,16 +130,17 @@ auto SemanticsNodeStack::PopForParseNodeAndNodeId(ParseNodeKind pop_parse_kind) return {back.parse_node, back.node_id}; } -auto SemanticsNodeStack::PopForParseNodeAndNameId() +auto SemanticsNodeStack::PopForParseNodeAndNameId(ParseNodeKind pop_parse_kind) -> std::pair { - auto back = PopEntry(ParseNodeKind::PatternBinding); + auto back = PopEntry(pop_parse_kind); RequireValidId(back); return {back.parse_node, back.name_id}; } -auto SemanticsNodeStack::PeekForNameId() -> SemanticsStringId { +auto SemanticsNodeStack::PeekForNameId(ParseNodeKind parse_kind) + -> SemanticsStringId { auto back = stack_.back(); - RequireParseKind(back, ParseNodeKind::PatternBinding); + RequireParseKind(back, parse_kind); RequireValidId(back); return back.name_id; } diff --git a/toolchain/semantics/semantics_node_stack.h b/toolchain/semantics/semantics_node_stack.h index 5f9ff0a7f93c..1b22eeaf131d 100644 --- a/toolchain/semantics/semantics_node_stack.h +++ b/toolchain/semantics/semantics_node_stack.h @@ -45,10 +45,8 @@ class SemanticsNodeStack { PushEntry({.parse_node = parse_node, .node_id = node_id}, DebugLog::NodeId); } - // Pushes a PatternBinding parse tree node onto the stack with its name. + // Pushes a parse tree node onto the stack with its name. auto Push(ParseTree::Node parse_node, SemanticsStringId name_id) -> void { - CARBON_CHECK(parse_tree_->node_kind(parse_node) == - ParseNodeKind::PatternBinding); PushEntry({.parse_node = parse_node, .name_id = name_id}, DebugLog::NameId); } @@ -85,16 +83,14 @@ class SemanticsNodeStack { auto PopForNodeId() -> SemanticsNodeId; // Pops the top of the stack and returns the parse_node and name_id. - // Verifies that the parse_node is a PatternBinding. - auto PopForParseNodeAndNameId() + auto PopForParseNodeAndNameId(ParseNodeKind pop_parse_kind) -> std::pair; // Peeks at the parse_node of the top of the stack. auto PeekParseNode() -> ParseTree::Node { return stack_.back().parse_node; } // Peeks at the name_id of the top of the stack. - // Verifies that the parse_node is a PatternBinding. - auto PeekForNameId() -> SemanticsStringId; + auto PeekForNameId(ParseNodeKind parse_kind) -> SemanticsStringId; // Prints the stack for a stack dump. auto PrintForStackDump(llvm::raw_ostream& output) const -> void; @@ -115,8 +111,6 @@ class SemanticsNodeStack { // is used based on the ParseNodeKind. union { SemanticsNodeId node_id; - - // Right now name_id is exclusively for PatternBinding, which is enforced. SemanticsStringId name_id; }; }; diff --git a/toolchain/semantics/semantics_parse_tree_handler.cpp b/toolchain/semantics/semantics_parse_tree_handler.cpp index 26e0d90c51bf..1d94d1348b24 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.cpp +++ b/toolchain/semantics/semantics_parse_tree_handler.cpp @@ -232,68 +232,123 @@ auto SemanticsParseTreeHandler::TryTypeConversionOnArgs( return true; } +auto SemanticsParseTreeHandler::ImplicitAs(ParseTree::Node parse_node, + SemanticsNodeId value_id, + SemanticsNodeId as_type_id) + -> SemanticsNodeId { + // Start by making sure both sides are valid. If any part is invalid, the + // result is invalid and we shouldn't error. + if (value_id == SemanticsNodeId::BuiltinInvalidType || + as_type_id == SemanticsNodeId::BuiltinInvalidType) { + return SemanticsNodeId::BuiltinInvalidType; + } + auto value_type_id = semantics_->GetType(value_id); + if (value_type_id == SemanticsNodeId::BuiltinInvalidType) { + return SemanticsNodeId::BuiltinInvalidType; + } + + // If the type doesn't need to change, we can return the value directly. + if (value_type_id == as_type_id) { + return value_id; + } + + // When converting to a Type, there are some automatic conversions that can be + // done. + if (as_type_id == SemanticsNodeId::BuiltinTypeType) { + if (value_id == SemanticsNodeId::BuiltinEmptyTuple) { + return SemanticsNodeId::BuiltinEmptyTupleType; + } + if (value_id == SemanticsNodeId::BuiltinEmptyStruct) { + return SemanticsNodeId::BuiltinEmptyStructType; + } + } + + auto value_type = semantics_->GetNode(value_type_id); + auto as_type = semantics_->GetNode(as_type_id); + if (CanImplicitAsStruct(value_type, as_type)) { + return value_id; + } + + CARBON_DIAGNOSTIC(ImplicitAsConversionFailure, Error, + "Cannot implicitly convert from {0} to {1}.", std::string, + std::string); + emitter_ + ->Build(parse_node, ImplicitAsConversionFailure, + semantics_->StringifyNode(value_type_id), + semantics_->StringifyNode(as_type_id)) + .Emit(); + return SemanticsNodeId::BuiltinInvalidType; +} + +auto SemanticsParseTreeHandler::CanImplicitAsStruct(SemanticsNode value_type, + SemanticsNode as_type) + -> bool { + if (value_type.kind() != SemanticsNodeKind::StructType || + as_type.kind() != SemanticsNodeKind::StructType) { + return false; + } + auto value_type_refs = + semantics_->GetNodeBlock(value_type.GetAsStructType().second); + auto as_type_refs = + semantics_->GetNodeBlock(as_type.GetAsStructType().second); + if (value_type_refs.size() != as_type_refs.size()) { + return false; + } + + for (int i = 0; i < static_cast(value_type_refs.size()); ++i) { + auto value_type_field = semantics_->GetNode(value_type_refs[i]); + auto as_type_field = semantics_->GetNode(as_type_refs[i]); + if (value_type_field.type_id() != as_type_field.type_id() || + value_type_field.GetAsStructTypeField() != + as_type_field.GetAsStructTypeField()) { + return false; + } + } + return true; +} + auto SemanticsParseTreeHandler::ParamOrArgStart() -> void { params_or_args_stack_.Push(); node_block_stack_.Push(); } -auto SemanticsParseTreeHandler::ParamOrArgComma(ParseTree::Node parse_node) - -> bool { - node_stack_.Push(parse_node); - - // Copy the last node added to the IR block into the params block. - if (!ParamOrArgSave()) { - emitter_->Emit( - parse_node, SemanticsTodo, - "Should have a param before comma, will need error recovery"); - return false; - } - - return true; +auto SemanticsParseTreeHandler::ParamOrArgComma(bool for_args) -> void { + ParamOrArgSave(for_args); } -auto SemanticsParseTreeHandler::ParamOrArgEnd( - ParseNodeKind start_kind, ParseNodeKind comma_kind, - std::function on_start) - -> bool { - // If there's a node in the IR block that has yet to be added to the params - // block, add it now. - ParamOrArgSave(); - - while (true) { - auto parse_kind = parse_tree_->node_kind(node_stack_.PeekParseNode()); - if (parse_kind == start_kind) { - return on_start(node_block_stack_.Pop(), params_or_args_stack_.Pop()); - } else if (parse_kind == comma_kind) { - node_stack_.PopAndDiscardSoloParseNode(comma_kind); - } else { - node_stack_.PopAndIgnore(); - } +auto SemanticsParseTreeHandler::ParamOrArgEnd(bool for_args, + ParseNodeKind start_kind) + -> std::pair { + if (parse_tree_->node_kind(node_stack_.PeekParseNode()) != start_kind) { + ParamOrArgSave(for_args); } + return {node_block_stack_.Pop(), params_or_args_stack_.Pop()}; } -auto SemanticsParseTreeHandler::ParamOrArgSave() -> bool { - // Copy the last node added to the IR block into the params block. - auto ir_id = node_block_stack_.Peek(); - if (!ir_id.is_valid()) { - return false; +auto SemanticsParseTreeHandler::ParamOrArgSave(bool for_args) -> void { + SemanticsNodeId param_or_arg_id = SemanticsNodeId::Invalid; + if (for_args) { + // For an argument, we add a stub reference to the expression on the top of + // the stack. There may not be anything on the IR prior to this. + auto [entry_parse_node, entry_node_id] = + node_stack_.PopForParseNodeAndNodeId(); + param_or_arg_id = AddNode(SemanticsNode::StubReference::Make( + entry_parse_node, semantics_->GetNode(entry_node_id).type_id(), + entry_node_id)); + } else { + // For a parameter, there should always be something in the IR. + node_stack_.PopAndIgnore(); + auto ir_id = node_block_stack_.Peek(); + CARBON_CHECK(ir_id.is_valid()); + auto& ir = semantics_->GetNodeBlock(ir_id); + CARBON_CHECK(!ir.empty()) << "Should have had a param"; + param_or_arg_id = ir.back(); } - // We get params before ir because it may add a node block, which can - // invalidate the ir reference. - auto& params = semantics_->GetNodeBlock(params_or_args_stack_.PeekForAdd()); - - auto& ir = semantics_->GetNodeBlock(ir_id); - CARBON_CHECK(!ir.empty()) - << "Should only have a valid ID if a node was added"; - auto& param = ir.back(); - - if (!params.empty() && param == params.back()) { - // The param was already added after a comma. - return false; - } - params.push_back(ir.back()); - return true; + // Save the param or arg ID. + auto& params_or_args = + semantics_->GetNodeBlock(params_or_args_stack_.PeekForAdd()); + params_or_args.push_back(param_or_arg_id); } auto SemanticsParseTreeHandler::HandleAddress(ParseTree::Node parse_node) @@ -316,45 +371,44 @@ auto SemanticsParseTreeHandler::HandleBreakStatementStart( auto SemanticsParseTreeHandler::HandleCallExpression(ParseTree::Node parse_node) -> bool { - auto on_start = [&](SemanticsNodeBlockId ir_id, - SemanticsNodeBlockId refs_id) -> bool { - // TODO: Convert to call expression. - auto [call_expr_parse_node, name_id] = node_stack_.PopForParseNodeAndNodeId( - ParseNodeKind::CallExpressionStart); - auto name_node = semantics_->GetNode(name_id); - if (name_node.kind() != SemanticsNodeKind::FunctionDeclaration) { - // TODO: Work on error. - emitter_->Emit(parse_node, SemanticsTodo, "Not a callable name"); - node_stack_.Push(parse_node, name_id); - return true; - } + auto [ir_id, refs_id] = + ParamOrArgEnd(/*for_args=*/true, ParseNodeKind::CallExpressionStart); - auto [_, callable_id] = name_node.GetAsFunctionDeclaration(); - auto callable = semantics_->GetCallable(callable_id); - - if (!TryTypeConversionOnArgs(call_expr_parse_node, ir_id, refs_id, - name_node.parse_node(), - callable.param_refs_id)) { - node_stack_.Push(parse_node, SemanticsNodeId::BuiltinInvalidType); - return true; - } - - auto call_id = semantics_->AddCall({ir_id, refs_id}); - // TODO: Propagate return types from callable. - auto call_node_id = AddNode(SemanticsNode::Call::Make( - call_expr_parse_node, SemanticsNodeId::BuiltinEmptyTuple, call_id, - callable_id)); - - node_stack_.Push(parse_node, call_node_id); + // TODO: Convert to call expression. + auto [call_expr_parse_node, name_id] = + node_stack_.PopForParseNodeAndNodeId(ParseNodeKind::CallExpressionStart); + auto name_node = semantics_->GetNode(name_id); + if (name_node.kind() != SemanticsNodeKind::FunctionDeclaration) { + // TODO: Work on error. + emitter_->Emit(parse_node, SemanticsTodo, "Not a callable name"); + node_stack_.Push(parse_node, name_id); return true; - }; - return ParamOrArgEnd(ParseNodeKind::CallExpressionStart, - ParseNodeKind::CallExpressionComma, on_start); + } + + auto [_, callable_id] = name_node.GetAsFunctionDeclaration(); + auto callable = semantics_->GetCallable(callable_id); + + if (!TryTypeConversionOnArgs(call_expr_parse_node, ir_id, refs_id, + name_node.parse_node(), + callable.param_refs_id)) { + node_stack_.Push(parse_node, SemanticsNodeId::BuiltinInvalidType); + return true; + } + + auto call_id = semantics_->AddCall({ir_id, refs_id}); + // TODO: Propagate return types from callable. + auto call_node_id = AddNode(SemanticsNode::Call::Make( + call_expr_parse_node, SemanticsNodeId::BuiltinEmptyTuple, call_id, + callable_id)); + + node_stack_.Push(parse_node, call_node_id); + return true; } auto SemanticsParseTreeHandler::HandleCallExpressionComma( - ParseTree::Node parse_node) -> bool { - return ParamOrArgComma(parse_node); + ParseTree::Node /*parse_node*/) -> bool { + ParamOrArgComma(/*for_args=*/true); + return true; } auto SemanticsParseTreeHandler::HandleCallExpressionStart( @@ -434,8 +488,11 @@ auto SemanticsParseTreeHandler::HandleDeducedParameterListStart( auto SemanticsParseTreeHandler::HandleDesignatedName(ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleDesignatedName"); - return false; + auto name_str = parse_tree_->GetNodeText(parse_node); + auto name_id = semantics_->AddString(name_str); + // The parent is responsible for binding the name. + node_stack_.Push(parse_node, name_id); + return true; } auto SemanticsParseTreeHandler::HandleDesignatorExpression( @@ -782,21 +839,20 @@ auto SemanticsParseTreeHandler::HandlePackageLibrary(ParseTree::Node parse_node) auto SemanticsParseTreeHandler::HandleParameterList(ParseTree::Node parse_node) -> bool { - auto on_start = [&](SemanticsNodeBlockId ir_id, - SemanticsNodeBlockId refs_id) -> bool { - PopScope(); - node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ParameterListStart); - finished_params_stack_.push_back({ir_id, refs_id}); - node_stack_.Push(parse_node); - return true; - }; - return ParamOrArgEnd(ParseNodeKind::ParameterListStart, - ParseNodeKind::ParameterListComma, on_start); + auto [ir_id, refs_id] = + ParamOrArgEnd(/*for_args=*/false, ParseNodeKind::ParameterListStart); + + PopScope(); + node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ParameterListStart); + finished_params_stack_.push_back({ir_id, refs_id}); + node_stack_.Push(parse_node); + return true; } auto SemanticsParseTreeHandler::HandleParameterListComma( - ParseTree::Node parse_node) -> bool { - return ParamOrArgComma(parse_node); + ParseTree::Node /*parse_node*/) -> bool { + ParamOrArgComma(/*for_args=*/false); + return true; } auto SemanticsParseTreeHandler::HandleParameterListStart( @@ -822,16 +878,19 @@ auto SemanticsParseTreeHandler::HandleParenExpressionOrTupleLiteralStart( auto SemanticsParseTreeHandler::HandlePatternBinding(ParseTree::Node parse_node) -> bool { - auto type = node_stack_.PopForNodeId(); + auto [type_node, parsed_type] = node_stack_.PopForParseNodeAndNodeId(); + auto cast_type_id = + ImplicitAs(type_node, parsed_type, SemanticsNodeId::BuiltinTypeType); // Get the name. auto name_node = node_stack_.PopForSoloParseNode(); // Allocate storage, linked to the name for error locations. - auto storage_id = AddNode(SemanticsNode::VarStorage::Make(name_node, type)); + auto storage_id = + AddNode(SemanticsNode::VarStorage::Make(name_node, cast_type_id)); // Bind the name to storage. - auto name_id = BindName(name_node, type, storage_id); + auto name_id = BindName(name_node, cast_type_id, storage_id); // If this node's result is used, it'll be for either the name or the storage // address. The storage address can be found through the name, so we push the @@ -939,22 +998,35 @@ auto SemanticsParseTreeHandler::HandleSelfValueIdentifier( return false; } -auto SemanticsParseTreeHandler::HandleStructComma(ParseTree::Node parse_node) - -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructComma"); - return false; +auto SemanticsParseTreeHandler::HandleStructComma( + ParseTree::Node /*parse_node*/) -> bool { + ParamOrArgComma( + /*for_args=*/parse_tree_->node_kind(node_stack_.PeekParseNode()) != + ParseNodeKind::StructFieldType); + return true; } auto SemanticsParseTreeHandler::HandleStructFieldDesignator( - ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructFieldDesignator"); - return false; + ParseTree::Node /*parse_node*/) -> bool { + // This leaves the designated name on top because the `.` isn't interesting. + CARBON_CHECK(parse_tree_->node_kind(node_stack_.PeekParseNode()) == + ParseNodeKind::DesignatedName); + return true; } auto SemanticsParseTreeHandler::HandleStructFieldType( ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructFieldType"); - return false; + auto [type_node, type_id] = node_stack_.PopForParseNodeAndNodeId(); + auto cast_type_id = + ImplicitAs(type_node, type_id, SemanticsNodeId::BuiltinTypeType); + + auto [name_node, name_id] = + node_stack_.PopForParseNodeAndNameId(ParseNodeKind::DesignatedName); + + AddNode( + SemanticsNode::StructTypeField::Make(name_node, cast_type_id, name_id)); + node_stack_.Push(parse_node); + return true; } auto SemanticsParseTreeHandler::HandleStructFieldUnknown( @@ -965,27 +1037,81 @@ auto SemanticsParseTreeHandler::HandleStructFieldUnknown( auto SemanticsParseTreeHandler::HandleStructFieldValue( ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructFieldValue"); - return false; + auto [value_parse_node, value_node_id] = + node_stack_.PopForParseNodeAndNodeId(); + auto [_, name_id] = + node_stack_.PopForParseNodeAndNameId(ParseNodeKind::DesignatedName); + + // Store the name for the type. + auto type_block_id = args_type_info_stack_.PeekForAdd(); + semantics_->AddNode( + type_block_id, + SemanticsNode::StructTypeField::Make( + parse_node, semantics_->GetNode(value_node_id).type_id(), name_id)); + + // Push the value back on the stack as an argument. + node_stack_.Push(parse_node, value_node_id); + return true; } auto SemanticsParseTreeHandler::HandleStructLiteral(ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructLiteral"); - return false; + auto [ir_id, refs_id] = ParamOrArgEnd( + /*for_args=*/true, ParseNodeKind::StructLiteralOrStructTypeLiteralStart); + + PopScope(); + node_stack_.PopAndDiscardSoloParseNode( + ParseNodeKind::StructLiteralOrStructTypeLiteralStart); + auto type_block_id = args_type_info_stack_.Pop(); + + // Special-case `{}`. + if (refs_id == SemanticsNodeBlockId::Empty) { + node_stack_.Push(parse_node, SemanticsNodeId::BuiltinEmptyStruct); + return true; + } + + // Construct a type for the literal. Each field is one node, so ir_id and + // refs_id match. + auto refs = semantics_->GetNodeBlock(refs_id); + auto type_id = AddNode(SemanticsNode::StructType::Make( + parse_node, type_block_id, type_block_id)); + + auto value_id = AddNode( + SemanticsNode::StructValue::Make(parse_node, type_id, ir_id, refs_id)); + node_stack_.Push(parse_node, value_id); + return true; } auto SemanticsParseTreeHandler::HandleStructLiteralOrStructTypeLiteralStart( ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, - "HandleStructLiteralOrStructTypeLiteralStart"); - return false; + PushScope(); + node_stack_.Push(parse_node); + // At this point we aren't sure whether this will be a value or type literal, + // so we push onto args irrespective. It just won't be used for a type + // literal. + args_type_info_stack_.Push(); + ParamOrArgStart(); + return true; } auto SemanticsParseTreeHandler::HandleStructTypeLiteral( ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleStructTypeLiteral"); - return false; + auto [ir_id, refs_id] = ParamOrArgEnd( + /*for_args=*/false, ParseNodeKind::StructLiteralOrStructTypeLiteralStart); + + PopScope(); + node_stack_.PopAndDiscardSoloParseNode( + ParseNodeKind::StructLiteralOrStructTypeLiteralStart); + // This is only used for value literals. + args_type_info_stack_.Pop(); + + CARBON_CHECK(refs_id != SemanticsNodeBlockId::Empty) + << "{} is handled by StructLiteral."; + + auto type_id = + AddNode(SemanticsNode::StructType::Make(parse_node, ir_id, refs_id)); + node_stack_.Push(parse_node, type_id); + return true; } auto SemanticsParseTreeHandler::HandleTemplate(ParseTree::Node parse_node) @@ -1015,16 +1141,17 @@ auto SemanticsParseTreeHandler::HandleVariableDeclaration( auto storage_id = node_stack_.PopForNodeId(ParseNodeKind::VariableInitializer); - auto binding = node_stack_.PopForParseNodeAndNameId(); + auto binding = + node_stack_.PopForParseNodeAndNameId(ParseNodeKind::PatternBinding); // Restore the name now that the initializer is complete. ReaddNameToLookup(binding.second, storage_id); - auto storage_type = - TryTypeConversion(parse_node, storage_id, last_child.second, - /*can_convert_lhs=*/false); - AddNode(SemanticsNode::Assign::Make(parse_node, storage_type, storage_id, - last_child.second)); + auto cast_value_id = ImplicitAs(parse_node, last_child.second, + semantics_->GetType(storage_id)); + AddNode(SemanticsNode::Assign::Make(parse_node, + semantics_->GetType(cast_value_id), + storage_id, cast_value_id)); } node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::VariableIntroducer); @@ -1046,7 +1173,8 @@ auto SemanticsParseTreeHandler::HandleVariableInitializer( // restored by `VariableDeclaration`. // Save the storage ID. - auto it = name_lookup_.find(node_stack_.PeekForNameId()); + auto it = name_lookup_.find( + node_stack_.PeekForNameId(ParseNodeKind::PatternBinding)); CARBON_CHECK(it != name_lookup_.end()); CARBON_CHECK(!it->second.empty()); auto storage_id = it->second.back(); diff --git a/toolchain/semantics/semantics_parse_tree_handler.h b/toolchain/semantics/semantics_parse_tree_handler.h index 20b0ed73488b..02f89fdbfe3a 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.h +++ b/toolchain/semantics/semantics_parse_tree_handler.h @@ -33,6 +33,8 @@ class SemanticsParseTreeHandler { node_block_stack_("node_block_stack_", semantics.node_blocks_, vlog_stream), params_or_args_stack_("params_or_args_stack_", semantics.node_blocks_, + vlog_stream), + args_type_info_stack_("args_type_info_stack_", semantics.node_blocks_, vlog_stream) {} // Outputs the ParseTree information into SemanticsIR. @@ -127,16 +129,37 @@ class SemanticsParseTreeHandler { ParseTree::Node param_parse_node, SemanticsNodeBlockId param_refs_id) -> bool; - auto ParamOrArgStart() -> void; - auto ParamOrArgComma(ParseTree::Node parse_node) -> bool; - auto ParamOrArgEnd( - ParseNodeKind start_kind, ParseNodeKind comma_kind, - std::function on_start) + // Runs ImplicitAs behavior to convert `value` to `as_type`, returning the + // result type. The result will be the node to use to replace `value`. The + // result will be BuiltinInvalidType for errors; this handles printing + // diagnostics. + auto ImplicitAs(ParseTree::Node parse_node, SemanticsNodeId value, + SemanticsNodeId as_type) -> SemanticsNodeId; + + // Returns true if the ImplicitAs can use struct conversion. + // TODO: This currently only supports struct types that precisely match. + auto CanImplicitAsStruct(SemanticsNode value_type, SemanticsNode as_type) -> bool; + // Starts handling parameters or arguments. + auto ParamOrArgStart() -> void; + + // On a comma, pushes the entry. On return, the top of node_stack_ will be + // start_kind. + auto ParamOrArgComma(bool for_args) -> void; + + // Detects whether there's an entry to push. On return, the top of + // node_stack_ will be start_kind, and the caller should do type-specific + // processing. Returns a pair of {ir_id, refs_id}. + auto ParamOrArgEnd(bool for_args, ParseNodeKind start_kind) + -> std::pair; + // Saves a parameter from the top block in node_stack_ to the top block in - // params_or_args_stack_. Returns false if nothing is copied. - auto ParamOrArgSave() -> bool; + // params_or_args_stack_. If for_args, adds a StubReference of the previous + // node's result to the IR. + // + // This should only be called by other ParamOrArg functions, not directly. + auto ParamOrArgSave(bool for_args) -> void; // Parse node handlers. Returns false for unrecoverable errors. #define CARBON_PARSE_NODE_KIND(Name) \ @@ -172,6 +195,12 @@ class SemanticsParseTreeHandler { // node in blocks here. SemanticsNodeBlockStack params_or_args_stack_; + // The stack of node blocks being used for type information while processing + // arguments. This is used in parallel with params_or_args_stack_. It's + // currently only used for struct literals, where we need to track names + // for a type separate from the literal arguments. + SemanticsNodeBlockStack args_type_info_stack_; + // Completed parameters that are held temporarily on a side-channel for a // function. This can't use node_stack_ because it has space for only one // value, whereas parameters return two values. diff --git a/toolchain/semantics/testdata/basics/builtin_nodes.carbon b/toolchain/semantics/testdata/basics/builtin_nodes.carbon index 2ba79471f120..b55ff2042351 100644 --- a/toolchain/semantics/testdata/basics/builtin_nodes.carbon +++ b/toolchain/semantics/testdata/basics/builtin_nodes.carbon @@ -22,6 +22,8 @@ // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: nodeTypeType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: nodeTypeType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: nodeTypeType}, +// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyStructType, type: nodeTypeType}, +// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyStruct, type: nodeEmptyStructType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyTupleType, type: nodeTypeType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyTuple, type: nodeEmptyTupleType}, // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/empty_struct.carbon b/toolchain/semantics/testdata/function/call/empty_struct.carbon new file mode 100644 index 000000000000..482a7629c151 --- /dev/null +++ b/toolchain/semantics/testdata/function/call/empty_struct.carbon @@ -0,0 +1,66 @@ +// 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 +// RUN: %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: {arg_ir: block4, arg_refs: block5}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: {param_ir: block1, param_refs: block2}, +// CHECK:STDOUT: {param_ir: block0, param_refs: block0}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: Echo, +// CHECK:STDOUT: Main, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str1, arg1: callable0}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1}, +// CHECK:STDOUT: {kind: StubReference, arg0: nodeEmptyStruct, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Echo(a: {}) { +} + +fn Main() { + Echo({}); +} diff --git a/toolchain/semantics/testdata/function/call/fail_param_count.carbon b/toolchain/semantics/testdata/function/call/fail_param_count.carbon index 8e9ad2a55d0d..59113d92e23a 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_count.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_count.carbon @@ -46,11 +46,17 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+10, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str5, arg1: callable3}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+15, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+17, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+19, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int4, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+21, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int5, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+23, type: nodeIntegerType}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+12, arg1: block0}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -64,7 +70,7 @@ // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, // CHECK:STDOUT: node+12, -// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+25, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+2, @@ -85,32 +91,38 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+13, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+14, -// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+16, // CHECK:STDOUT: node+17, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+16, -// CHECK:STDOUT: node+17, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+18, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+16, // CHECK:STDOUT: node+18, // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+23, +// CHECK:STDOUT: node+24, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+24, +// CHECK:STDOUT: ], // CHECK:STDOUT: ] fn Run0() {} diff --git a/toolchain/semantics/testdata/function/call/fail_param_type.carbon b/toolchain/semantics/testdata/function/call/fail_param_type.carbon index 119243483251..1e172265cd4e 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_type.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_type.carbon @@ -28,6 +28,7 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: nodeFloatingPointType}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block0}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -44,13 +45,14 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/more_param_ir.carbon b/toolchain/semantics/testdata/function/call/more_param_ir.carbon index 08cb2b1209b8..db24fee8b340 100644 --- a/toolchain/semantics/testdata/function/call/more_param_ir.carbon +++ b/toolchain/semantics/testdata/function/call/more_param_ir.carbon @@ -44,10 +44,13 @@ // CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+9, arg1: node+10, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: nodeIntegerType}, // CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+11, arg1: node+12, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int4, type: nodeIntegerType}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+14, arg1: node+15, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+15, arg1: node+16, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+17, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int5, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+19, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+8, arg1: block6}, // CHECK:STDOUT: ] @@ -71,7 +74,7 @@ // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, -// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+22, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+9, @@ -83,14 +86,17 @@ // CHECK:STDOUT: node+15, // CHECK:STDOUT: node+16, // CHECK:STDOUT: node+17, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+13, -// CHECK:STDOUT: node+16, -// CHECK:STDOUT: node+17, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+21, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_one.carbon b/toolchain/semantics/testdata/function/call/params_one.carbon index eebc96cfe3d9..51369a24c5d7 100644 --- a/toolchain/semantics/testdata/function/call/params_one.carbon +++ b/toolchain/semantics/testdata/function/call/params_one.carbon @@ -29,6 +29,7 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, // CHECK:STDOUT: ] @@ -46,17 +47,18 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+6, // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], // CHECK:STDOUT: ] fn Foo(a: i32) {} diff --git a/toolchain/semantics/testdata/function/call/params_one_comma.carbon b/toolchain/semantics/testdata/function/call/params_one_comma.carbon index 89a0c3aaa07c..b2fad16c30a9 100644 --- a/toolchain/semantics/testdata/function/call/params_one_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_one_comma.carbon @@ -31,8 +31,10 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call1, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, // CHECK:STDOUT: ] @@ -50,23 +52,25 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, -// CHECK:STDOUT: node+9, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_two.carbon b/toolchain/semantics/testdata/function/call/params_two.carbon index f9f004dd56a8..cb9c1ae34499 100644 --- a/toolchain/semantics/testdata/function/call/params_two.carbon +++ b/toolchain/semantics/testdata/function/call/params_two.carbon @@ -33,7 +33,9 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str3, arg1: callable1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block6}, // CHECK:STDOUT: ] @@ -54,18 +56,20 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: node+8, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_two_comma.carbon b/toolchain/semantics/testdata/function/call/params_two_comma.carbon index 85ef89fb6df8..c5c2dc0251ee 100644 --- a/toolchain/semantics/testdata/function/call/params_two_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_two_comma.carbon @@ -36,10 +36,14 @@ // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str3, arg1: callable1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: nodeIntegerType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+14, type: nodeIntegerType}, // CHECK:STDOUT: {kind: Call, arg0: call1, arg1: callable0, type: nodeEmptyTuple}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block6}, // CHECK:STDOUT: ] @@ -60,27 +64,31 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, -// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+17, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: node+8, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+10, -// CHECK:STDOUT: node+11, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+10, -// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/struct/empty.carbon b/toolchain/semantics/testdata/struct/empty.carbon new file mode 100644 index 000000000000..765efd01ae91 --- /dev/null +++ b/toolchain/semantics/testdata/struct/empty.carbon @@ -0,0 +1,42 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// RUN: %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// 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: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+0, arg1: nodeEmptyStruct, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: VarStorage, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+3, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+0, type: nodeEmptyStructType}, +// 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: ] + +var x: {} = {}; +var y: {} = x; diff --git a/toolchain/semantics/testdata/struct/fail_assign_empty.carbon b/toolchain/semantics/testdata/struct/fail_assign_empty.carbon new file mode 100644 index 000000000000..9191d55bc32d --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_assign_empty.carbon @@ -0,0 +1,45 @@ +// 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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: node+1}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_assign_empty.carbon:[[@LINE+1]]:22: Cannot implicitly convert from {} as Type to {.a: i32}. +var x: {.a: i32} = {}; diff --git a/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon b/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon new file mode 100644 index 000000000000..a2c8c5687e42 --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon @@ -0,0 +1,54 @@ +// 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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// 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: a, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: nodeEmptyStructType}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+2, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block3, arg1: block3, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block2, arg1: block4, type: node+5}, +// CHECK:STDOUT: {kind: Assign, arg0: node+0, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon:[[@LINE+1]]:21: Cannot implicitly convert from {.a: i32} to {} as Type. +var x: {} = {.a = 1}; diff --git a/toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon b/toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon new file mode 100644 index 000000000000..070080b5cf16 --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_field_name_mismatch.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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: b, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: node+1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str2, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+7}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon:[[@LINE+1]]:28: Cannot implicitly convert from {.b: i32} to {.a: i32}. +var x: {.a: i32} = {.b = 1}; diff --git a/toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon b/toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon new file mode 100644 index 000000000000..c326bd11233d --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_field_type_mismatch.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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: {mantissa: 10, exponent: -1, is_decimal: 1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: b, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: node+1}, +// CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str2, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+7}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon:[[@LINE+1]]:30: Cannot implicitly convert from {.b: f64} to {.a: i32}. +var x: {.a: i32} = {.b = 1.0}; diff --git a/toolchain/semantics/testdata/struct/fail_too_few_values.carbon b/toolchain/semantics/testdata/struct/fail_too_few_values.carbon new file mode 100644 index 000000000000..28443ed8482e --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_too_few_values.carbon @@ -0,0 +1,67 @@ +// 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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: b, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+2}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+3, type: node+2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+8}, +// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_too_few_values.carbon:[[@LINE+1]]:37: Cannot implicitly convert from {.a: i32} to {.a: i32, .b: i32}. +var x: {.a: i32, .b: i32} = {.a = 1}; diff --git a/toolchain/semantics/testdata/struct/fail_type_assign.carbon b/toolchain/semantics/testdata/struct/fail_type_assign.carbon new file mode 100644 index 000000000000..944f4d79233a --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_type_assign.carbon @@ -0,0 +1,54 @@ +// 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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: node+1}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block4, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_type_assign.carbon:[[@LINE+1]]:29: Cannot implicitly convert from Type to {.a: i32}. +var x: {.a: i32} = {.a: i32}; diff --git a/toolchain/semantics/testdata/struct/fail_value_as_type.carbon b/toolchain/semantics/testdata/struct/fail_value_as_type.carbon new file mode 100644 index 000000000000..361e19a55bff --- /dev/null +++ b/toolchain/semantics/testdata/struct/fail_value_as_type.carbon @@ -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 +// +// AUTOUPDATE +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block2, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block1, arg1: block3, type: node+3}, +// CHECK:STDOUT: {kind: VarStorage, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+5, type: nodeInvalidType}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/struct/fail_value_as_type.carbon:[[@LINE+1]]:15: Cannot implicitly convert from {.a: i32} to Type. +var x: {.a = 1}; diff --git a/toolchain/semantics/testdata/struct/one_entry.carbon b/toolchain/semantics/testdata/struct/one_entry.carbon new file mode 100644 index 000000000000..e48f76eccb47 --- /dev/null +++ b/toolchain/semantics/testdata/struct/one_entry.carbon @@ -0,0 +1,79 @@ +// 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 +// RUN: %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 4, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: x, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: node+1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+7}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+8, type: node+7}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block7, arg1: block8, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+11}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+12, type: node+11}, +// CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: node+2, type: node+1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// 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: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +var x: {.a: i32} = {.a = 4}; +var y: {.a: i32} = x; diff --git a/toolchain/semantics/testdata/struct/two_entries.carbon b/toolchain/semantics/testdata/struct/two_entries.carbon new file mode 100644 index 000000000000..20e4fdb0df09 --- /dev/null +++ b/toolchain/semantics/testdata/struct/two_entries.carbon @@ -0,0 +1,94 @@ +// 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 +// RUN: %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// 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: a, +// CHECK:STDOUT: b, +// CHECK:STDOUT: x, +// CHECK:STDOUT: y, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block1, arg1: block2, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+2}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+3, type: node+2}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+11}, +// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: node+12, type: node+11}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block7, arg1: block8, type: nodeTypeType}, +// CHECK:STDOUT: {kind: VarStorage, type: node+16}, +// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+17, type: node+16}, +// CHECK:STDOUT: {kind: Assign, arg0: node+17, arg1: node+3, type: node+2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, +// 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/var/fail_init_type_mismatch.carbon b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon index 2e31f5a1d640..4103e902c164 100644 --- a/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon +++ b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon @@ -24,7 +24,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: nodeIntegerType}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: nodeIntegerType}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, -// CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: node+3, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: nodeInvalidType, type: nodeInvalidType}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block2}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -43,6 +43,6 @@ // CHECK:STDOUT: ] fn Main() { - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon:[[@LINE+1]]:19: Type mismatch: lhs is i32, rhs is f64 + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon:[[@LINE+1]]:19: Cannot implicitly convert from f64 to i32. var x: i32 = 1.0; } diff --git a/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon b/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon new file mode 100644 index 000000000000..79086593e645 --- /dev/null +++ b/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon @@ -0,0 +1,51 @@ +// 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 +// RUN: %{not} %{carbon-run-semantics} +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: calls: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: {param_ir: block0, param_refs: block0}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: Main, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: VarStorage, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block2}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Main() { + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon:[[@LINE+1]]:10: Cannot implicitly convert from i32 to Type. + var x: 1 = 1; +}