diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index 6d2f84392076..f486bd395a06 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -206,7 +206,7 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param, SemIR::InstId new_param_pattern_id, SemIR::InstId prev_param_pattern_id, SemIR::SpecificId prev_specific_id, bool diagnose, - bool check_self) -> bool { + bool check_syntax, bool check_self) -> bool { auto orig_new_param_pattern_id = new_param_pattern_id; auto orig_prev_param_pattern_id = prev_param_pattern_id; @@ -300,7 +300,7 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param, return false; } - if (new_name_id != prev_name_id) { + if (check_syntax && new_name_id != prev_name_id) { emit_diagnostic(); return false; } @@ -315,7 +315,7 @@ static auto CheckRedeclParams(Context& context, SemIR::LocId new_decl_loc_id, SemIR::InstBlockId prev_param_patterns_id, bool is_implicit_param, SemIR::SpecificId prev_specific_id, bool diagnose, - bool check_self) -> bool { + bool check_syntax, bool check_self) -> bool { // This will often occur for empty params. if (new_param_patterns_id == prev_param_patterns_id) { return true; @@ -373,7 +373,8 @@ static auto CheckRedeclParams(Context& context, SemIR::LocId new_decl_loc_id, llvm::enumerate(new_param_pattern_ids, prev_param_pattern_ids)) { if (!CheckRedeclParam(context, is_implicit_param, index, new_param_pattern_id, prev_param_pattern_id, - prev_specific_id, diagnose, check_self)) { + prev_specific_id, diagnose, check_syntax, + check_self)) { return false; } } @@ -493,7 +494,8 @@ auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, if (!CheckRedeclParams( context, new_entity.loc_id, new_entity.implicit_param_patterns_id, prev_entity.loc_id, prev_entity.implicit_param_patterns_id, - /*is_implicit_param=*/true, prev_specific_id, diagnose, check_self)) { + /*is_implicit_param=*/true, prev_specific_id, diagnose, check_syntax, + check_self)) { return false; } // Don't forward `check_self` here because it's extra cost, and `self` is only @@ -502,7 +504,7 @@ auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, new_entity.param_patterns_id, prev_entity.loc_id, prev_entity.param_patterns_id, /*is_implicit_param=*/false, prev_specific_id, - diagnose, /*check_self=*/true)) { + diagnose, check_syntax, /*check_self=*/true)) { return false; } if (check_syntax && diff --git a/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon b/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon index 0e32fcb99eb6..73eeb64158da 100644 --- a/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon +++ b/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon @@ -8,39 +8,15 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon -// --- fail_todo_param_name_differs.carbon +// --- no_thunk_param_name_differs.carbon library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+3]]:20: error: parameter has incomplete type `C` in function definition [IncompleteTypeInFunctionParam] -// CHECK:STDERR: interface I { fn F(x: Self); } -// CHECK:STDERR: ^~~~~~~ interface I { fn F(x: Self); } -// TODO: This currently uses a thunk due to the parameter name mismatch, but shouldn't! -// TODO: This then fails because we attempt to build the thunk before `C` is complete. -// CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ +// This is OK, and does not require a thunk despite the parameter name differing. class C { impl as I { - // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+17]]:5: note: while building thunk calling this function [ThunkCallee] - // CHECK:STDERR: fn F(not_x: C); - // CHECK:STDERR: ^~~~~~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-13]]:20: error: forming value of incomplete type `C` [IncompleteTypeInValueConversion] - // CHECK:STDERR: interface I { fn F(x: Self); } - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-9]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] - // CHECK:STDERR: class C { - // CHECK:STDERR: ^~~~~~~~~ - // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam] - // CHECK:STDERR: fn F(not_x: C); - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-22]]:15: note: while building thunk to match the signature of this function [ThunkSignature] - // CHECK:STDERR: interface I { fn F(x: Self); } - // CHECK:STDERR: ^~~~~~~~~~~~~~ - // CHECK:STDERR: fn F(not_x: C); } } @@ -227,7 +203,7 @@ impl C as I { fn NoReturn() -> C; } -// CHECK:STDOUT: --- fail_todo_param_name_differs.carbon +// CHECK:STDOUT: --- no_thunk_param_name_differs.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] @@ -235,18 +211,15 @@ impl C as I { // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] // CHECK:STDOUT: %pattern_type.6de: type = pattern_type %Self.as_type [symbolic] // CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] // CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %I.impl_witness: = impl_witness @C.%I.impl_witness_table [concrete] // CHECK:STDOUT: %pattern_type.c48: type = pattern_type %C [concrete] -// CHECK:STDOUT: %F.type.f3605c.1: type = fn_type @F.2 [concrete] -// CHECK:STDOUT: %F.4c32b3.1: %F.type.f3605c.1 = struct_value () [concrete] +// CHECK:STDOUT: %F.type.f36: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.4c3: %F.type.f36 = struct_value () [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] -// CHECK:STDOUT: %F.type.f3605c.2: type = fn_type @F.3 [concrete] -// CHECK:STDOUT: %F.4c32b3.2: %F.type.f3605c.2 = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: } @@ -266,13 +239,13 @@ impl C as I { // CHECK:STDOUT: %x.patt: @F.1.%pattern_type (%pattern_type.6de) = binding_pattern x [concrete] // CHECK:STDOUT: %x.param_patt: @F.1.%pattern_type (%pattern_type.6de) = value_param_pattern %x.patt, call_param0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %x.param: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type) = value_param call_param0 -// CHECK:STDOUT: %.loc7_23.1: type = splice_block %.loc7_23.2 [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] { +// CHECK:STDOUT: %x.param: @F.1.%Self.as_type.loc4_23.1 (%Self.as_type) = value_param call_param0 +// CHECK:STDOUT: %.loc4_23.1: type = splice_block %.loc4_23.2 [symbolic = %Self.as_type.loc4_23.1 (constants.%Self.as_type)] { // CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] -// CHECK:STDOUT: %Self.as_type.loc7_23.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %.loc7_23.2: type = converted %Self.ref, %Self.as_type.loc7_23.2 [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %Self.as_type.loc4_23.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc4_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc4_23.2: type = converted %Self.ref, %Self.as_type.loc4_23.2 [symbolic = %Self.as_type.loc4_23.1 (constants.%Self.as_type)] // CHECK:STDOUT: } -// CHECK:STDOUT: %x: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type) = bind_name x, %x.param +// CHECK:STDOUT: %x: @F.1.%Self.as_type.loc4_23.1 (%Self.as_type) = bind_name x, %x.param // CHECK:STDOUT: } // CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] // CHECK:STDOUT: @@ -283,7 +256,7 @@ impl C as I { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %Self.ref as %I.ref { -// CHECK:STDOUT: %F.decl.loc33_19.1: %F.type.f3605c.1 = fn_decl @F.2 [concrete = constants.%F.4c32b3.1] { +// CHECK:STDOUT: %F.decl: %F.type.f36 = fn_decl @F.2 [concrete = constants.%F.4c3] { // CHECK:STDOUT: %not_x.patt: %pattern_type.c48 = binding_pattern not_x [concrete] // CHECK:STDOUT: %not_x.param_patt: %pattern_type.c48 = value_param_pattern %not_x.patt, call_param0 [concrete] // CHECK:STDOUT: } { @@ -291,17 +264,10 @@ impl C as I { // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: %not_x: %C = bind_name not_x, %not_x.param // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl.loc33_19.2: %F.type.f3605c.2 = fn_decl @F.3 [concrete = constants.%F.4c32b3.2] { -// CHECK:STDOUT: %x.patt: %pattern_type.c48 = binding_pattern x [concrete] -// CHECK:STDOUT: %x.param_patt: %pattern_type.c48 = value_param_pattern %x.patt, call_param0 [concrete] -// CHECK:STDOUT: } { -// CHECK:STDOUT: %x.param: %C = value_param call_param0 -// CHECK:STDOUT: %x: %C = bind_name x, %x.param -// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .C = -// CHECK:STDOUT: .F = %F.decl.loc33_19.1 +// CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: witness = @C.%I.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: @@ -310,7 +276,7 @@ impl C as I { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc33_19.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl), @impl [concrete] // CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] @@ -324,30 +290,23 @@ impl C as I { // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { // CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] -// CHECK:STDOUT: %Self.as_type.loc7_23.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc7_23.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] +// CHECK:STDOUT: %Self.as_type.loc4_23.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc4_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc4_23.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%x.param: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type)); +// CHECK:STDOUT: fn(%x.param: @F.1.%Self.as_type.loc4_23.1 (%Self.as_type)); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(%not_x.param: %C); // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.3(%x.param: %C) { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %C = name_ref x, %x.param -// CHECK:STDOUT: %F.call: init %empty_tuple.type = call @impl.%F.decl.loc33_19.1() -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%Self) { // CHECK:STDOUT: %Self => constants.%Self -// CHECK:STDOUT: %Self.as_type.loc7_23.1 => constants.%Self.as_type +// CHECK:STDOUT: %Self.as_type.loc4_23.1 => constants.%Self.as_type // CHECK:STDOUT: %pattern_type => constants.%pattern_type.6de // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%I.facet) { // CHECK:STDOUT: %Self => constants.%I.facet -// CHECK:STDOUT: %Self.as_type.loc7_23.1 => constants.%C +// CHECK:STDOUT: %Self.as_type.loc4_23.1 => constants.%C // CHECK:STDOUT: %pattern_type => constants.%pattern_type.c48 // CHECK:STDOUT: } // CHECK:STDOUT: