diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index d225bfed2791..6f296874fcbc 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -91,7 +91,6 @@ CARBON_DIAGNOSTIC_KIND(ParametersRequiredByDeduced) CARBON_DIAGNOSTIC_KIND(SemanticsTodo) -CARBON_DIAGNOSTIC_KIND(TypeMismatch) CARBON_DIAGNOSTIC_KIND(NameNotFound) CARBON_DIAGNOSTIC_KIND(NameRedefined) CARBON_DIAGNOSTIC_KIND(PreviousDefinition) @@ -101,7 +100,6 @@ CARBON_DIAGNOSTIC_KIND(CallArgTypeMismatch) CARBON_DIAGNOSTIC_KIND(ReturnStatementDisallowExpression) CARBON_DIAGNOSTIC_KIND(ReturnStatementImplicitNote) CARBON_DIAGNOSTIC_KIND(ReturnStatementMissingExpression) -CARBON_DIAGNOSTIC_KIND(ReturnStatementTypeMismatch) CARBON_DIAGNOSTIC_KIND(ImplicitAsConversionFailure) CARBON_DIAGNOSTIC_KIND(DesignatorExpressionUnsupported) CARBON_DIAGNOSTIC_KIND(DesignatorExpressionNameNotFound) diff --git a/toolchain/semantics/semantics_ir.h b/toolchain/semantics/semantics_ir.h index 780053a34b2b..74c34a922a48 100644 --- a/toolchain/semantics/semantics_ir.h +++ b/toolchain/semantics/semantics_ir.h @@ -166,11 +166,6 @@ class SemanticsIR { return node_id; } - // Returns the type of the requested node. - auto GetType(SemanticsNodeId node_id) -> SemanticsNodeId { - return GetNode(node_id).type_id(); - } - // Adds an empty new node block, returning an ID to reference it and add // items. auto AddNodeBlock() -> SemanticsNodeBlockId { diff --git a/toolchain/semantics/semantics_parse_tree_handler.cpp b/toolchain/semantics/semantics_parse_tree_handler.cpp index 7071616a2949..90c8b026f03d 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.cpp +++ b/toolchain/semantics/semantics_parse_tree_handler.cpp @@ -139,48 +139,10 @@ auto SemanticsParseTreeHandler::PopScope() -> void { } } -auto SemanticsParseTreeHandler::CanTypeConvert(SemanticsNodeId from_type, - SemanticsNodeId to_type) - -> SemanticsNodeId { - // TODO: This should attempt implicit conversions, but there's not enough - // implemented to do that right now. - if (from_type == SemanticsNodeId::BuiltinInvalidType || - to_type == SemanticsNodeId::BuiltinInvalidType) { - return SemanticsNodeId::BuiltinInvalidType; - } - if (from_type == to_type) { - return from_type; - } - return SemanticsNodeId::Invalid; -} - -auto SemanticsParseTreeHandler::TryTypeConversion(ParseTree::Node parse_node, - SemanticsNodeId lhs_id, - SemanticsNodeId rhs_id, - bool /*can_convert_lhs*/) - -> SemanticsNodeId { - auto lhs_type = semantics_->GetType(lhs_id); - auto rhs_type = semantics_->GetType(rhs_id); - // TODO: CanTypeConvert can be assumed to handle rhs conversions, and we'll - // either want to call it twice or refactor it to be aware of lhs conversions. - auto type = CanTypeConvert(rhs_type, lhs_type); - if (type.is_valid()) { - return type; - } - CARBON_DIAGNOSTIC(TypeMismatch, Error, - "Type mismatch: lhs is {0}, rhs is {1}", std::string, - std::string); - emitter_->Emit(parse_node, TypeMismatch, semantics_->StringifyNode(lhs_type), - semantics_->StringifyNode(rhs_type)); - return SemanticsNodeId::BuiltinInvalidType; -} - -auto SemanticsParseTreeHandler::TryTypeConversionOnArgs( - ParseTree::Node arg_parse_node, SemanticsNodeBlockId /*arg_ir_id*/, - SemanticsNodeBlockId arg_refs_id, ParseTree::Node param_parse_node, - SemanticsNodeBlockId param_refs_id) -> bool { - CARBON_DIAGNOSTIC(NoMatchingCall, Error, "No matching callable was found."); - +auto SemanticsParseTreeHandler::ImplicitAsForArgs( + SemanticsNodeBlockId /*arg_ir_id*/, SemanticsNodeBlockId arg_refs_id, + ParseTree::Node param_parse_node, SemanticsNodeBlockId param_refs_id, + DiagnosticEmitter::DiagnosticBuilder* diagnostic) -> bool { // If both arguments and parameters are empty, return quickly. Otherwise, // we'll fetch both so that errors are consistent. if (arg_refs_id == SemanticsNodeBlockId::Empty && @@ -193,13 +155,13 @@ auto SemanticsParseTreeHandler::TryTypeConversionOnArgs( // If sizes mismatch, fail early. if (arg_refs.size() != param_refs.size()) { + CARBON_CHECK(diagnostic != nullptr) << "Should have validated first"; CARBON_DIAGNOSTIC(CallArgCountMismatch, Note, - "Received {0} argument(s), but require {1} argument(s).", + "Callable cannot be used: Received {0} argument(s), but " + "require {1} argument(s).", int, int); - emitter_->Build(arg_parse_node, NoMatchingCall) - .Note(param_parse_node, CallArgCountMismatch, arg_refs.size(), - param_refs.size()) - .Emit(); + diagnostic->Note(param_parse_node, CallArgCountMismatch, arg_refs.size(), + param_refs.size()); return false; } @@ -207,22 +169,20 @@ auto SemanticsParseTreeHandler::TryTypeConversionOnArgs( // TODO: arg_ir_id is passed so that implicit conversions can be inserted. // It's currently not supported, but will be needed. for (size_t i = 0; i < arg_refs.size(); ++i) { - const auto& arg_ref = arg_refs[i]; - auto arg_ref_type = semantics_->GetType(arg_ref); - const auto& param_ref = param_refs[i]; - auto param_ref_type = semantics_->GetType(param_ref); - - auto result_type = CanTypeConvert(arg_ref_type, param_ref_type); - if (!result_type.is_valid()) { - CARBON_DIAGNOSTIC( - CallArgTypeMismatch, Note, - "Type mismatch: cannot convert argument {0} from {1} to {2}.", size_t, - std::string, std::string); - emitter_->Build(arg_parse_node, NoMatchingCall) - .Note(param_parse_node, CallArgTypeMismatch, i, - semantics_->StringifyNode(arg_ref_type), - semantics_->StringifyNode(param_ref_type)) - .Emit(); + auto value_id = arg_refs[i]; + auto as_type_id = semantics_->GetNode(param_refs[i]).type_id(); + if (ImplicitAsImpl(value_id, as_type_id, + diagnostic == nullptr ? &value_id : nullptr) == + ImplicitAsKind::Incompatible) { + CARBON_CHECK(diagnostic != nullptr) << "Should have validated first"; + CARBON_DIAGNOSTIC(CallArgTypeMismatch, Note, + "Callable cannot be used: Cannot implicityly convert " + "argument {0} from `{1}` to `{2}`.", + size_t, std::string, std::string); + diagnostic->Note( + param_parse_node, CallArgTypeMismatch, i, + semantics_->StringifyNode(semantics_->GetNode(value_id).type_id()), + semantics_->StringifyNode(as_type_id)); return false; } } @@ -230,52 +190,86 @@ auto SemanticsParseTreeHandler::TryTypeConversionOnArgs( return true; } -auto SemanticsParseTreeHandler::ImplicitAs(ParseTree::Node parse_node, - SemanticsNodeId value_id, - SemanticsNodeId as_type_id) +auto SemanticsParseTreeHandler::ImplicitAsRequired(ParseTree::Node parse_node, + SemanticsNodeId value_id, + SemanticsNodeId as_type_id) -> SemanticsNodeId { + SemanticsNodeId output_value_id = value_id; + if (ImplicitAsImpl(value_id, as_type_id, &output_value_id) == + ImplicitAsKind::Incompatible) { + // Only error when the system is trying to use the result. + CARBON_DIAGNOSTIC(ImplicitAsConversionFailure, Error, + "Cannot implicitly convert from `{0}` to `{1}`.", + std::string, std::string); + emitter_ + ->Build( + parse_node, ImplicitAsConversionFailure, + semantics_->StringifyNode(semantics_->GetNode(value_id).type_id()), + semantics_->StringifyNode(as_type_id)) + .Emit(); + } + return output_value_id; +} + +auto SemanticsParseTreeHandler::ImplicitAsImpl(SemanticsNodeId value_id, + SemanticsNodeId as_type_id, + SemanticsNodeId* output_value_id) + -> ImplicitAsKind { // 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; + if (value_id == SemanticsNodeId::BuiltinInvalidType) { + // If the value is invalid, we can't do much, but do "succeed". + return ImplicitAsKind::Identical; } - auto value_type_id = semantics_->GetType(value_id); + auto value_type_id = semantics_->GetNode(value_id).type_id(); if (value_type_id == SemanticsNodeId::BuiltinInvalidType) { - return SemanticsNodeId::BuiltinInvalidType; + return ImplicitAsKind::Identical; + } + if (as_type_id == SemanticsNodeId::BuiltinInvalidType) { + // Although the target type is invalid, this still changes the value. + if (output_value_id != nullptr) { + *output_value_id = SemanticsNodeId::BuiltinInvalidType; + } + return ImplicitAsKind::Compatible; } - // If the type doesn't need to change, we can return the value directly. if (value_type_id == as_type_id) { - return value_id; + // Type doesn't need to change. + return ImplicitAsKind::Identical; } // 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 (output_value_id != nullptr) { + *output_value_id = SemanticsNodeId::BuiltinEmptyTupleType; + } + return ImplicitAsKind::Compatible; } if (value_id == SemanticsNodeId::BuiltinEmptyStruct) { - return SemanticsNodeId::BuiltinEmptyStructType; + if (output_value_id != nullptr) { + *output_value_id = SemanticsNodeId::BuiltinEmptyStructType; + } + return ImplicitAsKind::Compatible; } } 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; + // Under the current implementation, struct types are only allowed to + // ImplicitAs when they're equivalent. What's really missing is type + // consolidation such that this would fall under the above `value_type_id == + // as_type_id` case. In the future, this will need to handle actual + // conversions. + return ImplicitAsKind::Identical; } - 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; + if (output_value_id != nullptr) { + *output_value_id = SemanticsNodeId::BuiltinInvalidType; + } + return ImplicitAsKind::Incompatible; } auto SemanticsParseTreeHandler::CanImplicitAsStruct(SemanticsNode value_type, @@ -386,18 +380,23 @@ auto SemanticsParseTreeHandler::HandleCallExpression(ParseTree::Node parse_node) 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)) { + CARBON_DIAGNOSTIC(NoMatchingCall, Error, "No matching callable was found."); + auto diagnostic = emitter_->Build(call_expr_parse_node, NoMatchingCall); + if (!ImplicitAsForArgs(ir_id, refs_id, name_node.parse_node(), + callable.param_refs_id, &diagnostic)) { + diagnostic.Emit(); node_stack_.Push(parse_node, SemanticsNodeId::BuiltinInvalidType); return true; } + CARBON_CHECK(ImplicitAsForArgs(ir_id, refs_id, name_node.parse_node(), + callable.param_refs_id, + /*diagnostic=*/nullptr)); + 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)); + call_expr_parse_node, callable.return_type_id, call_id, callable_id)); node_stack_.Push(parse_node, call_node_id); return true; @@ -685,15 +684,20 @@ auto SemanticsParseTreeHandler::HandleInfixOperator(ParseTree::Node parse_node) -> bool { auto rhs_id = node_stack_.PopForNodeId(); auto lhs_id = node_stack_.PopForNodeId(); - SemanticsNodeId result_type = - TryTypeConversion(parse_node, lhs_id, rhs_id, /*can_convert_lhs=*/true); + + // TODO: This should search for a compatible interface. For now, it's a very + // trivial check of validity on the operation. + lhs_id = ImplicitAsRequired(parse_node, lhs_id, + semantics_->GetNode(rhs_id).type_id()); // Figure out the operator for the token. auto token = parse_tree_->node_token(parse_node); switch (auto token_kind = tokens_->GetKind(token)) { case TokenKind::Plus: - AddNodeAndPush(parse_node, SemanticsNode::BinaryOperatorAdd::Make( - parse_node, result_type, lhs_id, rhs_id)); + AddNodeAndPush(parse_node, + SemanticsNode::BinaryOperatorAdd::Make( + parse_node, semantics_->GetNode(lhs_id).type_id(), + lhs_id, rhs_id)); break; default: emitter_->Emit(parse_node, SemanticsTodo, @@ -915,9 +919,9 @@ auto SemanticsParseTreeHandler::HandleParenExpressionOrTupleLiteralStart( auto SemanticsParseTreeHandler::HandlePatternBinding(ParseTree::Node parse_node) -> bool { - auto [type_node, parsed_type] = node_stack_.PopForParseNodeAndNodeId(); - auto cast_type_id = - ImplicitAs(type_node, parsed_type, SemanticsNodeId::BuiltinTypeType); + auto [type_node, parsed_type_id] = node_stack_.PopForParseNodeAndNodeId(); + SemanticsNodeId cast_type_id = ImplicitAsRequired( + type_node, parsed_type_id, SemanticsNodeId::BuiltinTypeType); // Get the name. auto name_node = node_stack_.PopForSoloParseNode(); @@ -929,9 +933,9 @@ auto SemanticsParseTreeHandler::HandlePatternBinding(ParseTree::Node parse_node) // Bind the name to storage. 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 - // name. + // 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 name. node_stack_.Push(parse_node, name_id); return true; @@ -972,8 +976,7 @@ auto SemanticsParseTreeHandler::HandleReturnStatement( AddNodeAndPush(parse_node, SemanticsNode::Return::Make(parse_node)); } else { - const auto arg = node_stack_.PopForNodeId(); - auto arg_type = semantics_->GetType(arg); + auto arg = node_stack_.PopForNodeId(); node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ReturnStatementStart); if (!callable.return_type_id.is_valid()) { @@ -986,23 +989,12 @@ auto SemanticsParseTreeHandler::HandleReturnStatement( .Note(fn_node.parse_node(), ReturnStatementImplicitNote) .Emit(); } else { - const auto new_type = CanTypeConvert(arg_type, callable.return_type_id); - if (!new_type.is_valid()) { - // TODO: Add a note pointing at the return type's parse node. - CARBON_DIAGNOSTIC(ReturnStatementTypeMismatch, Error, - "Cannot convert {0} to {1}.", std::string, - std::string); - emitter_ - ->Build(parse_node, ReturnStatementTypeMismatch, - semantics_->StringifyNode(arg_type), - semantics_->StringifyNode(callable.return_type_id)) - .Emit(); - } - arg_type = new_type; + arg = ImplicitAsRequired(parse_node, arg, callable.return_type_id); } - AddNodeAndPush(parse_node, SemanticsNode::ReturnExpression::Make( - parse_node, arg_type, arg)); + AddNodeAndPush(parse_node, + SemanticsNode::ReturnExpression::Make( + parse_node, semantics_->GetNode(arg).type_id(), arg)); } return true; } @@ -1017,7 +1009,10 @@ auto SemanticsParseTreeHandler::HandleReturnStatementStart( auto SemanticsParseTreeHandler::HandleReturnType(ParseTree::Node parse_node) -> bool { // Propagate the type expression. - node_stack_.Push(parse_node, node_stack_.PopForNodeId()); + auto [type_parse_node, type_node_id] = node_stack_.PopForParseNodeAndNodeId(); + auto cast_node_id = ImplicitAsRequired(type_parse_node, type_node_id, + SemanticsNodeId::BuiltinTypeType); + node_stack_.Push(parse_node, cast_node_id); return true; } @@ -1052,8 +1047,8 @@ auto SemanticsParseTreeHandler::HandleStructFieldDesignator( auto SemanticsParseTreeHandler::HandleStructFieldType( ParseTree::Node parse_node) -> bool { auto [type_node, type_id] = node_stack_.PopForParseNodeAndNodeId(); - auto cast_type_id = - ImplicitAs(type_node, type_id, SemanticsNodeId::BuiltinTypeType); + SemanticsNodeId cast_type_id = + ImplicitAsRequired(type_node, type_id, SemanticsNodeId::BuiltinTypeType); auto [name_node, name_id] = node_stack_.PopForParseNodeAndNameId(ParseNodeKind::DesignatedName); @@ -1169,9 +1164,9 @@ auto SemanticsParseTreeHandler::HandleTupleLiteralComma( auto SemanticsParseTreeHandler::HandleVariableDeclaration( ParseTree::Node parse_node) -> bool { - auto last_child = node_stack_.PopForParseNodeAndNodeId(); + auto [last_parse_node, last_node_id] = node_stack_.PopForParseNodeAndNodeId(); - if (parse_tree_->node_kind(last_child.first) != + if (parse_tree_->node_kind(last_parse_node) != ParseNodeKind::PatternBinding) { auto storage_id = node_stack_.PopForNodeId(ParseNodeKind::VariableInitializer); @@ -1182,11 +1177,11 @@ auto SemanticsParseTreeHandler::HandleVariableDeclaration( // Restore the name now that the initializer is complete. ReaddNameToLookup(binding.second, storage_id); - 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)); + auto cast_value_id = ImplicitAsRequired( + parse_node, last_node_id, semantics_->GetNode(storage_id).type_id()); + AddNode(SemanticsNode::Assign::Make( + parse_node, semantics_->GetNode(cast_value_id).type_id(), storage_id, + cast_value_id)); } node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::VariableIntroducer); diff --git a/toolchain/semantics/semantics_parse_tree_handler.h b/toolchain/semantics/semantics_parse_tree_handler.h index 02f89fdbfe3a..15f5e070f686 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.h +++ b/toolchain/semantics/semantics_parse_tree_handler.h @@ -46,6 +46,16 @@ class SemanticsParseTreeHandler { // Prints the node_block_stack_ on stack dumps. class PrettyStackTraceNodeBlockStack; + // For CanImplicitAs, the detected conversion to apply. + enum ImplicitAsKind { + // Incompatible types. + Incompatible, + // No conversion required. + Identical, + // ImplicitAs is required. + Compatible, + }; + // Provides DenseMapInfo for SemanticsStringId. struct SemanticsStringIdMapInfo { static inline auto getEmptyKey() -> SemanticsStringId { @@ -102,39 +112,35 @@ class SemanticsParseTreeHandler { // Pops the top scope from scope_stack_, cleaning up names from name_lookup_. auto PopScope() -> void; - // Attempts a type conversion between two types. Returns: - // - The result type if valid. - // - BuiltinInvalidType if either lhs_id or rhs_id is BuiltinInvalidType. - // - Invalid if no conversion is supported. + // Runs ImplicitAsImpl for a set of arguments and parameters. // - // The caller might choose to print a diagnostic if Invalid is returned, - // whereas BuiltinInvalidType means there was a previous error that may be - // related and another diagnostic is undesirable. - auto CanTypeConvert(SemanticsNodeId from_type, SemanticsNodeId to_type) - -> SemanticsNodeId; + // This will eventually need to support checking against multiple possible + // overloads, multiple of which may be possible but not "best". While this can + // currently be done by calling twice, toggling `apply_implicit_as`, in the + // future we may want to remember the right implicit conversions to do for + // valid cases in order to efficiently handle generics. + auto ImplicitAsForArgs( + SemanticsNodeBlockId arg_ir_id, SemanticsNodeBlockId arg_refs_id, + ParseTree::Node param_parse_node, SemanticsNodeBlockId param_refs_id, + DiagnosticEmitter::DiagnosticBuilder* diagnostic) + -> bool; - // Attempts a type conversion between two arguments, returning the result - // type. The result type will be BuiltinInvalidType for errors; this handles - // printing diagnostics. - auto TryTypeConversion(ParseTree::Node parse_node, SemanticsNodeId lhs_id, - SemanticsNodeId rhs_id, bool can_convert_lhs) - -> SemanticsNodeId; - - // Attempts a type conversion between arguments and parameters. Returns true - // on success. arg_parse_node and param_parse_node are only used for - // diagnostic locations. - auto TryTypeConversionOnArgs(ParseTree::Node arg_parse_node, - SemanticsNodeBlockId arg_ir_id, - SemanticsNodeBlockId arg_refs_id, - ParseTree::Node param_parse_node, - SemanticsNodeBlockId param_refs_id) -> bool; + // Runs ImplicitAsImpl for a situation where a cast is required, returning the + // updated `value_id`. Prints a diagnostic and returns an InvalidType if + // unsupported. + auto ImplicitAsRequired(ParseTree::Node parse_node, SemanticsNodeId value_id, + SemanticsNodeId as_type_id) -> SemanticsNodeId; // 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; + // result type. The result will be the node to use to replace `value`. + // + // If `output_value_id` is null, then this only checks if the conversion is + // possible. + // + // If `output_value_id` is not null, then it will be set if there is a need to + // cast. + auto ImplicitAsImpl(SemanticsNodeId value_id, SemanticsNodeId as_type_id, + SemanticsNodeId* output_value_id) -> ImplicitAsKind; // Returns true if the ImplicitAs can use struct conversion. // TODO: This currently only supports struct types that precisely match. diff --git a/toolchain/semantics/testdata/function/call/empty_struct.carbon b/toolchain/semantics/testdata/function/call/empty_struct.carbon index 482a7629c151..089c292a4f01 100644 --- a/toolchain/semantics/testdata/function/call/empty_struct.carbon +++ b/toolchain/semantics/testdata/function/call/empty_struct.carbon @@ -28,7 +28,7 @@ // 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: Call, arg0: call0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/fail_param_count.carbon b/toolchain/semantics/testdata/function/call/fail_param_count.carbon index 59113d92e23a..a3ed8bcbb963 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_count.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_count.carbon @@ -131,23 +131,23 @@ fn Run2(a: i32, b: i32) {} fn Main() { // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-6]]:1: Received 1 argument(s), but require 0 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-6]]:1: Callable cannot be used: Received 1 argument(s), but require 0 argument(s). Run0(1); // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-9]]:1: Received 2 argument(s), but require 0 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-9]]:1: Callable cannot be used: Received 2 argument(s), but require 0 argument(s). Run0(0, 1); // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-12]]:1: Received 0 argument(s), but require 1 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-12]]:1: Callable cannot be used: Received 0 argument(s), but require 1 argument(s). Run1(); // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-15]]:1: Received 2 argument(s), but require 1 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-15]]:1: Callable cannot be used: Received 2 argument(s), but require 1 argument(s). Run1(0, 1); // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-18]]:1: Received 0 argument(s), but require 2 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-18]]:1: Callable cannot be used: Received 0 argument(s), but require 2 argument(s). Run2(); // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-21]]:1: Received 1 argument(s), but require 2 argument(s). + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_count.carbon:[[@LINE-21]]:1: Callable cannot be used: Received 1 argument(s), but require 2 argument(s). Run2(0); } diff --git a/toolchain/semantics/testdata/function/call/fail_param_type.carbon b/toolchain/semantics/testdata/function/call/fail_param_type.carbon index 1e172265cd4e..18a5f4260bc6 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_type.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_type.carbon @@ -60,6 +60,6 @@ fn Run(a: i32) {} fn Main() { // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_type.carbon:[[@LINE+2]]:6: No matching callable was found. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_type.carbon:[[@LINE-4]]:1: Type mismatch: cannot convert argument 0 from f64 to i32. + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_param_type.carbon:[[@LINE-4]]:1: Callable cannot be used: Cannot implicityly convert argument 0 from `f64` to `i32`. Run(1.0); } diff --git a/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon b/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon new file mode 100644 index 000000000000..886576cbf677 --- /dev/null +++ b/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon @@ -0,0 +1,63 @@ +// 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: {arg_ir: block0, arg_refs: block0}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: {param_ir: block0, param_refs: block0, return_type: nodeFloatingPointType}, +// CHECK:STDOUT: {param_ir: block0, param_refs: block0}, +// 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: Foo, +// CHECK:STDOUT: Run, +// CHECK:STDOUT: x, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, +// CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+1, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block2}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str1, arg1: callable1}, +// CHECK:STDOUT: {kind: VarStorage, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+5, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeFloatingPointType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: nodeInvalidType, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block3}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Foo() -> f64 { return 1.0; } + +fn Run() { + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon:[[@LINE+1]]:21: Cannot implicitly convert from `f64` to `i32`. + var x: i32 = Foo(); +} diff --git a/toolchain/semantics/testdata/function/call/i32.carbon b/toolchain/semantics/testdata/function/call/i32.carbon new file mode 100644 index 000000000000..86e2a2cb318c --- /dev/null +++ b/toolchain/semantics/testdata/function/call/i32.carbon @@ -0,0 +1,85 @@ +// 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: block6, arg_refs: block7}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: callables: [ +// CHECK:STDOUT: {param_ir: block1, param_refs: block2, return_type: nodeIntegerType}, +// 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: a, +// CHECK:STDOUT: Echo, +// CHECK:STDOUT: Main, +// CHECK:STDOUT: b, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str1, arg1: callable0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+3, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block4}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str2, arg1: callable1}, +// CHECK:STDOUT: {kind: VarStorage, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: 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: nodeIntegerType}, +// CHECK:STDOUT: {kind: Assign, arg0: node+7, arg1: node+11, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block5}, +// 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+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Echo(a: i32) -> i32 { + // TODO: `return a;` requires the parameter to be in name lookup. + return 1; +} + +fn Main() { + var b: i32 = Echo(1); +} diff --git a/toolchain/semantics/testdata/function/call/more_param_ir.carbon b/toolchain/semantics/testdata/function/call/more_param_ir.carbon index db24fee8b340..415df0671de2 100644 --- a/toolchain/semantics/testdata/function/call/more_param_ir.carbon +++ b/toolchain/semantics/testdata/function/call/more_param_ir.carbon @@ -51,7 +51,7 @@ // 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: Call, arg0: call0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+8, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/params_one.carbon b/toolchain/semantics/testdata/function/call/params_one.carbon index 51369a24c5d7..95f58315e90b 100644 --- a/toolchain/semantics/testdata/function/call/params_one.carbon +++ b/toolchain/semantics/testdata/function/call/params_one.carbon @@ -30,7 +30,7 @@ // 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: Call, arg0: call0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/params_one_comma.carbon b/toolchain/semantics/testdata/function/call/params_one_comma.carbon index b2fad16c30a9..76cb014fa87a 100644 --- a/toolchain/semantics/testdata/function/call/params_one_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_one_comma.carbon @@ -32,10 +32,10 @@ // 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: Call, arg0: call0, arg1: callable0}, // 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: Call, arg0: call1, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+4, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/params_two.carbon b/toolchain/semantics/testdata/function/call/params_two.carbon index cb9c1ae34499..a99f0b8b1796 100644 --- a/toolchain/semantics/testdata/function/call/params_two.carbon +++ b/toolchain/semantics/testdata/function/call/params_two.carbon @@ -36,7 +36,7 @@ // 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: Call, arg0: call0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/params_two_comma.carbon b/toolchain/semantics/testdata/function/call/params_two_comma.carbon index c5c2dc0251ee..0a1447c4ba4f 100644 --- a/toolchain/semantics/testdata/function/call/params_two_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_two_comma.carbon @@ -39,12 +39,12 @@ // 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: Call, arg0: call0, arg1: callable0}, // 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: Call, arg0: call1, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+6, arg1: block6}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/function/call/params_zero.carbon b/toolchain/semantics/testdata/function/call/params_zero.carbon index b03af4333ada..aabccb5d8e62 100644 --- a/toolchain/semantics/testdata/function/call/params_zero.carbon +++ b/toolchain/semantics/testdata/function/call/params_zero.carbon @@ -24,7 +24,7 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str1, arg1: callable1}, -// CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0, type: nodeEmptyTuple}, +// CHECK:STDOUT: {kind: Call, arg0: call0, arg1: callable0}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block2}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ diff --git a/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon b/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon index 26539a2814b7..e13ffd5db76a 100644 --- a/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon +++ b/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon @@ -23,7 +23,7 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+1, arg1: node+2, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: nodeInvalidType, arg1: node+2, type: nodeInvalidType}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+3, type: nodeInvalidType}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block2}, // CHECK:STDOUT: ] @@ -43,6 +43,6 @@ // CHECK:STDOUT: ] fn Main() -> i32 { - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon:[[@LINE+1]]:13: Type mismatch: lhs is i32, rhs is f64 + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon:[[@LINE+1]]:13: Cannot implicitly convert from `i32` to `f64`. return 12 + 3.4; } diff --git a/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon b/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon index 84fb140ce7ae..314d14bbee11 100644 --- a/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon +++ b/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon @@ -24,7 +24,7 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+1, arg1: node+2, type: nodeInvalidType}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: nodeInvalidType, arg1: node+2, type: nodeInvalidType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: nodeIntegerType}, // CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+3, arg1: node+4, type: nodeInvalidType}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+5, type: nodeInvalidType}, @@ -50,6 +50,6 @@ fn Main() -> i32 { // The following line has two mismatches, but after the first, it shouldn't // keep erroring. - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon:[[@LINE+1]]:13: Type mismatch: lhs is i32, rhs is f64 + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon:[[@LINE+1]]:13: Cannot implicitly convert from `i32` to `f64`. return 12 + 3.4 + 12; } diff --git a/toolchain/semantics/testdata/return/fail_type_mismatch.carbon b/toolchain/semantics/testdata/return/fail_type_mismatch.carbon index 26891caddde1..e82ab651045e 100644 --- a/toolchain/semantics/testdata/return/fail_type_mismatch.carbon +++ b/toolchain/semantics/testdata/return/fail_type_mismatch.carbon @@ -21,7 +21,7 @@ // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: str0, arg1: callable0}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: nodeFloatingPointType}, -// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: nodeInvalidType, type: nodeInvalidType}, // CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+0, arg1: block2}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -38,6 +38,6 @@ // CHECK:STDOUT: ] fn Main() -> i32 { - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/return/fail_type_mismatch.carbon:[[@LINE+1]]:13: Cannot convert f64 to i32. + // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/return/fail_type_mismatch.carbon:[[@LINE+1]]:13: Cannot implicitly convert from `f64` to `i32`. return 1.0; } diff --git a/toolchain/semantics/testdata/return/struct.carbon b/toolchain/semantics/testdata/return/struct.carbon new file mode 100644 index 000000000000..b2e8f11d0305 --- /dev/null +++ b/toolchain/semantics/testdata/return/struct.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: %{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, return_type: node+1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 3, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: a, +// CHECK:STDOUT: Main, +// 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: FunctionDeclaration, arg0: str1, arg1: callable0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructTypeField, arg0: str0, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+3, type: nodeIntegerType}, +// CHECK:STDOUT: {kind: StructType, arg0: block5, arg1: block5, type: nodeTypeType}, +// CHECK:STDOUT: {kind: StructValue, arg0: block4, arg1: block6, type: node+6}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+7, type: node+6}, +// CHECK:STDOUT: {kind: FunctionDefinition, arg0: node+2, arg1: block7}, +// 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+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Main() -> {.a: i32} { + return {.a = 3}; +} diff --git a/toolchain/semantics/testdata/struct/fail_assign_empty.carbon b/toolchain/semantics/testdata/struct/fail_assign_empty.carbon index 9191d55bc32d..cb8405cab90d 100644 --- a/toolchain/semantics/testdata/struct/fail_assign_empty.carbon +++ b/toolchain/semantics/testdata/struct/fail_assign_empty.carbon @@ -41,5 +41,5 @@ // 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}. +// 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 index a2c8c5687e42..c40af0b19e53 100644 --- a/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon +++ b/toolchain/semantics/testdata/struct/fail_assign_to_empty.carbon @@ -50,5 +50,5 @@ // 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. +// 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 index 070080b5cf16..9cb10d8c057c 100644 --- a/toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon +++ b/toolchain/semantics/testdata/struct/fail_field_name_mismatch.carbon @@ -60,5 +60,5 @@ // 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}. +// 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 index c326bd11233d..f2b0e38168de 100644 --- a/toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon +++ b/toolchain/semantics/testdata/struct/fail_field_type_mismatch.carbon @@ -60,5 +60,5 @@ // 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}. +// 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 index 28443ed8482e..ebfffb7f5c69 100644 --- a/toolchain/semantics/testdata/struct/fail_too_few_values.carbon +++ b/toolchain/semantics/testdata/struct/fail_too_few_values.carbon @@ -63,5 +63,5 @@ // 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}. +// 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 index 944f4d79233a..8bfe0d064b6f 100644 --- a/toolchain/semantics/testdata/struct/fail_type_assign.carbon +++ b/toolchain/semantics/testdata/struct/fail_type_assign.carbon @@ -50,5 +50,5 @@ // 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}. +// 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 index 361e19a55bff..39e917ef2878 100644 --- a/toolchain/semantics/testdata/struct/fail_value_as_type.carbon +++ b/toolchain/semantics/testdata/struct/fail_value_as_type.carbon @@ -48,5 +48,5 @@ // 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. +// 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/var/fail_init_type_mismatch.carbon b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon index 4103e902c164..a076142a327b 100644 --- a/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon +++ b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon @@ -43,6 +43,6 @@ // CHECK:STDOUT: ] fn Main() { - // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon:[[@LINE+1]]:19: Cannot implicitly convert from f64 to i32. + // 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 index 79086593e645..3511c9c8c7c6 100644 --- a/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon +++ b/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon @@ -46,6 +46,6 @@ // 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. + // 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; }