From db022658c63cea82d25e3c8d7efb028648fe1f46 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 23 Jul 2024 13:32:24 -0700 Subject: [PATCH] Implement syntactic merge checks for parameters. (#4149) Note this isn't implementing checking through imports. The parse node there is harder to access through the context, so would require examining the entity in order to get the import declaration, to get at the ImportIR. We also don't have a parse tree attached in that case, and would need to add one to SemIR::File. But I believe we do want to add that, so it's explicitly a TODO. Note GetTokenText re-lexes literal values, so there's a bit of potential overhead there. Not sure if we want a more efficient manner for comparing in cases like this. --- toolchain/check/decl_name_stack.cpp | 14 +- toolchain/check/function.cpp | 6 +- toolchain/check/function.h | 5 +- toolchain/check/global_init.cpp | 2 + toolchain/check/handle_class.cpp | 4 + toolchain/check/handle_function.cpp | 7 +- toolchain/check/handle_impl.cpp | 2 + toolchain/check/handle_interface.cpp | 5 +- toolchain/check/handle_pattern_list.cpp | 8 +- toolchain/check/impl.cpp | 3 +- toolchain/check/import_ref.cpp | 6 + toolchain/check/merge.cpp | 85 +- toolchain/check/merge.h | 19 +- toolchain/check/name_component.cpp | 25 + toolchain/check/name_component.h | 6 + .../check/testdata/class/base_method.carbon | 4 +- .../class/no_prelude/syntactic_merge.carbon | 794 +++++++++++++++++ .../class/syntactic_merge_literal.carbon | 191 +++++ .../no_prelude/syntactic_merge.carbon | 754 +++++++++++++++++ .../no_prelude/syntactic_merge.carbon | 795 ++++++++++++++++++ toolchain/diagnostics/diagnostic_kind.def | 2 + toolchain/parse/tree.cpp | 7 + toolchain/parse/tree.h | 5 + toolchain/sem_ir/class.h | 5 + toolchain/sem_ir/function.h | 5 + toolchain/sem_ir/interface.h | 5 + 26 files changed, 2738 insertions(+), 26 deletions(-) create mode 100644 toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon create mode 100644 toolchain/check/testdata/class/syntactic_merge_literal.carbon create mode 100644 toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon create mode 100644 toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index b328800a6d40b..5ed6aee3ebd97 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -366,8 +366,9 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context, return InvalidResult; } - auto new_params = - DeclParams(name.name_loc_id, name.implicit_params_id, name.params_id); + auto new_params = DeclParams(name.name_loc_id, name.first_param_node_id, + name.last_param_node_id, name.implicit_params_id, + name.params_id); // Find the scope corresponding to the resolved instruction. CARBON_KIND_SWITCH(context_->insts().Get(name_context.resolved_inst_id)) { @@ -404,10 +405,11 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context, case CARBON_KIND(SemIR::Namespace resolved_inst): { auto scope_id = resolved_inst.name_scope_id; auto& scope = context_->name_scopes().Get(scope_id); - if (!CheckRedeclParamsMatch(*context_, new_params, - DeclParams(name_context.resolved_inst_id, - SemIR::InstBlockId::Invalid, - SemIR::InstBlockId::Invalid))) { + if (!CheckRedeclParamsMatch( + *context_, new_params, + DeclParams(name_context.resolved_inst_id, Parse::NodeId::Invalid, + Parse::NodeId::Invalid, SemIR::InstBlockId::Invalid, + SemIR::InstBlockId::Invalid))) { return InvalidResult; } if (scope.is_closed_import) { diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index 7aafb42b18b94..eeecf30c58e88 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -13,9 +13,11 @@ namespace Carbon::Check { auto CheckFunctionTypeMatches(Context& context, const SemIR::Function& new_function, const SemIR::Function& prev_function, - Substitutions substitutions) -> bool { + Substitutions substitutions, bool check_syntax) + -> bool { if (!CheckRedeclParamsMatch(context, DeclParams(new_function), - DeclParams(prev_function), substitutions)) { + DeclParams(prev_function), substitutions, + check_syntax)) { return false; } diff --git a/toolchain/check/function.h b/toolchain/check/function.h index f7de8352ba32d..44de24bc09281 100644 --- a/toolchain/check/function.h +++ b/toolchain/check/function.h @@ -29,12 +29,11 @@ struct SuspendedFunction { // Checks that `new_function` has the same parameter types and return type as // `prev_function`, applying the specified set of substitutions to the // previous function. Prints a suitable diagnostic and returns false if not. -// Note that this doesn't include the syntactic check that's performed for -// redeclarations. auto CheckFunctionTypeMatches(Context& context, const SemIR::Function& new_function, const SemIR::Function& prev_function, - Substitutions substitutions) -> bool; + Substitutions substitutions, bool check_syntax) + -> bool; // Checks that the return type of the specified function is complete, issuing an // error if not. This computes the return slot usage for the function if diff --git a/toolchain/check/global_init.cpp b/toolchain/check/global_init.cpp index 56995b1d06d52..0c5b4c781bfe8 100644 --- a/toolchain/check/global_init.cpp +++ b/toolchain/check/global_init.cpp @@ -39,6 +39,8 @@ auto GlobalInit::Finalize() -> void { .parent_scope_id = SemIR::NameScopeId::Package, .decl_id = SemIR::InstId::Invalid, .generic_id = SemIR::GenericId::Invalid, + .first_param_node_id = Parse::NodeId::Invalid, + .last_param_node_id = Parse::NodeId::Invalid, .implicit_param_refs_id = SemIR::InstBlockId::Invalid, .param_refs_id = SemIR::InstBlockId::Empty, .return_storage_id = SemIR::InstId::Invalid, diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index e14ecbf4818c8..a460b80e155f8 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -93,6 +93,8 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc, } if (new_is_definition) { + prev_class.first_param_node_id = new_class.first_param_node_id; + prev_class.last_param_node_id = new_class.last_param_node_id; prev_class.implicit_param_refs_id = new_class.implicit_param_refs_id; prev_class.param_refs_id = new_class.param_refs_id; prev_class.definition_id = new_class.definition_id; @@ -225,6 +227,8 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, .name_id = name_context.name_id_for_new_inst(), .parent_scope_id = name_context.parent_scope_id_for_new_inst(), .generic_id = SemIR::GenericId::Invalid, + .first_param_node_id = name.first_param_node_id, + .last_param_node_id = name.last_param_node_id, .implicit_param_refs_id = name.implicit_params_id, .param_refs_id = name.params_id, // `.self_type_id` depends on the ClassType, so is set below. diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 2d5e6a50abf13..69b035f1be175 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -99,7 +99,8 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc, SemIR::ImportIRId prev_import_ir_id) -> bool { auto& prev_function = context.functions().Get(prev_function_id); - if (!CheckFunctionTypeMatches(context, new_function, prev_function, {})) { + if (!CheckFunctionTypeMatches(context, new_function, prev_function, {}, + /*check_syntax=*/true)) { return false; } @@ -118,6 +119,8 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc, // Track the signature from the definition, so that IDs in the body // match IDs in the signature. prev_function.definition_id = new_function.definition_id; + prev_function.first_param_node_id = new_function.first_param_node_id; + prev_function.last_param_node_id = new_function.last_param_node_id; prev_function.implicit_param_refs_id = new_function.implicit_param_refs_id; prev_function.param_refs_id = new_function.param_refs_id; prev_function.return_storage_id = new_function.return_storage_id; @@ -252,6 +255,8 @@ static auto BuildFunctionDecl(Context& context, .parent_scope_id = name_context.parent_scope_id_for_new_inst(), .decl_id = decl_id, .generic_id = SemIR::GenericId::Invalid, + .first_param_node_id = name.first_param_node_id, + .last_param_node_id = name.last_param_node_id, .implicit_param_refs_id = name.implicit_params_id, .param_refs_id = name.params_id, .return_storage_id = return_storage_id, diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 1626c0f1e7e74..f501d74bef92c 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -36,6 +36,8 @@ auto HandleParseNode(Context& context, Parse::ImplIntroducerId node_id) auto HandleParseNode(Context& context, Parse::ImplForallId node_id) -> bool { auto params_id = context.node_stack().Pop(); + context.node_stack() + .PopAndDiscardSoloNodeId(); context.node_stack().Push(node_id, params_id); return true; } diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index 0bbc33ebb255f..c7e8c57f6d7e6 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -62,7 +62,8 @@ static auto BuildInterfaceDecl(Context& context, // now we just check the generic parameters match. if (CheckRedeclParamsMatch( context, - DeclParams(interface_decl_id, name.implicit_params_id, + DeclParams(interface_decl_id, name.first_param_node_id, + name.last_param_node_id, name.implicit_params_id, name.params_id), DeclParams(context.interfaces().Get( existing_interface_decl->interface_id)))) { @@ -90,6 +91,8 @@ static auto BuildInterfaceDecl(Context& context, .name_id = name_context.name_id_for_new_inst(), .parent_scope_id = name_context.parent_scope_id_for_new_inst(), .generic_id = generic_id, + .first_param_node_id = name.first_param_node_id, + .last_param_node_id = name.last_param_node_id, .implicit_param_refs_id = name.implicit_params_id, .param_refs_id = name.params_id, .decl_id = interface_decl_id}; diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index 6ee4b79c4162e..44dbb4a36840d 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -16,10 +16,10 @@ auto HandleParseNode(Context& context, Parse::ImplicitParamListStartId node_id) auto HandleParseNode(Context& context, Parse::ImplicitParamListId node_id) -> bool { + // Note the Start node remains on the stack, where the param list handler can + // make use of it. auto refs_id = context.param_and_arg_refs_stack().EndAndPop( Parse::NodeKind::ImplicitParamListStart); - context.node_stack() - .PopAndDiscardSoloNodeId(); context.node_stack().Push(node_id, refs_id); // The implicit parameter list's scope extends to the end of the following // parameter list. @@ -40,10 +40,10 @@ auto HandleParseNode(Context& context, Parse::PatternListCommaId /*node_id*/) } auto HandleParseNode(Context& context, Parse::TuplePatternId node_id) -> bool { + // Note the Start node remains on the stack, where the param list handler can + // make use of it. auto refs_id = context.param_and_arg_refs_stack().EndAndPop( Parse::NodeKind::TuplePatternStart); - context.node_stack() - .PopAndDiscardSoloNodeId(); context.node_stack().Push(node_id, refs_id); return true; } diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 9aeadc285ec95..18fd57028d738 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -54,7 +54,8 @@ static auto CheckAssociatedFunctionImplementation( // synthesize a suitable thunk. if (!CheckFunctionTypeMatches( context, context.functions().Get(impl_function_decl->function_id), - context.functions().Get(interface_function_id), substitutions)) { + context.functions().Get(interface_function_id), substitutions, + /*check_syntax=*/false)) { return SemIR::InstId::BuiltinError; } return impl_decl_id; diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 369114020197f..289ccfc1c6583 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -909,6 +909,8 @@ class ImportRefResolver { // importing the parameters. .parent_scope_id = SemIR::NameScopeId::Invalid, .generic_id = generic_id, + .first_param_node_id = Parse::NodeId::Invalid, + .last_param_node_id = Parse::NodeId::Invalid, .implicit_param_refs_id = import_class.implicit_param_refs_id.is_valid() ? SemIR::InstBlockId::Empty : SemIR::InstBlockId::Invalid, @@ -1143,6 +1145,8 @@ class ImportRefResolver { .parent_scope_id = parent_scope_id, .decl_id = function_decl_id, .generic_id = generic_id, + .first_param_node_id = Parse::NodeId::Invalid, + .last_param_node_id = Parse::NodeId::Invalid, .implicit_param_refs_id = GetLocalParamRefsId( function.implicit_param_refs_id, implicit_param_const_ids), .param_refs_id = @@ -1249,6 +1253,8 @@ class ImportRefResolver { // importing the parameters. .parent_scope_id = SemIR::NameScopeId::Invalid, .generic_id = generic_id, + .first_param_node_id = Parse::NodeId::Invalid, + .last_param_node_id = Parse::NodeId::Invalid, .implicit_param_refs_id = import_interface.implicit_param_refs_id.is_valid() ? SemIR::InstBlockId::Empty diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index de85034f8f237..e93966755da7f 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -268,9 +268,79 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc, return true; } +// Returns true if the two nodes represent the same syntax. +// TODO: Detect raw identifiers (will require token changes). +static auto IsNodeSyntaxEqual(Context& context, Parse::NodeId new_node_id, + Parse::NodeId prev_node_id) -> bool { + if (context.parse_tree().node_kind(new_node_id) != + context.parse_tree().node_kind(prev_node_id)) { + return false; + } + + // TODO: Should there be a trivial way to check if we need to check spellings? + // Identifiers and literals need their text checked for cross-file matching, + // but not intra-file. Keywords and operators shouldn't need the token text + // examined at all. + auto new_spelling = context.tokens().GetTokenText( + context.parse_tree().node_token(new_node_id)); + auto prev_spelling = context.tokens().GetTokenText( + context.parse_tree().node_token(prev_node_id)); + return new_spelling == prev_spelling; +} + +// Returns false if redeclaration parameter syntax doesn't match. +static auto CheckRedeclParamSyntax(Context& context, + Parse::NodeId new_first_param_node_id, + Parse::NodeId new_last_param_node_id, + Parse::NodeId prev_first_param_node_id, + Parse::NodeId prev_last_param_node_id) + -> bool { + // Parse nodes may not always be available to compare. + // TODO: Support cross-file syntax checks. Right now imports provide invalid + // nodes, and we'll need to follow the declaration to its original file to + // get the parse tree. + if (!new_first_param_node_id.is_valid() || + !prev_first_param_node_id.is_valid()) { + return true; + } + CARBON_CHECK(new_last_param_node_id.is_valid()) + << "new_last_param_node_id.is_valid should match " + "new_first_param_node_id.is_valid"; + CARBON_CHECK(prev_last_param_node_id.is_valid()) + << "prev_last_param_node_id.is_valid should match " + "prev_first_param_node_id.is_valid"; + + auto new_range = context.parse_tree().postorder(new_first_param_node_id, + new_last_param_node_id); + auto prev_range = context.parse_tree().postorder(prev_first_param_node_id, + prev_last_param_node_id); + + // zip is using the shortest range. If they differ in length, there should be + // some difference inside the range because the range includes parameter + // brackets. As a consequence, we don't explicitly handle different range + // sizes here. + for (auto [new_node_id, prev_node_id] : llvm::zip(new_range, prev_range)) { + if (!IsNodeSyntaxEqual(context, new_node_id, prev_node_id)) { + CARBON_DIAGNOSTIC(RedeclParamSyntaxDiffers, Error, + "Redeclaration syntax differs here."); + CARBON_DIAGNOSTIC(RedeclParamSyntaxPrevious, Note, + "Comparing with previous declaration here."); + context.emitter() + .Build(new_node_id, RedeclParamSyntaxDiffers) + .Note(prev_node_id, RedeclParamSyntaxPrevious) + .Emit(); + + return false; + } + } + + return true; +} + auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, const DeclParams& prev_entity, - Substitutions substitutions) -> bool { + Substitutions substitutions, bool check_syntax) + -> bool { if (EntityHasParamError(context, new_entity) || EntityHasParamError(context, prev_entity)) { return false; @@ -278,12 +348,21 @@ auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, if (!CheckRedeclParams(context, new_entity.loc, new_entity.implicit_param_refs_id, prev_entity.loc, prev_entity.implicit_param_refs_id, "implicit ", - substitutions) || - !CheckRedeclParams(context, new_entity.loc, new_entity.param_refs_id, + substitutions)) { + return false; + } + if (!CheckRedeclParams(context, new_entity.loc, new_entity.param_refs_id, prev_entity.loc, prev_entity.param_refs_id, "", substitutions)) { return false; } + if (check_syntax && + !CheckRedeclParamSyntax(context, new_entity.first_param_node_id, + new_entity.last_param_node_id, + prev_entity.first_param_node_id, + prev_entity.last_param_node_id)) { + return false; + } return true; } diff --git a/toolchain/check/merge.h b/toolchain/check/merge.h index d7a96b9a94d84..121af502edc7e 100644 --- a/toolchain/check/merge.h +++ b/toolchain/check/merge.h @@ -47,17 +47,30 @@ struct DeclParams { template explicit DeclParams(const Entity& entity) : loc(entity.decl_id), + first_param_node_id(entity.first_param_node_id), + last_param_node_id(entity.last_param_node_id), implicit_param_refs_id(entity.implicit_param_refs_id), param_refs_id(entity.param_refs_id) {} - DeclParams(SemIRLoc loc, SemIR::InstBlockId implicit_params_id, + DeclParams(SemIRLoc loc, Parse::NodeId first_param_node_id, + Parse::NodeId last_param_node_id, + SemIR::InstBlockId implicit_params_id, SemIR::InstBlockId params_id) : loc(loc), + first_param_node_id(first_param_node_id), + last_param_node_id(last_param_node_id), implicit_param_refs_id(implicit_params_id), param_refs_id(params_id) {} // The location of the declaration of the entity. SemIRLoc loc; + + // Parse tree bounds for the parameters, including both implicit and explicit + // parameters. These will be compared to match between declaration and + // definition. + Parse::NodeId first_param_node_id; + Parse::NodeId last_param_node_id; + // The implicit parameters of the entity. Can be Invalid if there is no // implicit parameter list. SemIR::InstBlockId implicit_param_refs_id; @@ -71,8 +84,8 @@ struct DeclParams { // returns false. auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, const DeclParams& prev_entity, - Substitutions substitutions = Substitutions()) - -> bool; + Substitutions substitutions = Substitutions(), + bool check_syntax = true) -> bool; } // namespace Carbon::Check diff --git a/toolchain/check/name_component.cpp b/toolchain/check/name_component.cpp index b5c785132af89..7c92754303cd5 100644 --- a/toolchain/check/name_component.cpp +++ b/toolchain/check/name_component.cpp @@ -9,15 +9,40 @@ namespace Carbon::Check { auto PopNameComponent(Context& context) -> NameComponent { + Parse::NodeId first_param_node_id = Parse::InvalidNodeId(); + Parse::NodeId last_param_node_id = Parse::InvalidNodeId(); + + // Explicit params. auto [params_loc_id, params_id] = context.node_stack().PopWithNodeIdIf(); + if (params_id) { + first_param_node_id = + context.node_stack() + .PopForSoloNodeId(); + last_param_node_id = params_loc_id; + } + + // Implicit params. auto [implicit_params_loc_id, implicit_params_id] = context.node_stack() .PopWithNodeIdIf(); + if (implicit_params_id) { + // Implicit params always come before explicit params. + first_param_node_id = + context.node_stack() + .PopForSoloNodeId(); + // Only use the end of implicit params if there weren't explicit params. + if (last_param_node_id.is_valid()) { + last_param_node_id = params_loc_id; + } + } + auto [name_loc_id, name_id] = context.node_stack().PopNameWithNodeId(); return { .name_loc_id = name_loc_id, .name_id = name_id, + .first_param_node_id = first_param_node_id, + .last_param_node_id = last_param_node_id, .implicit_params_loc_id = implicit_params_loc_id, .implicit_params_id = implicit_params_id.value_or(SemIR::InstBlockId::Invalid), diff --git a/toolchain/check/name_component.h b/toolchain/check/name_component.h index 4adecac7ce82c..e058e52eacf0d 100644 --- a/toolchain/check/name_component.h +++ b/toolchain/check/name_component.h @@ -20,6 +20,12 @@ struct NameComponent { Parse::NodeId name_loc_id; SemIR::NameId name_id; + // Parse tree bounds for the parameters, including both implicit and explicit + // parameters. These will be compared to match between declaration and + // definition. + Parse::NodeId first_param_node_id; + Parse::NodeId last_param_node_id; + // The implicit parameter list. Parse::NodeId implicit_params_loc_id; SemIR::InstBlockId implicit_params_id; diff --git a/toolchain/check/testdata/class/base_method.carbon b/toolchain/check/testdata/class/base_method.carbon index 81b297de859a1..edb7a0c87c9ef 100644 --- a/toolchain/check/testdata/class/base_method.carbon +++ b/toolchain/check/testdata/class/base_method.carbon @@ -14,7 +14,7 @@ base class Base { fn F[addr self: Self*](); } -fn Base.F[addr self: Base*]() { +fn Base.F[addr self: Self*]() { (*self).a = 1; } @@ -73,7 +73,7 @@ fn Call(p: Derived*) { // CHECK:STDOUT: } // CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {} // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %Base.ref: type = name_ref Base, %Base.decl [template = constants.%Base] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%Base [template = constants.%Base] // CHECK:STDOUT: %.loc17_26: type = ptr_type %Base [template = constants.%.3] // CHECK:STDOUT: %self.loc17_16.1: %.3 = param self // CHECK:STDOUT: @F.%self: %.3 = bind_name self, %self.loc17_16.1 diff --git a/toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon b/toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon new file mode 100644 index 0000000000000..5c1c4135c9c37 --- /dev/null +++ b/toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon @@ -0,0 +1,794 @@ +// 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 +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon + +// --- basic.carbon + +library "basic"; + +class C {} +alias D = C; + +class Foo(a: C); +class Foo(a: C) {} + +class Bar(a: D); +class Bar(a: D) {} + +// --- spacing.carbon + +library "spacing"; + +class C {} + +class Foo [ ] ( a : C ); +class Foo[](a: C) {} + +// --- fail_parens.carbon + +library "parens"; + +class C {} + +class Foo(a: C); +// CHECK:STDERR: fail_parens.carbon:[[@LINE+7]]:14: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class Foo(a: (C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_parens.carbon:[[@LINE-4]]:14: Comparing with previous declaration here. +// CHECK:STDERR: class Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +class Foo(a: (C)) {} + +// --- todo_fail_raw_identifier.carbon + +library "raw_identifier"; + +class C {} + +class Foo(a: C); +class Foo(a: r#C) {} + +// --- two_file.carbon + +library "two_file"; + +class C {} +alias D = C; + +class Foo(a: C); +class Bar(a: D); + +// --- two_file.impl.carbon + +impl library "two_file"; + +class Foo(a: C) {} +class Bar(a: D) {} + +// --- fail_name_mismatch.carbon + +library "name_mismatch"; + +class C {} +alias D = C; + +class Foo(a: C); +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE+7]]:11: ERROR: Redeclaration differs at parameter 1. +// CHECK:STDERR: class Foo(b: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE-4]]:11: Previous declaration's corresponding parameter here. +// CHECK:STDERR: class Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +class Foo(b: D) {} + +// --- fail_alias.carbon + +library "alias"; + +class C {} +alias D = C; + +class Foo(a: C); +// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:14: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class Foo(a: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_alias.carbon:[[@LINE-4]]:14: Comparing with previous declaration here. +// CHECK:STDERR: class Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +class Foo(a: D) {} + +// --- fail_deduced_alias.carbon + +library "deduced_alias"; + +class C {} +alias D = C; + +class Foo[a: C](); +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:14: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class Foo[a: D]() {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:14: Comparing with previous declaration here. +// CHECK:STDERR: class Foo[a: C](); +// CHECK:STDERR: ^ +// CHECK:STDERR: +class Foo[a: D]() {} + +// --- alias_two_file.carbon + +library "alias_two_file"; + +class C {} + +class Foo(a: C); + +// --- todo_fail_alias_two_file.impl.carbon + +impl library "alias_two_file"; + +alias D = C; + +class Foo(a: D) {} + +// --- fail_repeat_const.carbon + +library "repeat_const"; + +class C {} + +class Foo(a: const C); +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+11]]:14: WARNING: `const` applied repeatedly to the same type has no additional effect. +// CHECK:STDERR: class Foo(a: const (const C)) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+7]]:20: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class Foo(a: const (const C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE-8]]:20: Comparing with previous declaration here. +// CHECK:STDERR: class Foo(a: const C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +class Foo(a: const (const C)) {} + +// --- fail_self_type.carbon + +library "self_type"; + +base class Base { + var a: (); + + fn F[addr self: Self*](); +} + +// CHECK:STDERR: fail_self_type.carbon:[[@LINE+6]]:22: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: fn Base.F[addr self: Base*]() { +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: fail_self_type.carbon:[[@LINE-6]]:19: Comparing with previous declaration here. +// CHECK:STDERR: fn F[addr self: Self*](); +// CHECK:STDERR: ^~~~ +fn Base.F[addr self: Base*]() { + (*self).a = (); +} + +// CHECK:STDOUT: --- basic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %Bar.type: type = generic_class_type @Bar [template] +// CHECK:STDOUT: %Bar.1: %Bar.type = struct_value () [template] +// CHECK:STDOUT: %Bar.2: type = class_type @Bar [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl.loc7 +// CHECK:STDOUT: .Bar = %Bar.decl.loc10 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc8: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc8_11.1: %C = param a +// CHECK:STDOUT: %a.loc8_11.2: %C = bind_name a, %a.loc8_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc10: %Bar.type = class_decl @Bar [template = constants.%Bar.1] { +// CHECK:STDOUT: %D.ref.loc10: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc10_11.1: %C = param a +// CHECK:STDOUT: %a.loc10_11.2: %C = bind_name a, %a.loc10_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc11: %Bar.type = class_decl @Bar [template = constants.%Bar.1] { +// CHECK:STDOUT: %D.ref.loc11: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc11_11.1: %C = param a +// CHECK:STDOUT: %a.loc11_11.2: %C = bind_name a, %a.loc11_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Foo.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- spacing.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_17.1: %C = param a +// CHECK:STDOUT: %a.loc6_17.2: %C = bind_name a, %a.loc6_17.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_13.1: %C = param a +// CHECK:STDOUT: %a.loc7_13.2: %C = bind_name a, %a.loc7_13.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Foo.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_parens.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_11.1: %C = param a +// CHECK:STDOUT: %a.loc6_11.2: %C = bind_name a, %a.loc6_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %C.ref.loc14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_11.1: %C = param a +// CHECK:STDOUT: %a.loc14_11.2: %C = bind_name a, %a.loc14_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_11.1: %C = param a +// CHECK:STDOUT: %a.loc6_11.2: %C = bind_name a, %a.loc6_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Foo.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %Bar.type: type = generic_class_type @Bar [template] +// CHECK:STDOUT: %Bar.1: %Bar.type = struct_value () [template] +// CHECK:STDOUT: %Bar.2: type = class_type @Bar [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = class_decl @Bar [template = constants.%Bar.1] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc8_11.1: %C = param a +// CHECK:STDOUT: %a.loc8_11.2: %C = bind_name a, %a.loc8_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar; +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %Bar.type: type = generic_class_type @Bar [template] +// CHECK:STDOUT: %Bar.1: %Bar.type = struct_value () [template] +// CHECK:STDOUT: %Bar.2: type = class_type @Bar [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//two_file, inst+5, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3: %Foo.type = import_ref Main//two_file, inst+9, loaded [template = constants.%Foo.1] +// CHECK:STDOUT: %import_ref.4: %Bar.type = import_ref Main//two_file, inst+17, loaded [template = constants.%Bar.1] +// CHECK:STDOUT: %import_ref.5 = import_ref Main//two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .D = imports.%import_ref.2 +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %a.loc4_11.1: %C = param a +// CHECK:STDOUT: %a.loc4_11.2: %C = bind_name a, %a.loc4_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = class_decl @Bar [template = constants.%Bar.1] { +// CHECK:STDOUT: %D.ref: type = name_ref D, imports.%import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %a.loc5_11.1: %C = param a +// CHECK:STDOUT: %a.loc5_11.2: %C = bind_name a, %a.loc5_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Foo.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Bar { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Bar.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_name_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %b.loc15_11.1: %C = param b +// CHECK:STDOUT: %b.loc15_11.2: %C = bind_name b, %b.loc15_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_11.1: %C = param a +// CHECK:STDOUT: %a.loc15_11.2: %C = bind_name a, %a.loc15_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduced_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_11.1: %C = param a +// CHECK:STDOUT: %a.loc7_11.2: %C = bind_name a, %a.loc7_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_11.1: %C = param a +// CHECK:STDOUT: %a.loc15_11.2: %C = bind_name a, %a.loc15_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- alias_two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_11.1: %C = param a +// CHECK:STDOUT: %a.loc6_11.2: %C = bind_name a, %a.loc6_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_alias_two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//alias_two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: %Foo.type = import_ref Main//alias_two_file, inst+7, loaded [template = constants.%Foo.1] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//alias_two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc6_11.1: %C = param a +// CHECK:STDOUT: %a.loc6_11.2: %C = bind_name a, %a.loc6_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Foo.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_repeat_const.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = const_type %C [template] +// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.1: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Foo.2: type = class_type @Foo [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.4: %.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = class_decl @Foo [template = constants.%Foo.1] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc6: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %a.loc6_11.1: %.2 = param a +// CHECK:STDOUT: %a.loc6_11.2: %.2 = bind_name a, %a.loc6_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.4] { +// CHECK:STDOUT: %C.ref.loc18: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc18_21: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %.loc18_14: type = const_type %.2 [template = constants.%.2] +// CHECK:STDOUT: %a.loc18_11.1: %.2 = param a +// CHECK:STDOUT: %a.loc18_11.2: %.2 = bind_name a, %a.loc18_11.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_self_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Base: type = class_type @Base [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = unbound_element_type %Base, %.1 [template] +// CHECK:STDOUT: %.3: type = ptr_type %Base [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = struct_type {.a: %.1} [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.5: %.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.4 [template] +// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Base = %Base.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {} +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] { +// CHECK:STDOUT: %Base.ref: type = name_ref Base, %Base.decl [template = constants.%Base] +// CHECK:STDOUT: %.loc16_26: type = ptr_type %Base [template = constants.%.3] +// CHECK:STDOUT: %self.loc16_16.1: %.3 = param self +// CHECK:STDOUT: @.1.%self: %.3 = bind_name self, %self.loc16_16.1 +// CHECK:STDOUT: @.1.%.loc16: %.3 = addr_pattern @.1.%self +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Base { +// CHECK:STDOUT: %.loc5_11.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc5_11.2: type = converted %.loc5_11.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc5_8: %.2 = field_decl a, element0 [template] +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%Base [template = constants.%Base] +// CHECK:STDOUT: %.loc7_23: type = ptr_type %Base [template = constants.%.3] +// CHECK:STDOUT: %self.loc7_13.1: %.3 = param self +// CHECK:STDOUT: %self.loc7_13.3: %.3 = bind_name self, %self.loc7_13.1 +// CHECK:STDOUT: %.loc7_8: %.3 = addr_pattern %self.loc7_13.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Base +// CHECK:STDOUT: .a = %.loc5_8 +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F[addr @Base.%self.loc7_13.3: %.3](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1[addr %self: %.3]() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %.3 = name_ref self, %self +// CHECK:STDOUT: %.loc17_4: ref %Base = deref %self.ref +// CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Base.%.loc5_8 [template = @Base.%.loc5_8] +// CHECK:STDOUT: %.loc17_10: ref %.1 = class_element_access %.loc17_4, element0 +// CHECK:STDOUT: %.loc17_16.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc17_16.2: init %.1 = tuple_init () to %.loc17_10 [template = constants.%tuple] +// CHECK:STDOUT: %.loc17_13: init %.1 = converted %.loc17_16.1, %.loc17_16.2 [template = constants.%tuple] +// CHECK:STDOUT: assign %.loc17_10, %.loc17_13 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/syntactic_merge_literal.carbon b/toolchain/check/testdata/class/syntactic_merge_literal.carbon new file mode 100644 index 0000000000000..a5504a4c37e62 --- /dev/null +++ b/toolchain/check/testdata/class/syntactic_merge_literal.carbon @@ -0,0 +1,191 @@ +// 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 +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/syntactic_merge_literal.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/syntactic_merge_literal.carbon +// CHECK:STDERR: fail_int_mismatch.carbon: ERROR: Main//default previously provided by `int_match.carbon`. +// CHECK:STDERR: + +// --- int_match.carbon + +class C(a: i32) {} +class D(b: C(1_000)); +class D(b: C(1_000)) {} + +// --- fail_int_mismatch.carbon + +class C(a: i32) {} +class D(b: C(1000)); +// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE+6]]:14: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class D(b: C(1_000)) {} +// CHECK:STDERR: ^~~~~ +// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE-4]]:14: Comparing with previous declaration here. +// CHECK:STDERR: class D(b: C(1000)); +// CHECK:STDERR: ^~~~ +class D(b: C(1_000)) {} + +// CHECK:STDOUT: --- int_match.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: i32 = int_literal 1000 [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%.3) [template] +// CHECK:STDOUT: %D.type: type = generic_class_type @D [template] +// CHECK:STDOUT: %D.1: %D.type = struct_value () [template] +// CHECK:STDOUT: %D.2: type = class_type @D [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl.loc3 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Core: = namespace %Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc2_12.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_12.2: type = converted %int.make_type_32, %.loc2_12.1 [template = i32] +// CHECK:STDOUT: %a.loc2_9.1: i32 = param a +// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_name a, %a.loc2_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %D.decl.loc3: %D.type = class_decl @D [template = constants.%D.1] { +// CHECK:STDOUT: %C.ref.loc3: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %.loc3_14: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc3_13: init type = call %C.ref.loc3(%.loc3_14) [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_19.1: type = value_of_initializer %.loc3_13 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_19.2: type = converted %.loc3_13, %.loc3_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %b.loc3_9.1: %C.3 = param b +// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_name b, %b.loc3_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %D.decl.loc4: %D.type = class_decl @D [template = constants.%D.1] { +// CHECK:STDOUT: %C.ref.loc4: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %.loc4_14: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc4_13: init type = call %C.ref.loc4(%.loc4_14) [template = constants.%C.3] +// CHECK:STDOUT: %.loc4_19.1: type = value_of_initializer %.loc4_13 [template = constants.%C.3] +// CHECK:STDOUT: %.loc4_19.2: type = converted %.loc4_13, %.loc4_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %b.loc4_9.1: %C.3 = param b +// CHECK:STDOUT: %b.loc4_9.2: %C.3 = bind_name b, %b.loc4_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%.3); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_int_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: i32 = int_literal 1000 [template] +// CHECK:STDOUT: %C.3: type = class_type @C, (%.3) [template] +// CHECK:STDOUT: %D.type: type = generic_class_type @D [template] +// CHECK:STDOUT: %D.1: %D.type = struct_value () [template] +// CHECK:STDOUT: %D.2: type = class_type @D [template] +// CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] +// CHECK:STDOUT: %.4: %.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = class_type @.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Core: = namespace %Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc2_12.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_12.2: type = converted %int.make_type_32, %.loc2_12.1 [template = i32] +// CHECK:STDOUT: %a.loc2_9.1: i32 = param a +// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_name a, %a.loc2_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %D.decl: %D.type = class_decl @D [template = constants.%D.1] { +// CHECK:STDOUT: %C.ref.loc3: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %.loc3_14: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc3_13: init type = call %C.ref.loc3(%.loc3_14) [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_18.1: type = value_of_initializer %.loc3_13 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_18.2: type = converted %.loc3_13, %.loc3_18.1 [template = constants.%C.3] +// CHECK:STDOUT: %b.loc3_9.1: %C.3 = param b +// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_name b, %b.loc3_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.4] { +// CHECK:STDOUT: %C.ref.loc10: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %.loc10_14: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc10_13: init type = call %C.ref.loc10(%.loc10_14) [template = constants.%C.3] +// CHECK:STDOUT: %.loc10_19.1: type = value_of_initializer %.loc10_13 [template = constants.%C.3] +// CHECK:STDOUT: %.loc10_19.2: type = converted %.loc10_13, %.loc10_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %b.loc10_9.1: %C.3 = param b +// CHECK:STDOUT: %b.loc10_9.2: %C.3 = bind_name b, %b.loc10_9.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D; +// CHECK:STDOUT: +// CHECK:STDOUT: class @.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: specific (constants.%.3); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon b/toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon new file mode 100644 index 0000000000000..bc081cd815004 --- /dev/null +++ b/toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon @@ -0,0 +1,754 @@ +// 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 +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/no_prelude/syntactic_merge.carbon + +// --- basic.carbon + +library "basic"; + +class C {} +alias D = C; + +fn Foo(a: C); +fn Foo(a: C) {} + +fn Bar(a: D); +fn Bar(a: D) {} + +// --- spacing.carbon + +library "spacing"; + +class C {} + +fn Foo [ ] ( a : C ); +fn Foo[](a: C) {} + +// --- fail_parens.carbon + +library "parens"; + +class C {} + +fn Foo(a: C); +// CHECK:STDERR: fail_parens.carbon:[[@LINE+7]]:11: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: fn Foo(a: (C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_parens.carbon:[[@LINE-4]]:11: Comparing with previous declaration here. +// CHECK:STDERR: fn Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Foo(a: (C)) {} + +// --- todo_fail_raw_identifier.carbon + +library "raw_identifier"; + +class C {} + +fn Foo(a: C); +fn Foo(a: r#C) {} + +// --- two_file.carbon + +library "two_file"; + +class C {} +alias D = C; + +fn Foo(a: C); +fn Bar(a: D); + +// --- two_file.impl.carbon + +impl library "two_file"; + +fn Foo(a: C) {} +fn Bar(a: D) {} + +// --- fail_name_mismatch.carbon + +library "name_mismatch"; + +class C {} +alias D = C; + +fn Foo(a: C); +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE+7]]:8: ERROR: Redeclaration differs at parameter 1. +// CHECK:STDERR: fn Foo(b: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE-4]]:8: Previous declaration's corresponding parameter here. +// CHECK:STDERR: fn Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Foo(b: D) {} + +// --- fail_alias.carbon + +library "alias"; + +class C {} +alias D = C; + +fn Foo(a: C); +// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:11: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: fn Foo(a: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_alias.carbon:[[@LINE-4]]:11: Comparing with previous declaration here. +// CHECK:STDERR: fn Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Foo(a: D) {} + +// --- fail_deduced_alias.carbon + +library "deduced_alias"; + +class C {} +alias D = C; + +fn Foo[a: C](); +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:11: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: fn Foo[a: D]() {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:11: Comparing with previous declaration here. +// CHECK:STDERR: fn Foo[a: C](); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Foo[a: D]() {} + +// --- todo_fail_alias_in_return.carbon + +library "alias_in_return"; + +class C {} +alias D = C; + +fn Foo() -> C; +fn Foo() -> D { return {}; } + +// --- alias_two_file.carbon + +library "alias_two_file"; + +class C {} + +fn Foo(a: C); + +// --- todo_fail_alias_two_file.impl.carbon + +impl library "alias_two_file"; + +alias D = C; + +fn Foo(a: D) {} + +// --- fail_repeat_const.carbon + +library "repeat_const"; + +class C {} + +fn Foo(a: const C); +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+10]]:11: WARNING: `const` applied repeatedly to the same type has no additional effect. +// CHECK:STDERR: fn Foo(a: const (const C)) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+6]]:17: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: fn Foo(a: const (const C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE-8]]:17: Comparing with previous declaration here. +// CHECK:STDERR: fn Foo(a: const C); +// CHECK:STDERR: ^ +fn Foo(a: const (const C)) {} + +// CHECK:STDOUT: --- basic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %Bar.type: type = fn_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl.loc7 +// CHECK:STDOUT: .Bar = %Bar.decl.loc10 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: %a.loc7_8.2: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc8: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc8_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc8_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc10: %Bar.type = fn_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref.loc10: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc10_8.1: %C = param a +// CHECK:STDOUT: %a.loc10_8.2: %C = bind_name a, %a.loc10_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc11: %Bar.type = fn_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref.loc11: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc11_8.1: %C = param a +// CHECK:STDOUT: @Bar.%a: %C = bind_name a, %a.loc11_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Bar(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- spacing.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_14.1: %C = param a +// CHECK:STDOUT: %a.loc6_14.2: %C = bind_name a, %a.loc6_14.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_10.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_10.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo[](%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_parens.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc6_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %C.ref.loc14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_8.1: %C = param a +// CHECK:STDOUT: @.1.%a: %C = bind_name a, %a.loc14_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_8.1: %C = param a +// CHECK:STDOUT: %a.loc6_8.2: %C = bind_name a, %a.loc6_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Bar.type: type = fn_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = fn_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc8_8.1: %C = param a +// CHECK:STDOUT: @Bar.%a: %C = bind_name a, %a.loc8_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Bar(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %Bar.type: type = fn_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//two_file, inst+5, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3: %Foo.type = import_ref Main//two_file, inst+9, loaded [template = constants.%Foo] +// CHECK:STDOUT: %import_ref.4: %Bar.type = import_ref Main//two_file, inst+16, loaded [template = constants.%Bar] +// CHECK:STDOUT: %import_ref.5 = import_ref Main//two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .D = imports.%import_ref.2 +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %a.loc4_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc4_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = fn_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref: type = name_ref D, imports.%import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %a.loc5_8.1: %C = param a +// CHECK:STDOUT: @Bar.%a: %C = bind_name a, %a.loc5_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Bar(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_name_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %b.loc15_8.1: %C = param b +// CHECK:STDOUT: @.1.%b: %C = bind_name b, %b.loc15_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1(%b: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_8.1: %C = param a +// CHECK:STDOUT: @.1.%a: %C = bind_name a, %a.loc15_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduced_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc7_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_8.1: %C = param a +// CHECK:STDOUT: @.1.%a: %C = bind_name a, %a.loc15_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo[%a: %C](); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1[%a: %C]() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_alias_in_return.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl.loc7 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %return.var.loc7: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc8: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: @Foo.%return: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo() -> %return: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_25.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc8_25.2: init %C = class_init (), %return [template = constants.%struct] +// CHECK:STDOUT: %.loc8_26: init %C = converted %.loc8_25.1, %.loc8_25.2 [template = constants.%struct] +// CHECK:STDOUT: return %.loc8_26 to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- alias_two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc6_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_alias_two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//alias_two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: %Foo.type = import_ref Main//alias_two_file, inst+7, loaded [template = constants.%Foo] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//alias_two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc6_8.1: %C = param a +// CHECK:STDOUT: @Foo.%a: %C = bind_name a, %a.loc6_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_repeat_const.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = const_type %C [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.4: %.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc6: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %a.loc6_8.1: %.2 = param a +// CHECK:STDOUT: @Foo.%a: %.2 = bind_name a, %a.loc6_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.4] { +// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc17_18: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %.loc17_11: type = const_type %.2 [template = constants.%.2] +// CHECK:STDOUT: %a.loc17_8.1: %.2 = param a +// CHECK:STDOUT: @.1.%a: %.2 = bind_name a, %a.loc17_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo(%a: %.2); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @.1(%a: %.2) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon b/toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon new file mode 100644 index 0000000000000..2b74b35a2266a --- /dev/null +++ b/toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon @@ -0,0 +1,795 @@ +// 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 +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon + +// --- basic.carbon + +library "basic"; + +class C {} +alias D = C; + +interface Foo(a: C); +interface Foo(a: C) {} + +interface Bar(a: D); +interface Bar(a: D) {} + +// --- spacing.carbon + +library "spacing"; + +class C {} + +interface Foo [ ] ( a : C ); +interface Foo[](a: C) {} + +// --- fail_parens.carbon + +library "parens"; + +class C {} + +interface Foo(a: C); +// CHECK:STDERR: fail_parens.carbon:[[@LINE+7]]:18: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: interface Foo(a: (C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_parens.carbon:[[@LINE-4]]:18: Comparing with previous declaration here. +// CHECK:STDERR: interface Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +interface Foo(a: (C)) {} + +// --- todo_fail_raw_identifier.carbon + +library "raw_identifier"; + +class C {} + +interface Foo(a: C); +interface Foo(a: r#C) {} + +// --- two_file.carbon + +library "two_file"; + +class C {} +alias D = C; + +interface Foo(a: C); +interface Bar(a: D); + +// --- fail_todo_two_file.impl.carbon + +impl library "two_file"; + +// CHECK:STDERR: fail_todo_two_file.impl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: interface Foo(a: C) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_todo_two_file.impl.carbon:[[@LINE-5]]:6: In import. +// CHECK:STDERR: impl library "two_file"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: two_file.carbon:7:1: Name is previously declared here. +// CHECK:STDERR: interface Foo(a: C); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +interface Foo(a: C) {} +// CHECK:STDERR: fail_todo_two_file.impl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: interface Bar(a: D) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_todo_two_file.impl.carbon:[[@LINE-16]]:6: In import. +// CHECK:STDERR: impl library "two_file"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: two_file.carbon:8:1: Name is previously declared here. +// CHECK:STDERR: interface Bar(a: D); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +interface Bar(a: D) {} + +// --- fail_name_mismatch.carbon + +library "name_mismatch"; + +class C {} +alias D = C; + +interface Foo(a: C); +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE+7]]:15: ERROR: Redeclaration differs at parameter 1. +// CHECK:STDERR: interface Foo(b: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE-4]]:15: Previous declaration's corresponding parameter here. +// CHECK:STDERR: interface Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +interface Foo(b: D) {} + +// --- fail_alias.carbon + +library "alias"; + +class C {} +alias D = C; + +interface Foo(a: C); +// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:18: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: interface Foo(a: D) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_alias.carbon:[[@LINE-4]]:18: Comparing with previous declaration here. +// CHECK:STDERR: interface Foo(a: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +interface Foo(a: D) {} + +// --- fail_deduced_alias.carbon + +library "deduced_alias"; + +class C {} +alias D = C; + +interface Foo[a: C](); +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:18: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: interface Foo[a: D]() {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:18: Comparing with previous declaration here. +// CHECK:STDERR: interface Foo[a: C](); +// CHECK:STDERR: ^ +// CHECK:STDERR: +interface Foo[a: D]() {} + +// --- alias_two_file.carbon + +library "alias_two_file"; + +class C {} + +interface Foo(a: C); + +// --- fail_alias_two_file.impl.carbon + +impl library "alias_two_file"; + +alias D = C; + +// TODO: This fails because importing interfaces doesn't work well. It should +// fail due to `C` versus `D`, but may succeed if importing interfaces is fixed +// before syntax matching on imports is supported. +// CHECK:STDERR: fail_alias_two_file.impl.carbon:[[@LINE+10]]:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: interface Foo(a: D) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_alias_two_file.impl.carbon:[[@LINE-10]]:6: In import. +// CHECK:STDERR: impl library "alias_two_file"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: alias_two_file.carbon:6:1: Name is previously declared here. +// CHECK:STDERR: interface Foo(a: C); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +interface Foo(a: D) {} + +// --- fail_repeat_const.carbon + +library "repeat_const"; + +class C {} + +interface Foo(a: const C); +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+10]]:18: WARNING: `const` applied repeatedly to the same type has no additional effect. +// CHECK:STDERR: interface Foo(a: const (const C)) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+6]]:24: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: interface Foo(a: const (const C)) {} +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE-8]]:24: Comparing with previous declaration here. +// CHECK:STDERR: interface Foo(a: const C); +// CHECK:STDERR: ^ +interface Foo(a: const (const C)) {} + +// CHECK:STDOUT: --- basic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = interface_type @Foo [template] +// CHECK:STDOUT: %Self.1: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %Bar.type: type = generic_interface_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @Bar [template] +// CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl.loc7 +// CHECK:STDOUT: .Bar = %Bar.decl.loc10 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc8: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc8_15.1: %C = param a +// CHECK:STDOUT: %a.loc8_15.2: %C = bind_name a, %a.loc8_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc10: %Bar.type = interface_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref.loc10: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc10_15.1: %C = param a +// CHECK:STDOUT: %a.loc10_15.2: %C = bind_name a, %a.loc10_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl.loc11: %Bar.type = interface_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref.loc11: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc11_15.1: %C = param a +// CHECK:STDOUT: %a.loc11_15.2: %C = bind_name a, %a.loc11_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo { +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Bar { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- spacing.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = interface_type @Foo [template] +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_21.1: %C = param a +// CHECK:STDOUT: %a.loc6_21.2: %C = bind_name a, %a.loc6_21.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_17.1: %C = param a +// CHECK:STDOUT: %a.loc7_17.2: %C = bind_name a, %a.loc7_17.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo { +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_parens.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_15.1: %C = param a +// CHECK:STDOUT: %a.loc6_15.2: %C = bind_name a, %a.loc6_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %C.ref.loc14: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc14_15.1: %C = param a +// CHECK:STDOUT: %a.loc14_15.2: %C = bind_name a, %a.loc14_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = interface_type @Foo [template] +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl.loc6 +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_15.1: %C = param a +// CHECK:STDOUT: %a.loc6_15.2: %C = bind_name a, %a.loc6_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo { +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %Bar.type: type = generic_interface_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = interface_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc8_15.1: %C = param a +// CHECK:STDOUT: %a.loc8_15.2: %C = bind_name a, %a.loc8_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Bar; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type.1: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type.1 = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self.1: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %Bar.type: type = generic_interface_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: %.type.2: type = generic_interface_type @.2 [template] +// CHECK:STDOUT: %.5: %.type.2 = struct_value () [template] +// CHECK:STDOUT: %.6: type = interface_type @.2 [template] +// CHECK:STDOUT: %Self.2: %.6 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//two_file, inst+5, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3: %Foo.type = import_ref Main//two_file, inst+9, loaded [template = constants.%Foo] +// CHECK:STDOUT: %import_ref.4: %Bar.type = import_ref Main//two_file, inst+16, loaded [template = constants.%Bar] +// CHECK:STDOUT: %import_ref.5 = import_ref Main//two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .D = imports.%import_ref.2 +// CHECK:STDOUT: .Foo = imports.%import_ref.3 +// CHECK:STDOUT: .Bar = imports.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %.decl.loc14: %.type.1 = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %a.loc14_15.1: %C = param a +// CHECK:STDOUT: %a.loc14_15.2: %C = bind_name a, %a.loc14_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl.loc25: %.type.2 = interface_decl @.2 [template = constants.%.5] { +// CHECK:STDOUT: %D.ref: type = name_ref D, imports.%import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %a.loc25_15.1: %C = param a +// CHECK:STDOUT: %a.loc25_15.2: %C = bind_name a, %a.loc25_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Bar; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.2 { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_name_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %b.loc15_15.1: %C = param b +// CHECK:STDOUT: %b.loc15_15.2: %C = bind_name b, %b.loc15_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_15.1: %C = param a +// CHECK:STDOUT: %a.loc15_15.2: %C = bind_name a, %a.loc15_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_deduced_alias.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref.loc5: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %C.decl [template = constants.%C] +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc7_15.1: %C = param a +// CHECK:STDOUT: %a.loc7_15.2: %C = bind_name a, %a.loc7_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc15_15.1: %C = param a +// CHECK:STDOUT: %a.loc15_15.2: %C = bind_name a, %a.loc15_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- alias_two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %a.loc6_15.1: %C = param a +// CHECK:STDOUT: %a.loc6_15.2: %C = bind_name a, %a.loc6_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_alias_two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.3: %.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//alias_two_file, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: %Foo.type = import_ref Main//alias_two_file, inst+7, loaded [template = constants.%Foo] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//alias_two_file, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .Foo = imports.%import_ref.2 +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.3] { +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %a.loc19_15.1: %C = param a +// CHECK:STDOUT: %a.loc19_15.2: %C = bind_name a, %a.loc19_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_repeat_const.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = const_type %C [template] +// CHECK:STDOUT: %Foo.type: type = generic_interface_type @Foo [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = generic_interface_type @.1 [template] +// CHECK:STDOUT: %.4: %.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = interface_type @.1 [template] +// CHECK:STDOUT: %Self: %.5 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %Foo.decl: %Foo.type = interface_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc6: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %a.loc6_15.1: %.2 = param a +// CHECK:STDOUT: %a.loc6_15.2: %.2 = bind_name a, %a.loc6_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.decl: %.type = interface_decl @.1 [template = constants.%.4] { +// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc17_25: type = const_type %C [template = constants.%.2] +// CHECK:STDOUT: %.loc17_18: type = const_type %.2 [template = constants.%.2] +// CHECK:STDOUT: %a.loc17_15.1: %.2 = param a +// CHECK:STDOUT: %a.loc17_15.2: %.2 = bind_name a, %a.loc17_15.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Foo; +// CHECK:STDOUT: +// CHECK:STDOUT: interface @.1 { +// CHECK:STDOUT: %Self: %.5 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index dbe4896a3ae67..2012fd5acd542 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -165,6 +165,8 @@ CARBON_DIAGNOSTIC_KIND(RedeclParamCountDiffers) CARBON_DIAGNOSTIC_KIND(RedeclParamCountPrevious) CARBON_DIAGNOSTIC_KIND(RedeclParamDiffers) CARBON_DIAGNOSTIC_KIND(RedeclParamPrevious) +CARBON_DIAGNOSTIC_KIND(RedeclParamSyntaxDiffers) +CARBON_DIAGNOSTIC_KIND(RedeclParamSyntaxPrevious) // Function call checking. CARBON_DIAGNOSTIC_KIND(AddrSelfIsNonRef) diff --git a/toolchain/parse/tree.cpp b/toolchain/parse/tree.cpp index 6fbf54d27cb5d..8423e8de6162f 100644 --- a/toolchain/parse/tree.cpp +++ b/toolchain/parse/tree.cpp @@ -32,6 +32,13 @@ auto Tree::postorder(NodeId n) const PostorderIterator(NodeId(end_index))); } +auto Tree::postorder(NodeId begin, NodeId end) const + -> llvm::iterator_range { + CARBON_CHECK(begin.is_valid() && end.is_valid()); + return llvm::iterator_range( + PostorderIterator(begin), PostorderIterator(NodeId(end.index + 1))); +} + auto Tree::children(NodeId n) const -> llvm::iterator_range { CARBON_CHECK(n.is_valid()); int end_index = n.index - node_impls_[n.index].subtree_size; diff --git a/toolchain/parse/tree.h b/toolchain/parse/tree.h index a67f4473a6d55..8a204d952d15d 100644 --- a/toolchain/parse/tree.h +++ b/toolchain/parse/tree.h @@ -118,6 +118,11 @@ class Tree : public Printable { // descendants in depth-first postorder. auto postorder(NodeId n) const -> llvm::iterator_range; + // Returns an iterable range between the two parse tree nodes, in depth-first + // postorder. The range is inclusive of the bounds: [begin, end]. + auto postorder(NodeId begin, NodeId end) const + -> llvm::iterator_range; + // Returns an iterable range over the direct children of a node in the parse // tree. This is a forward range, but is constant time to increment. The order // of children is the same as would be found in a reverse postorder traversal. diff --git a/toolchain/sem_ir/class.h b/toolchain/sem_ir/class.h index 96a6aac668108..9ddf535936e40 100644 --- a/toolchain/sem_ir/class.h +++ b/toolchain/sem_ir/class.h @@ -42,6 +42,11 @@ struct Class : public Printable { NameScopeId parent_scope_id; // If this is a generic function, information about the generic. GenericId generic_id; + // Parse tree bounds for the parameters, including both implicit and explicit + // parameters. These will be compared to match between declaration and + // definition. + Parse::NodeId first_param_node_id; + Parse::NodeId last_param_node_id; // A block containing a single reference instruction per implicit parameter. InstBlockId implicit_param_refs_id; // A block containing a single reference instruction per parameter. diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 5e45ee710cd4e..c9bbff17c5617 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -86,6 +86,11 @@ struct Function : public Printable { InstId decl_id; // If this is a generic function, information about the generic. GenericId generic_id; + // Parse tree bounds for the parameters, including both implicit and explicit + // parameters. These will be compared to match between declaration and + // definition. + Parse::NodeId first_param_node_id; + Parse::NodeId last_param_node_id; // A block containing a single reference instruction per implicit parameter. InstBlockId implicit_param_refs_id; // A block containing a single reference instruction per parameter. diff --git a/toolchain/sem_ir/interface.h b/toolchain/sem_ir/interface.h index 89fbe93a03605..67e595a34ebf3 100644 --- a/toolchain/sem_ir/interface.h +++ b/toolchain/sem_ir/interface.h @@ -39,6 +39,11 @@ struct Interface : public Printable { NameScopeId parent_scope_id; // If this is a generic function, information about the generic. GenericId generic_id; + // Parse tree bounds for the parameters, including both implicit and explicit + // parameters. These will be compared to match between declaration and + // definition. + Parse::NodeId first_param_node_id; + Parse::NodeId last_param_node_id; // A block containing a single reference instruction per implicit parameter. InstBlockId implicit_param_refs_id; // A block containing a single reference instruction per parameter.