From 1c3c92b3327850880368fce4f62668f115f0a57b Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 5 Oct 2024 03:44:44 +0000 Subject: [PATCH 1/9] Baseline --- toolchain/check/testdata/class/fail_abstract.carbon | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index 75c5d4322b79c..8111972b04f9d 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -30,6 +30,8 @@ fn Access(d: Derived) -> (i32, i32) { return (d.d, d.base.a); } +abstract class AbstractDecl; + // CHECK:STDOUT: --- fail_abstract.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -59,6 +61,7 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDOUT: %Access.type: type = fn_type @Access [template] // CHECK:STDOUT: %Access: %Access.type = struct_value () [template] // CHECK:STDOUT: %.18: type = ptr_type %.17 [template] +// CHECK:STDOUT: %AbstractDecl: type = class_type @AbstractDecl [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -83,6 +86,7 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDOUT: .Derived = %Derived.decl // CHECK:STDOUT: .Make = %Make.decl // CHECK:STDOUT: .Access = %Access.decl +// CHECK:STDOUT: .AbstractDecl = %AbstractDecl.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %Abstract.decl: type = class_decl @Abstract [template = constants.%Abstract] {} {} @@ -107,6 +111,7 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDOUT: %.loc29_35.6: type = converted %.loc29_35.1, constants.%.17 [template = constants.%.17] // CHECK:STDOUT: %return: ref %.17 = var // CHECK:STDOUT: } +// CHECK:STDOUT: %AbstractDecl.decl: type = class_decl @AbstractDecl [template = constants.%AbstractDecl] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Abstract { @@ -137,6 +142,8 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDOUT: extend name_scope2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: class @AbstractDecl; +// CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: // CHECK:STDOUT: fn @Make() -> %return: %Derived { From e43805313c13a39a0928be5475e9cb343cb1304d Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 7 Oct 2024 18:38:02 +0000 Subject: [PATCH 2/9] Disallow `abstract` or `base` on class declarations (that are not definitions) Per: https://docs.carbon-lang.dev/proposals/p3762.html#modifier-keywords:~:text=Other%20class%2C%20impl%2C%20and%20interface%20modifiers%20%28abstract%2C%20base%2C%20final%29%20exist%20only%20on%20the%20definition%2C%20not%20on%20the%20forward%20declaration "Other class, impl, and interface modifiers (`abstract`, `base`, `final`) exist only on the definition, not on the forward declaration." --- toolchain/check/handle_class.cpp | 5 +- .../check/testdata/class/fail_abstract.carbon | 64 ++++++++-------- .../testdata/class/fail_base_bad_type.carbon | 74 ++++++++++--------- .../testdata/class/fail_modifiers.carbon | 20 ++++- .../fail_redeclaration_introducer.carbon | 58 ++++++++------- .../class/redeclaration_introducer.carbon | 39 +++++++--- 6 files changed, 152 insertions(+), 108 deletions(-) diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index c500a7dbf4a87..942e40216518f 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -195,8 +195,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, context.decl_introducer_state_stack().Pop(); CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); LimitModifiersOnDecl(context, introducer, - KeywordModifierSet::Class | KeywordModifierSet::Access | - KeywordModifierSet::Extern); + KeywordModifierSet::Access | KeywordModifierSet::Extern | + (is_definition ? KeywordModifierSet::Class + : KeywordModifierSet::None)); RestrictExternModifierOnDecl(context, introducer, parent_scope_inst, is_definition); diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index 8111972b04f9d..b689787cfbf7d 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -20,9 +20,10 @@ class Derived { fn Make() -> Derived { // TODO: This should be valid, and should construct an instance of `partial Abstract` as the base. - // CHECK:STDERR: fail_abstract.carbon:[[@LINE+3]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead + // CHECK:STDERR: fail_abstract.carbon:[[@LINE+4]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; } @@ -30,6 +31,9 @@ fn Access(d: Derived) -> (i32, i32) { return (d.d, d.base.a); } +// CHECK:STDERR: fail_abstract.carbon:[[@LINE+3]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract class AbstractDecl; +// CHECK:STDERR: ^~~~~~~~ abstract class AbstractDecl; // CHECK:STDOUT: --- fail_abstract.carbon @@ -101,14 +105,14 @@ abstract class AbstractDecl; // CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived] // CHECK:STDOUT: %d.param: %Derived = param d, runtime_param0 // CHECK:STDOUT: %d: %Derived = bind_name d, %d.param -// CHECK:STDOUT: %int.make_type_32.loc29_27: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc29_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc29_35.1: %.16 = tuple_literal (%int.make_type_32.loc29_27, %int.make_type_32.loc29_32) -// CHECK:STDOUT: %.loc29_35.2: type = value_of_initializer %int.make_type_32.loc29_27 [template = i32] -// CHECK:STDOUT: %.loc29_35.3: type = converted %int.make_type_32.loc29_27, %.loc29_35.2 [template = i32] -// CHECK:STDOUT: %.loc29_35.4: type = value_of_initializer %int.make_type_32.loc29_32 [template = i32] -// CHECK:STDOUT: %.loc29_35.5: type = converted %int.make_type_32.loc29_32, %.loc29_35.4 [template = i32] -// CHECK:STDOUT: %.loc29_35.6: type = converted %.loc29_35.1, constants.%.17 [template = constants.%.17] +// CHECK:STDOUT: %int.make_type_32.loc30_27: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc30_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc30_35.1: %.16 = tuple_literal (%int.make_type_32.loc30_27, %int.make_type_32.loc30_32) +// CHECK:STDOUT: %.loc30_35.2: type = value_of_initializer %int.make_type_32.loc30_27 [template = i32] +// CHECK:STDOUT: %.loc30_35.3: type = converted %int.make_type_32.loc30_27, %.loc30_35.2 [template = i32] +// CHECK:STDOUT: %.loc30_35.4: type = value_of_initializer %int.make_type_32.loc30_32 [template = i32] +// CHECK:STDOUT: %.loc30_35.5: type = converted %int.make_type_32.loc30_32, %.loc30_35.4 [template = i32] +// CHECK:STDOUT: %.loc30_35.6: type = converted %.loc30_35.1, constants.%.17 [template = constants.%.17] // CHECK:STDOUT: %return: ref %.17 = var // CHECK:STDOUT: } // CHECK:STDOUT: %AbstractDecl.decl: type = class_decl @AbstractDecl [template = constants.%AbstractDecl] {} {} @@ -148,33 +152,33 @@ abstract class AbstractDecl; // CHECK:STDOUT: // CHECK:STDOUT: fn @Make() -> %return: %Derived { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc26_25: i32 = int_literal 1 [template = constants.%.13] -// CHECK:STDOUT: %.loc26_26: %.3 = struct_literal (%.loc26_25) -// CHECK:STDOUT: %.loc26_34: i32 = int_literal 7 [template = constants.%.14] -// CHECK:STDOUT: %.loc26_35: %.15 = struct_literal (%.loc26_26, %.loc26_34) +// CHECK:STDOUT: %.loc27_25: i32 = int_literal 1 [template = constants.%.13] +// CHECK:STDOUT: %.loc27_26: %.3 = struct_literal (%.loc27_25) +// CHECK:STDOUT: %.loc27_34: i32 = int_literal 7 [template = constants.%.14] +// CHECK:STDOUT: %.loc27_35: %.15 = struct_literal (%.loc27_26, %.loc27_34) // CHECK:STDOUT: return to %return // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Access(%d: %Derived) -> %return: %.17 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %d.ref.loc30_11: %Derived = name_ref d, %d -// CHECK:STDOUT: %d.ref.loc30_12: %.7 = name_ref d, @Derived.%.loc18_8 [template = @Derived.%.loc18_8] -// CHECK:STDOUT: %.loc30_12.1: ref i32 = class_element_access %d.ref.loc30_11, element1 -// CHECK:STDOUT: %.loc30_12.2: i32 = bind_value %.loc30_12.1 -// CHECK:STDOUT: %d.ref.loc30_16: %Derived = name_ref d, %d +// CHECK:STDOUT: %d.ref.loc31_11: %Derived = name_ref d, %d +// CHECK:STDOUT: %d.ref.loc31_12: %.7 = name_ref d, @Derived.%.loc18_8 [template = @Derived.%.loc18_8] +// CHECK:STDOUT: %.loc31_12.1: ref i32 = class_element_access %d.ref.loc31_11, element1 +// CHECK:STDOUT: %.loc31_12.2: i32 = bind_value %.loc31_12.1 +// CHECK:STDOUT: %d.ref.loc31_16: %Derived = name_ref d, %d // CHECK:STDOUT: %base.ref: %.6 = name_ref base, @Derived.%.loc16 [template = @Derived.%.loc16] -// CHECK:STDOUT: %.loc30_17.1: ref %Abstract = class_element_access %d.ref.loc30_16, element0 -// CHECK:STDOUT: %.loc30_17.2: %Abstract = bind_value %.loc30_17.1 +// CHECK:STDOUT: %.loc31_17.1: ref %Abstract = class_element_access %d.ref.loc31_16, element0 +// CHECK:STDOUT: %.loc31_17.2: %Abstract = bind_value %.loc31_17.1 // CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Abstract.%.loc12_8 [template = @Abstract.%.loc12_8] -// CHECK:STDOUT: %.loc30_22.1: ref i32 = class_element_access %.loc30_17.2, element0 -// CHECK:STDOUT: %.loc30_22.2: i32 = bind_value %.loc30_22.1 -// CHECK:STDOUT: %.loc30_24.1: %.17 = tuple_literal (%.loc30_12.2, %.loc30_22.2) -// CHECK:STDOUT: %.loc30_24.2: ref i32 = tuple_access %return, element0 -// CHECK:STDOUT: %.loc30_24.3: init i32 = initialize_from %.loc30_12.2 to %.loc30_24.2 -// CHECK:STDOUT: %.loc30_24.4: ref i32 = tuple_access %return, element1 -// CHECK:STDOUT: %.loc30_24.5: init i32 = initialize_from %.loc30_22.2 to %.loc30_24.4 -// CHECK:STDOUT: %.loc30_24.6: init %.17 = tuple_init (%.loc30_24.3, %.loc30_24.5) to %return -// CHECK:STDOUT: %.loc30_25: init %.17 = converted %.loc30_24.1, %.loc30_24.6 -// CHECK:STDOUT: return %.loc30_25 to %return +// CHECK:STDOUT: %.loc31_22.1: ref i32 = class_element_access %.loc31_17.2, element0 +// CHECK:STDOUT: %.loc31_22.2: i32 = bind_value %.loc31_22.1 +// CHECK:STDOUT: %.loc31_24.1: %.17 = tuple_literal (%.loc31_12.2, %.loc31_22.2) +// CHECK:STDOUT: %.loc31_24.2: ref i32 = tuple_access %return, element0 +// CHECK:STDOUT: %.loc31_24.3: init i32 = initialize_from %.loc31_12.2 to %.loc31_24.2 +// CHECK:STDOUT: %.loc31_24.4: ref i32 = tuple_access %return, element1 +// CHECK:STDOUT: %.loc31_24.5: init i32 = initialize_from %.loc31_22.2 to %.loc31_24.4 +// CHECK:STDOUT: %.loc31_24.6: init %.17 = tuple_init (%.loc31_24.3, %.loc31_24.5) to %return +// CHECK:STDOUT: %.loc31_25: init %.17 = converted %.loc31_24.1, %.loc31_24.6 +// CHECK:STDOUT: return %.loc31_25 to %return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_base_bad_type.carbon b/toolchain/check/testdata/class/fail_base_bad_type.carbon index 4c6a34f0d2720..d5d5fddf418f0 100644 --- a/toolchain/check/testdata/class/fail_base_bad_type.carbon +++ b/toolchain/check/testdata/class/fail_base_bad_type.carbon @@ -99,6 +99,10 @@ fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return // It would be OK to reject this if we start actually looking in the struct type. fn AccessMemberWithInvalidBaseStruct(p: DeriveFromStruct*) -> i32 { return (*p).n; } +// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: base class Incomplete; +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: base class Incomplete; class DeriveFromIncomplete { @@ -422,23 +426,23 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: %p.patt: %.32 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] -// CHECK:STDOUT: %.loc122_54: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] +// CHECK:STDOUT: %.loc126_54: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] // CHECK:STDOUT: %p.param: %.32 = param p, runtime_param0 // CHECK:STDOUT: %p: %.32 = bind_name p, %p.param // CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] -// CHECK:STDOUT: %.loc122_70: type = ptr_type %Incomplete [template = constants.%.33] +// CHECK:STDOUT: %.loc126_70: type = ptr_type %Incomplete [template = constants.%.33] // CHECK:STDOUT: %return: ref %.33 = var // CHECK:STDOUT: } // CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete.decl: %AccessMemberWithInvalidBaseIncomplete.type = fn_decl @AccessMemberWithInvalidBaseIncomplete [template = constants.%AccessMemberWithInvalidBaseIncomplete] { // CHECK:STDOUT: %p.patt: %.32 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] -// CHECK:STDOUT: %.loc124_65: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] +// CHECK:STDOUT: %.loc128_65: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] // CHECK:STDOUT: %p.param: %.32 = param p, runtime_param0 // CHECK:STDOUT: %p: %.32 = bind_name p, %p.param // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc124_71.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc124_71.2: type = converted %int.make_type_32, %.loc124_71.1 [template = i32] +// CHECK:STDOUT: %.loc128_71.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc128_71.2: type = converted %int.make_type_32, %.loc128_71.1 [template = i32] // CHECK:STDOUT: %return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: %DeriveFromFinal.decl: type = class_decl @DeriveFromFinal [template = constants.%DeriveFromFinal] {} {} @@ -446,35 +450,35 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: %p.patt: %.40 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc135_44: type = ptr_type %DeriveFromFinal [template = constants.%.40] +// CHECK:STDOUT: %.loc139_44: type = ptr_type %DeriveFromFinal [template = constants.%.40] // CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 // CHECK:STDOUT: %p: %.40 = bind_name p, %p.param // CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] -// CHECK:STDOUT: %.loc135_55: type = ptr_type %Final [template = constants.%.41] +// CHECK:STDOUT: %.loc139_55: type = ptr_type %Final [template = constants.%.41] // CHECK:STDOUT: %return: ref %.41 = var // CHECK:STDOUT: } // CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember.decl: %AccessMemberWithInvalidBaseFinal_WithMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember [template = constants.%AccessMemberWithInvalidBaseFinal_WithMember] { // CHECK:STDOUT: %p.patt: %.40 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc139_66: type = ptr_type %DeriveFromFinal [template = constants.%.40] +// CHECK:STDOUT: %.loc143_66: type = ptr_type %DeriveFromFinal [template = constants.%.40] // CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 // CHECK:STDOUT: %p: %.40 = bind_name p, %p.param // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc139_72.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc139_72.2: type = converted %int.make_type_32, %.loc139_72.1 [template = i32] +// CHECK:STDOUT: %.loc143_72.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc143_72.2: type = converted %int.make_type_32, %.loc143_72.1 [template = i32] // CHECK:STDOUT: %return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember.decl: %AccessMemberWithInvalidBaseFinal_NoMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember [template = constants.%AccessMemberWithInvalidBaseFinal_NoMember] { // CHECK:STDOUT: %p.patt: %.40 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc143_64: type = ptr_type %DeriveFromFinal [template = constants.%.40] +// CHECK:STDOUT: %.loc147_64: type = ptr_type %DeriveFromFinal [template = constants.%.40] // CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 // CHECK:STDOUT: %p: %.40 = bind_name p, %p.param // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc143_70.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc143_70.2: type = converted %int.make_type_32, %.loc143_70.1 [template = i32] +// CHECK:STDOUT: %.loc147_70.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc147_70.2: type = converted %int.make_type_32, %.loc147_70.1 [template = i32] // CHECK:STDOUT: %return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -590,23 +594,23 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: class @DeriveFromIncomplete { // CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] -// CHECK:STDOUT: %.loc112: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc113: = complete_type_witness [template = ] +// CHECK:STDOUT: %.loc116: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc117: = complete_type_witness [template = ] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%DeriveFromIncomplete -// CHECK:STDOUT: .base = %.loc112 +// CHECK:STDOUT: .base = %.loc116 // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @DeriveFromFinal { // CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] -// CHECK:STDOUT: %.loc131: %.37 = base_decl %Final, element0 [template] -// CHECK:STDOUT: %.loc132: = complete_type_witness %.38 [template = constants.%.39] +// CHECK:STDOUT: %.loc135: %.37 = base_decl %Final, element0 [template] +// CHECK:STDOUT: %.loc136: = complete_type_witness %.38 [template = constants.%.39] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%DeriveFromFinal -// CHECK:STDOUT: .base = %.loc131 +// CHECK:STDOUT: .base = %.loc135 // CHECK:STDOUT: extend name_scope3 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -694,16 +698,16 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: %.32 = name_ref p, %p // CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.33) [template = constants.%ImplicitAs.type.7] -// CHECK:STDOUT: %.loc122_82.1: %.34 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.33) [template = constants.%.35] -// CHECK:STDOUT: %Convert.ref: %.34 = name_ref Convert, %.loc122_82.1 [template = constants.%.35] -// CHECK:STDOUT: %.loc122_82.2: %.33 = converted %p.ref, [template = ] +// CHECK:STDOUT: %.loc126_82.1: %.34 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.33) [template = constants.%.35] +// CHECK:STDOUT: %Convert.ref: %.34 = name_ref Convert, %.loc126_82.1 [template = constants.%.35] +// CHECK:STDOUT: %.loc126_82.2: %.33 = converted %p.ref, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @AccessMemberWithInvalidBaseIncomplete(%p: %.32) -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: %.32 = name_ref p, %p -// CHECK:STDOUT: %.loc124_85: ref %DeriveFromIncomplete = deref %p.ref +// CHECK:STDOUT: %.loc128_85: ref %DeriveFromIncomplete = deref %p.ref // CHECK:STDOUT: %n.ref: = name_ref n, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -711,29 +715,29 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: fn @ConvertToBadBaseFinal(%p: %.40) -> %.41 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc136_11.1: ref %DeriveFromFinal = deref %p.ref -// CHECK:STDOUT: %.loc136_11.2: ref %Final = class_element_access %.loc136_11.1, element0 -// CHECK:STDOUT: %.loc136_11.3: %.41 = addr_of %.loc136_11.2 -// CHECK:STDOUT: %.loc136_11.4: %.41 = converted %p.ref, %.loc136_11.3 -// CHECK:STDOUT: return %.loc136_11.4 +// CHECK:STDOUT: %.loc140_11.1: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %.loc140_11.2: ref %Final = class_element_access %.loc140_11.1, element0 +// CHECK:STDOUT: %.loc140_11.3: %.41 = addr_of %.loc140_11.2 +// CHECK:STDOUT: %.loc140_11.4: %.41 = converted %p.ref, %.loc140_11.3 +// CHECK:STDOUT: return %.loc140_11.4 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_WithMember(%p: %.40) -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc140_11: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %.loc144_11: ref %DeriveFromFinal = deref %p.ref // CHECK:STDOUT: %a.ref: %.4 = name_ref a, @Final.%.loc13_8 [template = @Final.%.loc13_8] -// CHECK:STDOUT: %.loc140_14.1: ref %Final = class_element_access %.loc140_11, element0 -// CHECK:STDOUT: %.loc140_14.2: ref %Final = converted %.loc140_11, %.loc140_14.1 -// CHECK:STDOUT: %.loc140_14.3: ref i32 = class_element_access %.loc140_14.2, element0 -// CHECK:STDOUT: %.loc140_14.4: i32 = bind_value %.loc140_14.3 -// CHECK:STDOUT: return %.loc140_14.4 +// CHECK:STDOUT: %.loc144_14.1: ref %Final = class_element_access %.loc144_11, element0 +// CHECK:STDOUT: %.loc144_14.2: ref %Final = converted %.loc144_11, %.loc144_14.1 +// CHECK:STDOUT: %.loc144_14.3: ref i32 = class_element_access %.loc144_14.2, element0 +// CHECK:STDOUT: %.loc144_14.4: i32 = bind_value %.loc144_14.3 +// CHECK:STDOUT: return %.loc144_14.4 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_NoMember(%p: %.40) -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc147: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %.loc151: ref %DeriveFromFinal = deref %p.ref // CHECK:STDOUT: %b.ref: = name_ref b, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index 33f8c20d64b1b..e86eb8075252a 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -8,6 +8,10 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_modifiers.carbon +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:9: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: private abstract private class DuplicatePrivate; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:18: error: `private` repeated on declaration // CHECK:STDERR: private abstract private class DuplicatePrivate; // CHECK:STDERR: ^~~~~~~ @@ -26,6 +30,10 @@ private abstract private class DuplicatePrivate; // CHECK:STDERR: private base protected class TwoAccess {} +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract abstract class TwoAbstract; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `abstract` repeated on declaration // CHECK:STDERR: abstract abstract class TwoAbstract; // CHECK:STDERR: ^~~~~~~~ @@ -52,6 +60,10 @@ abstract abstract class TwoAbstract; // CHECK:STDERR: protected virtual base class Virtual {} +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract protected class WrongOrder; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `protected` must appear before `abstract` // CHECK:STDERR: abstract protected class WrongOrder; // CHECK:STDERR: ^~~~~~~~~ @@ -141,7 +153,7 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: class @DuplicatePrivate; // CHECK:STDOUT: // CHECK:STDOUT: class @TwoAccess { -// CHECK:STDOUT: %.loc27: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc31: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%TwoAccess @@ -150,7 +162,7 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: class @TwoAbstract; // CHECK:STDOUT: // CHECK:STDOUT: class @Virtual { -// CHECK:STDOUT: %.loc53: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc61: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Virtual @@ -159,7 +171,7 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: class @WrongOrder; // CHECK:STDOUT: // CHECK:STDOUT: class @AbstractAndBase { -// CHECK:STDOUT: %.loc71: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc83: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%AbstractAndBase @@ -168,7 +180,7 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: class @AbstractWithDefinition { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {} // CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} {} -// CHECK:STDOUT: %.loc80: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc92: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%AbstractWithDefinition diff --git a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon b/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon index 800ec4e70f1e3..9ffa7a648cdd5 100644 --- a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon +++ b/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon @@ -40,20 +40,21 @@ abstract class B {} library "[[@TEST_NAME]]"; -base class C; -// CHECK:STDERR: fail_remove_base.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: class C {} -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_remove_base.carbon:[[@LINE-4]]:1: note: previously declared here +// CHECK:STDERR: fail_remove_base.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration // CHECK:STDERR: base class C; -// CHECK:STDERR: ^~~~~~~~~~~~~ +// CHECK:STDERR: ^~~~ // CHECK:STDERR: +base class C; class C {} // --- fail_base_to_abstract.carbon library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: base class D; +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: base class D; // CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind // CHECK:STDERR: abstract class D {} @@ -68,20 +69,21 @@ abstract class D {} library "[[@TEST_NAME]]"; -abstract class E; -// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: class E {} -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE-4]]:1: note: previously declared here +// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration // CHECK:STDERR: abstract class E; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: +abstract class E; class E {} // --- fail_abstract_to_base.carbon library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract class F; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: abstract class F; // CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE+6]]:1: error: class redeclared with different inheritance kind // CHECK:STDERR: base class F {} @@ -191,15 +193,15 @@ base class F {} // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: .C = %C.decl.loc8 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {} {} -// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %C.decl.loc8: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %C.decl.loc9: type = class_decl @C [template = constants.%C] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { -// CHECK:STDOUT: %.loc12: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc9: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C @@ -229,15 +231,15 @@ base class F {} // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .D = %D.decl.loc4 +// CHECK:STDOUT: .D = %D.decl.loc8 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %D.decl.loc4: type = class_decl @D [template = constants.%D] {} {} -// CHECK:STDOUT: %D.decl.loc12: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %D.decl.loc8: type = class_decl @D [template = constants.%D] {} {} +// CHECK:STDOUT: %D.decl.loc16: type = class_decl @D [template = constants.%D] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @D { -// CHECK:STDOUT: %.loc12: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc16: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D @@ -267,15 +269,15 @@ base class F {} // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .E = %E.decl.loc4 +// CHECK:STDOUT: .E = %E.decl.loc8 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %E.decl.loc4: type = class_decl @E [template = constants.%E] {} {} -// CHECK:STDOUT: %E.decl.loc12: type = class_decl @E [template = constants.%E] {} {} +// CHECK:STDOUT: %E.decl.loc8: type = class_decl @E [template = constants.%E] {} {} +// CHECK:STDOUT: %E.decl.loc9: type = class_decl @E [template = constants.%E] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @E { -// CHECK:STDOUT: %.loc12: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc9: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%E @@ -305,15 +307,15 @@ base class F {} // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .F = %F.decl.loc4 +// CHECK:STDOUT: .F = %F.decl.loc8 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %F.decl.loc4: type = class_decl @F [template = constants.%F] {} {} -// CHECK:STDOUT: %F.decl.loc11: type = class_decl @F [template = constants.%F] {} {} +// CHECK:STDOUT: %F.decl.loc8: type = class_decl @F [template = constants.%F] {} {} +// CHECK:STDOUT: %F.decl.loc15: type = class_decl @F [template = constants.%F] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @F { -// CHECK:STDOUT: %.loc11: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc15: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%F diff --git a/toolchain/check/testdata/class/redeclaration_introducer.carbon b/toolchain/check/testdata/class/redeclaration_introducer.carbon index 1ec4364bc483f..965d9bac66ee0 100644 --- a/toolchain/check/testdata/class/redeclaration_introducer.carbon +++ b/toolchain/check/testdata/class/redeclaration_introducer.carbon @@ -9,11 +9,32 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/redeclaration_introducer.carbon class A; +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: base class B; +// CHECK:STDERR: ^~~~ +// CHECK:STDERR: base class B; +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract class C; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: abstract class C; class A {} +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind +// CHECK:STDERR: base class B {} +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE-11]]:1: note: previously declared here +// CHECK:STDERR: base class B; +// CHECK:STDERR: ^~~~~~~~~~~~~ +// CHECK:STDERR: base class B {} +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+6]]:1: error: class redeclared with different inheritance kind +// CHECK:STDERR: abstract class C {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE-14]]:1: note: previously declared here +// CHECK:STDERR: abstract class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ abstract class C {} // CHECK:STDOUT: --- redeclaration_introducer.carbon @@ -43,34 +64,34 @@ abstract class C {} // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .A = %A.decl.loc11 -// CHECK:STDOUT: .B = %B.decl.loc12 -// CHECK:STDOUT: .C = %C.decl.loc13 +// CHECK:STDOUT: .B = %B.decl.loc16 +// CHECK:STDOUT: .C = %C.decl.loc21 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %A.decl.loc11: type = class_decl @A [template = constants.%A] {} {} -// CHECK:STDOUT: %B.decl.loc12: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: %C.decl.loc13: type = class_decl @C [template = constants.%C] {} {} -// CHECK:STDOUT: %A.decl.loc15: type = class_decl @A [template = constants.%A] {} {} // CHECK:STDOUT: %B.decl.loc16: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: %C.decl.loc17: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %C.decl.loc21: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %A.decl.loc23: type = class_decl @A [template = constants.%A] {} {} +// CHECK:STDOUT: %B.decl.loc31: type = class_decl @B [template = constants.%B] {} {} +// CHECK:STDOUT: %C.decl.loc38: type = class_decl @C [template = constants.%C] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @A { -// CHECK:STDOUT: %.loc15: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc23: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%A // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { -// CHECK:STDOUT: %.loc16: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc31: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { -// CHECK:STDOUT: %.loc17: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc38: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C From af590516240b76a1d434974151df04fe88e3d0f7 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 7 Oct 2024 23:15:32 +0000 Subject: [PATCH 3/9] Remove dead test coverage --- toolchain/check/handle_class.cpp | 13 - .../fail_redeclaration_introducer.carbon | 323 ------------------ .../class/redeclaration_introducer.carbon | 43 +-- toolchain/diagnostics/diagnostic_kind.def | 2 - 4 files changed, 11 insertions(+), 370 deletions(-) delete mode 100644 toolchain/check/testdata/class/fail_redeclaration_introducer.carbon diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 942e40216518f..def0cf1a38fe3 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -79,19 +79,6 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc, return false; } - // The introducer kind must match the previous declaration. - // TODO: The rule here is not yet decided. See #3384. - if (prev_class.inheritance_kind != new_class.inheritance_kind) { - CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducer, Error, - "class redeclared with different inheritance kind"); - CARBON_DIAGNOSTIC(ClassRedeclarationDifferentIntroducerPrevious, Note, - "previously declared here"); - context.emitter() - .Build(new_loc, ClassRedeclarationDifferentIntroducer) - .Note(prev_loc, ClassRedeclarationDifferentIntroducerPrevious) - .Emit(); - } - if (new_is_definition) { prev_class.MergeDefinition(new_class); prev_class.scope_id = new_class.scope_id; diff --git a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon b/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon deleted file mode 100644 index 9ffa7a648cdd5..0000000000000 --- a/toolchain/check/testdata/class/fail_redeclaration_introducer.carbon +++ /dev/null @@ -1,323 +0,0 @@ -// 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/fail_redeclaration_introducer.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_redeclaration_introducer.carbon - -// --- fail_add_base.carbon - -library "[[@TEST_NAME]]"; - -class A; -// CHECK:STDERR: fail_add_base.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: base class A {} -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_add_base.carbon:[[@LINE-4]]:1: note: previously declared here -// CHECK:STDERR: class A; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -base class A {} - -// --- fail_add_abstract.carbon - -library "[[@TEST_NAME]]"; - -class B; -// CHECK:STDERR: fail_add_abstract.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: abstract class B {} -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_add_abstract.carbon:[[@LINE-4]]:1: note: previously declared here -// CHECK:STDERR: class B; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -abstract class B {} - -// --- fail_remove_base.carbon - -library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_remove_base.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration -// CHECK:STDERR: base class C; -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: -base class C; -class C {} - -// --- fail_base_to_abstract.carbon - -library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration -// CHECK:STDERR: base class D; -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: -base class D; -// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: abstract class D {} -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_base_to_abstract.carbon:[[@LINE-4]]:1: note: previously declared here -// CHECK:STDERR: base class D; -// CHECK:STDERR: ^~~~~~~~~~~~~ -// CHECK:STDERR: -abstract class D {} - -// --- fail_remove_abstract.carbon - -library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_remove_abstract.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: abstract class E; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -abstract class E; -class E {} - -// --- fail_abstract_to_base.carbon - -library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: abstract class F; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -abstract class F; -// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE+6]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: base class F {} -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_abstract_to_base.carbon:[[@LINE-4]]:1: note: previously declared here -// CHECK:STDERR: abstract class F; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -base class F {} - -// CHECK:STDOUT: --- fail_add_base.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %A: type = class_type @A [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .A = %A.decl.loc4 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %A.decl.loc4: type = class_decl @A [template = constants.%A] {} {} -// CHECK:STDOUT: %A.decl.loc12: type = class_decl @A [template = constants.%A] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @A { -// CHECK:STDOUT: %.loc12: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%A -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_add_abstract.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %B: type = class_type @B [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .B = %B.decl.loc4 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %B.decl.loc4: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: %B.decl.loc12: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @B { -// CHECK:STDOUT: %.loc12: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%B -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_remove_base.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .C = %C.decl.loc8 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %C.decl.loc8: type = class_decl @C [template = constants.%C] {} {} -// CHECK:STDOUT: %C.decl.loc9: type = class_decl @C [template = constants.%C] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: %.loc9: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_base_to_abstract.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %D: type = class_type @D [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .D = %D.decl.loc8 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %D.decl.loc8: type = class_decl @D [template = constants.%D] {} {} -// CHECK:STDOUT: %D.decl.loc16: type = class_decl @D [template = constants.%D] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @D { -// CHECK:STDOUT: %.loc16: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%D -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_remove_abstract.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %E: type = class_type @E [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .E = %E.decl.loc8 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %E.decl.loc8: type = class_decl @E [template = constants.%E] {} {} -// CHECK:STDOUT: %E.decl.loc9: type = class_decl @E [template = constants.%E] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @E { -// CHECK:STDOUT: %.loc9: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%E -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_abstract_to_base.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %F: type = class_type @F [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%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/as -// 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: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .F = %F.decl.loc8 -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %F.decl.loc8: type = class_decl @F [template = constants.%F] {} {} -// CHECK:STDOUT: %F.decl.loc15: type = class_decl @F [template = constants.%F] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @F { -// CHECK:STDOUT: %.loc15: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%F -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/redeclaration_introducer.carbon b/toolchain/check/testdata/class/redeclaration_introducer.carbon index 965d9bac66ee0..614b6ce466c0a 100644 --- a/toolchain/check/testdata/class/redeclaration_introducer.carbon +++ b/toolchain/check/testdata/class/redeclaration_introducer.carbon @@ -9,32 +9,11 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/redeclaration_introducer.carbon class A; -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration -// CHECK:STDERR: base class B; -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: -base class B; -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: abstract class C; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -abstract class C; +class B; +class C; class A {} -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+7]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: base class B {} -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE-11]]:1: note: previously declared here -// CHECK:STDERR: base class B; -// CHECK:STDERR: ^~~~~~~~~~~~~ -// CHECK:STDERR: base class B {} -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE+6]]:1: error: class redeclared with different inheritance kind -// CHECK:STDERR: abstract class C {} -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: redeclaration_introducer.carbon:[[@LINE-14]]:1: note: previously declared here -// CHECK:STDERR: abstract class C; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ abstract class C {} // CHECK:STDOUT: --- redeclaration_introducer.carbon @@ -64,34 +43,34 @@ abstract class C {} // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .A = %A.decl.loc11 -// CHECK:STDOUT: .B = %B.decl.loc16 -// CHECK:STDOUT: .C = %C.decl.loc21 +// CHECK:STDOUT: .B = %B.decl.loc12 +// CHECK:STDOUT: .C = %C.decl.loc13 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %A.decl.loc11: type = class_decl @A [template = constants.%A] {} {} +// CHECK:STDOUT: %B.decl.loc12: type = class_decl @B [template = constants.%B] {} {} +// CHECK:STDOUT: %C.decl.loc13: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %A.decl.loc15: type = class_decl @A [template = constants.%A] {} {} // CHECK:STDOUT: %B.decl.loc16: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: %C.decl.loc21: type = class_decl @C [template = constants.%C] {} {} -// CHECK:STDOUT: %A.decl.loc23: type = class_decl @A [template = constants.%A] {} {} -// CHECK:STDOUT: %B.decl.loc31: type = class_decl @B [template = constants.%B] {} {} -// CHECK:STDOUT: %C.decl.loc38: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %C.decl.loc17: type = class_decl @C [template = constants.%C] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @A { -// CHECK:STDOUT: %.loc23: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc15: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%A // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { -// CHECK:STDOUT: %.loc31: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc16: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { -// CHECK:STDOUT: %.loc38: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc17: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index a134c0054123f..4d8fb15fd3f91 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -216,8 +216,6 @@ CARBON_DIAGNOSTIC_KIND(BaseDeclRepeated) CARBON_DIAGNOSTIC_KIND(BaseIsFinal) CARBON_DIAGNOSTIC_KIND(BaseMissingExtend) CARBON_DIAGNOSTIC_KIND(ClassForwardDeclaredHere) -CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducer) -CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducerPrevious) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclOutsideClass) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclPrevious) CARBON_DIAGNOSTIC_KIND(ClassIncompleteWithinDefinition) From 964be4f03d91301ba44a72f8e9dd3411eea17f95 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 9 Oct 2024 19:45:30 +0000 Subject: [PATCH 4/9] Separate out some test cases Also add definitions to cases where the decl/def distinction isn't needed, and the decl case is invalid for other reasons that are tested separately. --- .../testdata/class/fail_modifiers.carbon | 85 +++++++++++-------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index e86eb8075252a..168745c147328 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -8,40 +8,44 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_modifiers.carbon -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:9: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: private abstract private class DuplicatePrivate; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:18: error: `private` repeated on declaration -// CHECK:STDERR: private abstract private class DuplicatePrivate; -// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: error: `private` repeated on declaration +// CHECK:STDERR: private private class DuplicatePrivate; +// CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `private` previously appeared here -// CHECK:STDERR: private abstract private class DuplicatePrivate; +// CHECK:STDERR: private private class DuplicatePrivate; // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: -private abstract private class DuplicatePrivate; +private private class DuplicatePrivate; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:14: error: `protected` not allowed on declaration with `private` -// CHECK:STDERR: private base protected class TwoAccess {} -// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: abstract class AbstractDecl; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: +abstract class AbstractDecl; + +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: error: `protected` not allowed on declaration with `private` +// CHECK:STDERR: private protected class TwoAccess; +// CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `private` previously appeared here -// CHECK:STDERR: private base protected class TwoAccess {} +// CHECK:STDERR: private protected class TwoAccess; // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: -private base protected class TwoAccess {} +private protected class TwoAccess; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: abstract abstract class TwoAbstract; -// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: base class BaseDecl; +// CHECK:STDERR: ^~~~ // CHECK:STDERR: +base class BaseDecl; + // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `abstract` repeated on declaration -// CHECK:STDERR: abstract abstract class TwoAbstract; +// CHECK:STDERR: abstract abstract class TwoAbstract { } // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `abstract` previously appeared here -// CHECK:STDERR: abstract abstract class TwoAbstract; +// CHECK:STDERR: abstract abstract class TwoAbstract { } // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: -abstract abstract class TwoAbstract; +abstract abstract class TwoAbstract { } // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+15]]:1: error: `protected` not allowed on `class` declaration at file scope, `protected` is only allowed on class members // CHECK:STDERR: protected virtual base class Virtual {} @@ -60,18 +64,14 @@ abstract abstract class TwoAbstract; // CHECK:STDERR: protected virtual base class Virtual {} -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: error: `abstract` not allowed on `class` declaration -// CHECK:STDERR: abstract protected class WrongOrder; -// CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `protected` must appear before `abstract` -// CHECK:STDERR: abstract protected class WrongOrder; +// CHECK:STDERR: abstract protected class WrongOrder { } // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `abstract` previously appeared here -// CHECK:STDERR: abstract protected class WrongOrder; +// CHECK:STDERR: abstract protected class WrongOrder { } // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: -abstract protected class WrongOrder; +abstract protected class WrongOrder { } // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `base` not allowed on declaration with `abstract` // CHECK:STDERR: abstract base class AbstractAndBase {} @@ -100,10 +100,12 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %DuplicatePrivate: type = class_type @DuplicatePrivate [template] +// CHECK:STDOUT: %AbstractDecl: type = class_type @AbstractDecl [template] // CHECK:STDOUT: %TwoAccess: type = class_type @TwoAccess [template] +// CHECK:STDOUT: %BaseDecl: type = class_type @BaseDecl [template] +// CHECK:STDOUT: %TwoAbstract: type = class_type @TwoAbstract [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %TwoAbstract: type = class_type @TwoAbstract [template] // CHECK:STDOUT: %Virtual: type = class_type @Virtual [template] // CHECK:STDOUT: %WrongOrder: type = class_type @WrongOrder [template] // CHECK:STDOUT: %AbstractAndBase: type = class_type @AbstractAndBase [template] @@ -132,7 +134,9 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .DuplicatePrivate [private] = %DuplicatePrivate.decl +// CHECK:STDOUT: .AbstractDecl = %AbstractDecl.decl // CHECK:STDOUT: .TwoAccess [private] = %TwoAccess.decl +// CHECK:STDOUT: .BaseDecl = %BaseDecl.decl // CHECK:STDOUT: .TwoAbstract = %TwoAbstract.decl // CHECK:STDOUT: .Virtual = %Virtual.decl // CHECK:STDOUT: .WrongOrder = %WrongOrder.decl @@ -141,7 +145,9 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %DuplicatePrivate.decl: type = class_decl @DuplicatePrivate [template = constants.%DuplicatePrivate] {} {} +// CHECK:STDOUT: %AbstractDecl.decl: type = class_decl @AbstractDecl [template = constants.%AbstractDecl] {} {} // CHECK:STDOUT: %TwoAccess.decl: type = class_decl @TwoAccess [template = constants.%TwoAccess] {} {} +// CHECK:STDOUT: %BaseDecl.decl: type = class_decl @BaseDecl [template = constants.%BaseDecl] {} {} // CHECK:STDOUT: %TwoAbstract.decl: type = class_decl @TwoAbstract [template = constants.%TwoAbstract] {} {} // CHECK:STDOUT: %Virtual.decl: type = class_decl @Virtual [template = constants.%Virtual] {} {} // CHECK:STDOUT: %WrongOrder.decl: type = class_decl @WrongOrder [template = constants.%WrongOrder] {} {} @@ -152,23 +158,32 @@ fn AbstractWithDefinition.G() { // CHECK:STDOUT: // CHECK:STDOUT: class @DuplicatePrivate; // CHECK:STDOUT: -// CHECK:STDOUT: class @TwoAccess { -// CHECK:STDOUT: %.loc31: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: class @AbstractDecl; +// CHECK:STDOUT: +// CHECK:STDOUT: class @TwoAccess; +// CHECK:STDOUT: +// CHECK:STDOUT: class @BaseDecl; +// CHECK:STDOUT: +// CHECK:STDOUT: class @TwoAbstract { +// CHECK:STDOUT: %.loc48: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%TwoAccess +// CHECK:STDOUT: .Self = constants.%TwoAbstract // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @TwoAbstract; -// CHECK:STDOUT: // CHECK:STDOUT: class @Virtual { -// CHECK:STDOUT: %.loc61: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc65: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Virtual // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @WrongOrder; +// CHECK:STDOUT: class @WrongOrder { +// CHECK:STDOUT: %.loc74: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%WrongOrder +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @AbstractAndBase { // CHECK:STDOUT: %.loc83: = complete_type_witness %.1 [template = constants.%.2] From 068c7ec66e2cc509775be2418fde4d5b1688dd8c Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 9 Oct 2024 22:42:00 +0000 Subject: [PATCH 5/9] Rephrase the warning for modifiers that would be acceptable on definitions, but not declarations --- toolchain/check/handle_class.cpp | 11 +++++--- toolchain/check/modifiers.cpp | 24 ++++++++++++++---- toolchain/check/modifiers.h | 25 +++++++++++++++---- .../check/testdata/class/fail_abstract.carbon | 2 +- .../testdata/class/fail_base_bad_type.carbon | 2 +- .../testdata/class/fail_modifiers.carbon | 4 +-- toolchain/diagnostics/diagnostic_kind.def | 1 + 7 files changed, 51 insertions(+), 18 deletions(-) diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index def0cf1a38fe3..62e0a9dd2558c 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -181,10 +181,13 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, auto introducer = context.decl_introducer_state_stack().Pop(); CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); - LimitModifiersOnDecl(context, introducer, - KeywordModifierSet::Access | KeywordModifierSet::Extern | - (is_definition ? KeywordModifierSet::Class - : KeywordModifierSet::None)); + auto accepted_modifiers = + KeywordModifierSet::Access | KeywordModifierSet::Extern; + auto invalid_unless_definition_modifiers = KeywordModifierSet::None; + (is_definition ? accepted_modifiers : invalid_unless_definition_modifiers) |= + KeywordModifierSet::Class; + LimitModifiersOnDecl(context, introducer, accepted_modifiers, + invalid_unless_definition_modifiers); RestrictExternModifierOnDecl(context, introducer, parent_scope_inst, is_definition); diff --git a/toolchain/check/modifiers.cpp b/toolchain/check/modifiers.cpp index e53836fb310ec..a405b90130b5d 100644 --- a/toolchain/check/modifiers.cpp +++ b/toolchain/check/modifiers.cpp @@ -9,15 +9,22 @@ namespace Carbon::Check { static auto DiagnoseNotAllowed(Context& context, Parse::NodeId modifier_node, + bool allowed_in_definition, Lex::TokenKind decl_kind, llvm::StringRef context_string, SemIR::LocId context_loc_id) -> void { CARBON_DIAGNOSTIC(ModifierNotAllowedOn, Error, "`{0}` not allowed on `{1}` declaration{2}", Lex::TokenKind, Lex::TokenKind, std::string); - auto diag = context.emitter().Build(modifier_node, ModifierNotAllowedOn, - context.token_kind(modifier_node), - decl_kind, context_string.str()); + CARBON_DIAGNOSTIC( + ModifierNotAllowedOnDeclOnly, Error, + "`{0}` not allowed on `{1}` declaration, only definition{2}", + Lex::TokenKind, Lex::TokenKind, std::string); + auto diag = context.emitter().Build( + modifier_node, + allowed_in_definition ? ModifierNotAllowedOnDeclOnly + : ModifierNotAllowedOn, + context.token_kind(modifier_node), decl_kind, context_string.str()); if (context_loc_id.is_valid()) { CARBON_DIAGNOSTIC(ModifierNotInContext, Note, "containing definition here"); diag.Note(context_loc_id, ModifierNotInContext); @@ -39,8 +46,12 @@ static auto ModifierOrderAsSet(ModifierOrder order) -> KeywordModifierSet { auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, KeywordModifierSet forbidden, + KeywordModifierSet allowed_on_definition, llvm::StringRef context_string, SemIR::LocId context_loc_id) -> void { + CARBON_CHECK((allowed_on_definition & ~forbidden).empty(), + "allowed_on_definition modifiers must only be a subset of those " + "already forbidden"); auto not_allowed = introducer.modifier_set & forbidden; if (not_allowed.empty()) { return; @@ -50,8 +61,10 @@ auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, order_index <= static_cast(ModifierOrder::Last); ++order_index) { auto order = static_cast(order_index); if (not_allowed.HasAnyOf(ModifierOrderAsSet(order))) { - DiagnoseNotAllowed(context, introducer.modifier_node_id(order), - introducer.kind, context_string, context_loc_id); + DiagnoseNotAllowed( + context, introducer.modifier_node_id(order), + allowed_on_definition.HasAnyOf(ModifierOrderAsSet(order)), + introducer.kind, context_string, context_loc_id); introducer.set_modifier_node_id(order, Parse::NodeId::Invalid); } } @@ -71,6 +84,7 @@ auto CheckAccessModifiersOnDecl(Context& context, // scope. ForbidModifiersOnDecl( context, introducer, KeywordModifierSet::Protected, + KeywordModifierSet::None, " at file scope, `protected` is only allowed on class members"); return; } diff --git a/toolchain/check/modifiers.h b/toolchain/check/modifiers.h index fef07c00b0fcd..2b4b61950d22a 100644 --- a/toolchain/check/modifiers.h +++ b/toolchain/check/modifiers.h @@ -30,20 +30,35 @@ auto CheckMethodModifiersOnFunction( // Like `LimitModifiersOnDecl`, except says which modifiers are forbidden, and a // `context_string` (and optional `context_loc_id`) specifying the context in -// which those modifiers are forbidden. +// which those modifiers are forbidden. `allowed_on_definition` specifies +// modifiers that are forbidden, but would be valid if the declaration was a +// definition. // TODO: Take another look at diagnostic phrasing for callers. auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, KeywordModifierSet forbidden, + KeywordModifierSet allowed_on_definition, llvm::StringRef context_string, SemIR::LocId context_loc_id = SemIR::LocId::Invalid) -> void; +inline auto ForbidModifiersOnDecl( + Context& context, DeclIntroducerState& introducer, + KeywordModifierSet forbidden, llvm::StringRef context_string, + SemIR::LocId context_loc_id = SemIR::LocId::Invalid) -> void { + ForbidModifiersOnDecl(context, introducer, forbidden, + KeywordModifierSet::None, context_string, + context_loc_id); +} + // Reports a diagnostic (using `decl_kind`) if modifiers on this declaration are // not in `allowed`. Updates `introducer`. -inline auto LimitModifiersOnDecl(Context& context, - DeclIntroducerState& introducer, - KeywordModifierSet allowed) -> void { - ForbidModifiersOnDecl(context, introducer, ~allowed, ""); +inline auto LimitModifiersOnDecl( + Context& context, DeclIntroducerState& introducer, + KeywordModifierSet allowed, + KeywordModifierSet allowed_on_definition = KeywordModifierSet::None) + -> void { + ForbidModifiersOnDecl(context, introducer, ~allowed, allowed_on_definition, + ""); } // Restricts the `extern` modifier to only be used on namespace-scoped diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index b689787cfbf7d..dcbb6dbbf1942 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -31,7 +31,7 @@ fn Access(d: Derived) -> (i32, i32) { return (d.d, d.base.a); } -// CHECK:STDERR: fail_abstract.carbon:[[@LINE+3]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: fail_abstract.carbon:[[@LINE+3]]:1: error: `abstract` not allowed on `class` declaration, only definition // CHECK:STDERR: abstract class AbstractDecl; // CHECK:STDERR: ^~~~~~~~ abstract class AbstractDecl; diff --git a/toolchain/check/testdata/class/fail_base_bad_type.carbon b/toolchain/check/testdata/class/fail_base_bad_type.carbon index d5d5fddf418f0..873debf1e4d10 100644 --- a/toolchain/check/testdata/class/fail_base_bad_type.carbon +++ b/toolchain/check/testdata/class/fail_base_bad_type.carbon @@ -99,7 +99,7 @@ fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return // It would be OK to reject this if we start actually looking in the struct type. fn AccessMemberWithInvalidBaseStruct(p: DeriveFromStruct*) -> i32 { return (*p).n; } -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration, only definition // CHECK:STDERR: base class Incomplete; // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index 168745c147328..7070dd7d4518f 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -17,7 +17,7 @@ // CHECK:STDERR: private private class DuplicatePrivate; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` declaration, only definition // CHECK:STDERR: abstract class AbstractDecl; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -32,7 +32,7 @@ abstract class AbstractDecl; // CHECK:STDERR: private protected class TwoAccess; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration, only definition // CHECK:STDERR: base class BaseDecl; // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 4d8fb15fd3f91..f1efb990855ec 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -353,6 +353,7 @@ CARBON_DIAGNOSTIC_KIND(UseOfNonExprAsValue) CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedOn) CARBON_DIAGNOSTIC_KIND(ModifierNotInContext) CARBON_DIAGNOSTIC_KIND(ModifierRepeated) +CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedOnDeclOnly) CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedWith) CARBON_DIAGNOSTIC_KIND(ModifierMustAppearBefore) CARBON_DIAGNOSTIC_KIND(ModifierPrevious) From 854694fb8974ce7be2352fd8d4ea646356367e10 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 10 Oct 2024 00:00:29 +0000 Subject: [PATCH 6/9] Simplify the implementation of the decl-only-on-def modifier diagnostic --- toolchain/check/handle_class.cpp | 15 ++++++----- toolchain/check/modifiers.cpp | 24 ++++-------------- toolchain/check/modifiers.h | 31 ++++++++--------------- toolchain/diagnostics/diagnostic_kind.def | 1 - 4 files changed, 24 insertions(+), 47 deletions(-) diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 62e0a9dd2558c..75145bf9c4320 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -181,13 +181,14 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, auto introducer = context.decl_introducer_state_stack().Pop(); CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); - auto accepted_modifiers = - KeywordModifierSet::Access | KeywordModifierSet::Extern; - auto invalid_unless_definition_modifiers = KeywordModifierSet::None; - (is_definition ? accepted_modifiers : invalid_unless_definition_modifiers) |= - KeywordModifierSet::Class; - LimitModifiersOnDecl(context, introducer, accepted_modifiers, - invalid_unless_definition_modifiers); + LimitModifiersOnDecl(context, introducer, + KeywordModifierSet::Access | KeywordModifierSet::Extern | + KeywordModifierSet::Class); + if (!is_definition) { + LimitModifiersOnNotDefinition( + context, introducer, + KeywordModifierSet::Access | KeywordModifierSet::Extern); + } RestrictExternModifierOnDecl(context, introducer, parent_scope_inst, is_definition); diff --git a/toolchain/check/modifiers.cpp b/toolchain/check/modifiers.cpp index a405b90130b5d..e53836fb310ec 100644 --- a/toolchain/check/modifiers.cpp +++ b/toolchain/check/modifiers.cpp @@ -9,22 +9,15 @@ namespace Carbon::Check { static auto DiagnoseNotAllowed(Context& context, Parse::NodeId modifier_node, - bool allowed_in_definition, Lex::TokenKind decl_kind, llvm::StringRef context_string, SemIR::LocId context_loc_id) -> void { CARBON_DIAGNOSTIC(ModifierNotAllowedOn, Error, "`{0}` not allowed on `{1}` declaration{2}", Lex::TokenKind, Lex::TokenKind, std::string); - CARBON_DIAGNOSTIC( - ModifierNotAllowedOnDeclOnly, Error, - "`{0}` not allowed on `{1}` declaration, only definition{2}", - Lex::TokenKind, Lex::TokenKind, std::string); - auto diag = context.emitter().Build( - modifier_node, - allowed_in_definition ? ModifierNotAllowedOnDeclOnly - : ModifierNotAllowedOn, - context.token_kind(modifier_node), decl_kind, context_string.str()); + auto diag = context.emitter().Build(modifier_node, ModifierNotAllowedOn, + context.token_kind(modifier_node), + decl_kind, context_string.str()); if (context_loc_id.is_valid()) { CARBON_DIAGNOSTIC(ModifierNotInContext, Note, "containing definition here"); diag.Note(context_loc_id, ModifierNotInContext); @@ -46,12 +39,8 @@ static auto ModifierOrderAsSet(ModifierOrder order) -> KeywordModifierSet { auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, KeywordModifierSet forbidden, - KeywordModifierSet allowed_on_definition, llvm::StringRef context_string, SemIR::LocId context_loc_id) -> void { - CARBON_CHECK((allowed_on_definition & ~forbidden).empty(), - "allowed_on_definition modifiers must only be a subset of those " - "already forbidden"); auto not_allowed = introducer.modifier_set & forbidden; if (not_allowed.empty()) { return; @@ -61,10 +50,8 @@ auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, order_index <= static_cast(ModifierOrder::Last); ++order_index) { auto order = static_cast(order_index); if (not_allowed.HasAnyOf(ModifierOrderAsSet(order))) { - DiagnoseNotAllowed( - context, introducer.modifier_node_id(order), - allowed_on_definition.HasAnyOf(ModifierOrderAsSet(order)), - introducer.kind, context_string, context_loc_id); + DiagnoseNotAllowed(context, introducer.modifier_node_id(order), + introducer.kind, context_string, context_loc_id); introducer.set_modifier_node_id(order, Parse::NodeId::Invalid); } } @@ -84,7 +71,6 @@ auto CheckAccessModifiersOnDecl(Context& context, // scope. ForbidModifiersOnDecl( context, introducer, KeywordModifierSet::Protected, - KeywordModifierSet::None, " at file scope, `protected` is only allowed on class members"); return; } diff --git a/toolchain/check/modifiers.h b/toolchain/check/modifiers.h index 2b4b61950d22a..c9921f12a8593 100644 --- a/toolchain/check/modifiers.h +++ b/toolchain/check/modifiers.h @@ -30,35 +30,26 @@ auto CheckMethodModifiersOnFunction( // Like `LimitModifiersOnDecl`, except says which modifiers are forbidden, and a // `context_string` (and optional `context_loc_id`) specifying the context in -// which those modifiers are forbidden. `allowed_on_definition` specifies -// modifiers that are forbidden, but would be valid if the declaration was a -// definition. +// which those modifiers are forbidden. // TODO: Take another look at diagnostic phrasing for callers. auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer, KeywordModifierSet forbidden, - KeywordModifierSet allowed_on_definition, llvm::StringRef context_string, SemIR::LocId context_loc_id = SemIR::LocId::Invalid) -> void; -inline auto ForbidModifiersOnDecl( - Context& context, DeclIntroducerState& introducer, - KeywordModifierSet forbidden, llvm::StringRef context_string, - SemIR::LocId context_loc_id = SemIR::LocId::Invalid) -> void { - ForbidModifiersOnDecl(context, introducer, forbidden, - KeywordModifierSet::None, context_string, - context_loc_id); -} - // Reports a diagnostic (using `decl_kind`) if modifiers on this declaration are // not in `allowed`. Updates `introducer`. -inline auto LimitModifiersOnDecl( - Context& context, DeclIntroducerState& introducer, - KeywordModifierSet allowed, - KeywordModifierSet allowed_on_definition = KeywordModifierSet::None) - -> void { - ForbidModifiersOnDecl(context, introducer, ~allowed, allowed_on_definition, - ""); +inline auto LimitModifiersOnDecl(Context& context, + DeclIntroducerState& introducer, + KeywordModifierSet allowed) -> void { + ForbidModifiersOnDecl(context, introducer, ~allowed, ""); +} + +inline auto LimitModifiersOnNotDefinition(Context& context, + DeclIntroducerState& introducer, + KeywordModifierSet allowed) -> void { + ForbidModifiersOnDecl(context, introducer, ~allowed, ", only definition"); } // Restricts the `extern` modifier to only be used on namespace-scoped diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index f1efb990855ec..4d8fb15fd3f91 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -353,7 +353,6 @@ CARBON_DIAGNOSTIC_KIND(UseOfNonExprAsValue) CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedOn) CARBON_DIAGNOSTIC_KIND(ModifierNotInContext) CARBON_DIAGNOSTIC_KIND(ModifierRepeated) -CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedOnDeclOnly) CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedWith) CARBON_DIAGNOSTIC_KIND(ModifierMustAppearBefore) CARBON_DIAGNOSTIC_KIND(ModifierPrevious) From 49a27a782f93c4f71679cf334a8d9f00934f2bdf Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 10 Oct 2024 00:16:58 +0000 Subject: [PATCH 7/9] Add file splitting to some tests --- .../check/testdata/class/fail_abstract.carbon | 244 ++- .../testdata/class/fail_base_bad_type.carbon | 1503 +++++++++++------ 2 files changed, 1169 insertions(+), 578 deletions(-) diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index dcbb6dbbf1942..b1ebd03c374e5 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -8,6 +8,8 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_abstract.carbon + +// --- fail_rejects_valid_abstract_subobject_construction.carbon abstract class Abstract { var a: i32; } @@ -20,23 +22,39 @@ class Derived { fn Make() -> Derived { // TODO: This should be valid, and should construct an instance of `partial Abstract` as the base. - // CHECK:STDERR: fail_abstract.carbon:[[@LINE+4]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead + // CHECK:STDERR: fail_rejects_valid_abstract_subobject_construction.carbon:[[@LINE+8]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: + // CHECK:STDERR: base_abstract_subobject_access.carbon: error: `Main//default` previously provided by `fail_rejects_valid_abstract_subobject_construction.carbon` + // CHECK:STDERR: + // CHECK:STDERR: fail_abstract_decl.carbon: error: `Main//default` previously provided by `fail_rejects_valid_abstract_subobject_construction.carbon` + // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; } +// --- base_abstract_subobject_access.carbon +abstract class Abstract { + var a: i32; +} + +class Derived { + extend base: Abstract; + + var d: i32; +} + fn Access(d: Derived) -> (i32, i32) { return (d.d, d.base.a); } -// CHECK:STDERR: fail_abstract.carbon:[[@LINE+3]]:1: error: `abstract` not allowed on `class` declaration, only definition +// --- fail_abstract_decl.carbon +// CHECK:STDERR: fail_abstract_decl.carbon:[[@LINE+3]]:1: error: `abstract` not allowed on `class` declaration, only definition // CHECK:STDERR: abstract class AbstractDecl; // CHECK:STDERR: ^~~~~~~~ abstract class AbstractDecl; -// CHECK:STDOUT: --- fail_abstract.carbon +// CHECK:STDOUT: --- fail_rejects_valid_abstract_subobject_construction.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %Abstract: type = class_type @Abstract [template] @@ -60,12 +78,6 @@ abstract class AbstractDecl; // CHECK:STDOUT: %.13: i32 = int_literal 1 [template] // CHECK:STDOUT: %.14: i32 = int_literal 7 [template] // CHECK:STDOUT: %.15: type = struct_type {.base: %.3, .d: i32} [template] -// CHECK:STDOUT: %.16: type = tuple_type (type, type) [template] -// CHECK:STDOUT: %.17: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %Access.type: type = fn_type @Access [template] -// CHECK:STDOUT: %Access: %Access.type = struct_value () [template] -// CHECK:STDOUT: %.18: type = ptr_type %.17 [template] -// CHECK:STDOUT: %AbstractDecl: type = class_type @AbstractDecl [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -89,8 +101,6 @@ abstract class AbstractDecl; // CHECK:STDOUT: .Abstract = %Abstract.decl // CHECK:STDOUT: .Derived = %Derived.decl // CHECK:STDOUT: .Make = %Make.decl -// CHECK:STDOUT: .Access = %Access.decl -// CHECK:STDOUT: .AbstractDecl = %AbstractDecl.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %Abstract.decl: type = class_decl @Abstract [template = constants.%Abstract] {} {} @@ -99,86 +109,196 @@ abstract class AbstractDecl; // CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived] // CHECK:STDOUT: %return: ref %Derived = var // CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Abstract { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc2_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_10.2: type = converted %int.make_type_32, %.loc2_10.1 [template = i32] +// CHECK:STDOUT: %.loc2_8: %.2 = field_decl a, element0 [template] +// CHECK:STDOUT: %.loc3: = complete_type_witness %.3 [template = constants.%.4] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Abstract +// CHECK:STDOUT: .a = %.loc2_8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract] +// CHECK:STDOUT: %.loc6: %.6 = base_decl %Abstract, element0 [template] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_10.2: type = converted %int.make_type_32, %.loc8_10.1 [template = i32] +// CHECK:STDOUT: %.loc8_8: %.7 = field_decl d, element1 [template] +// CHECK:STDOUT: %.loc9: = complete_type_witness %.8 [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .base = %.loc6 +// CHECK:STDOUT: .d = %.loc8_8 +// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Make() -> %return: %Derived { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc21_25: i32 = int_literal 1 [template = constants.%.13] +// CHECK:STDOUT: %.loc21_26: %.3 = struct_literal (%.loc21_25) +// CHECK:STDOUT: %.loc21_34: i32 = int_literal 7 [template = constants.%.14] +// CHECK:STDOUT: %.loc21_35: %.15 = struct_literal (%.loc21_26, %.loc21_34) +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- base_abstract_subobject_access.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Abstract: type = class_type @Abstract [template] +// 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: %.2: type = unbound_element_type %Abstract, i32 [template] +// CHECK:STDOUT: %.3: type = struct_type {.a: i32} [template] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [template] +// CHECK:STDOUT: %Derived: type = class_type @Derived [template] +// CHECK:STDOUT: %.5: type = ptr_type %.3 [template] +// CHECK:STDOUT: %.6: type = unbound_element_type %Derived, %Abstract [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %Derived, i32 [template] +// CHECK:STDOUT: %.8: type = struct_type {.base: %Abstract, .d: i32} [template] +// CHECK:STDOUT: %.9: = complete_type_witness %.8 [template] +// CHECK:STDOUT: %.10: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.11: type = tuple_type (i32, i32) [template] +// CHECK:STDOUT: %Access.type: type = fn_type @Access [template] +// CHECK:STDOUT: %Access: %Access.type = struct_value () [template] +// CHECK:STDOUT: %.12: type = ptr_type %.11 [template] +// CHECK:STDOUT: %.13: type = struct_type {.base: %.5, .d: i32} [template] +// CHECK:STDOUT: %.14: type = ptr_type %.13 [template] +// CHECK:STDOUT: %.15: type = ptr_type %.8 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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/as +// 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: %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 = imports.%Core +// CHECK:STDOUT: .Abstract = %Abstract.decl +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .Access = %Access.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Abstract.decl: type = class_decl @Abstract [template = constants.%Abstract] {} {} +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [template = constants.%Derived] {} {} // CHECK:STDOUT: %Access.decl: %Access.type = fn_decl @Access [template = constants.%Access] { // CHECK:STDOUT: %d.patt: %Derived = binding_pattern d // CHECK:STDOUT: } { // CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived] // CHECK:STDOUT: %d.param: %Derived = param d, runtime_param0 // CHECK:STDOUT: %d: %Derived = bind_name d, %d.param -// CHECK:STDOUT: %int.make_type_32.loc30_27: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc30_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc30_35.1: %.16 = tuple_literal (%int.make_type_32.loc30_27, %int.make_type_32.loc30_32) -// CHECK:STDOUT: %.loc30_35.2: type = value_of_initializer %int.make_type_32.loc30_27 [template = i32] -// CHECK:STDOUT: %.loc30_35.3: type = converted %int.make_type_32.loc30_27, %.loc30_35.2 [template = i32] -// CHECK:STDOUT: %.loc30_35.4: type = value_of_initializer %int.make_type_32.loc30_32 [template = i32] -// CHECK:STDOUT: %.loc30_35.5: type = converted %int.make_type_32.loc30_32, %.loc30_35.4 [template = i32] -// CHECK:STDOUT: %.loc30_35.6: type = converted %.loc30_35.1, constants.%.17 [template = constants.%.17] -// CHECK:STDOUT: %return: ref %.17 = var +// CHECK:STDOUT: %int.make_type_32.loc11_27: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc11_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc11_35.1: %.10 = tuple_literal (%int.make_type_32.loc11_27, %int.make_type_32.loc11_32) +// CHECK:STDOUT: %.loc11_35.2: type = value_of_initializer %int.make_type_32.loc11_27 [template = i32] +// CHECK:STDOUT: %.loc11_35.3: type = converted %int.make_type_32.loc11_27, %.loc11_35.2 [template = i32] +// CHECK:STDOUT: %.loc11_35.4: type = value_of_initializer %int.make_type_32.loc11_32 [template = i32] +// CHECK:STDOUT: %.loc11_35.5: type = converted %int.make_type_32.loc11_32, %.loc11_35.4 [template = i32] +// CHECK:STDOUT: %.loc11_35.6: type = converted %.loc11_35.1, constants.%.11 [template = constants.%.11] +// CHECK:STDOUT: %return: ref %.11 = var // CHECK:STDOUT: } -// CHECK:STDOUT: %AbstractDecl.decl: type = class_decl @AbstractDecl [template = constants.%AbstractDecl] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Abstract { // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc12_10.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc12_10.2: type = converted %int.make_type_32, %.loc12_10.1 [template = i32] -// CHECK:STDOUT: %.loc12_8: %.2 = field_decl a, element0 [template] -// CHECK:STDOUT: %.loc13: = complete_type_witness %.3 [template = constants.%.4] +// CHECK:STDOUT: %.loc2_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_10.2: type = converted %int.make_type_32, %.loc2_10.1 [template = i32] +// CHECK:STDOUT: %.loc2_8: %.2 = field_decl a, element0 [template] +// CHECK:STDOUT: %.loc3: = complete_type_witness %.3 [template = constants.%.4] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Abstract -// CHECK:STDOUT: .a = %.loc12_8 +// CHECK:STDOUT: .a = %.loc2_8 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Derived { // CHECK:STDOUT: %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract] -// CHECK:STDOUT: %.loc16: %.6 = base_decl %Abstract, element0 [template] +// CHECK:STDOUT: %.loc6: %.6 = base_decl %Abstract, element0 [template] // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc18_10.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc18_10.2: type = converted %int.make_type_32, %.loc18_10.1 [template = i32] -// CHECK:STDOUT: %.loc18_8: %.7 = field_decl d, element1 [template] -// CHECK:STDOUT: %.loc19: = complete_type_witness %.8 [template = constants.%.9] +// CHECK:STDOUT: %.loc8_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_10.2: type = converted %int.make_type_32, %.loc8_10.1 [template = i32] +// CHECK:STDOUT: %.loc8_8: %.7 = field_decl d, element1 [template] +// CHECK:STDOUT: %.loc9: = complete_type_witness %.8 [template = constants.%.9] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .base = %.loc16 -// CHECK:STDOUT: .d = %.loc18_8 +// CHECK:STDOUT: .base = %.loc6 +// CHECK:STDOUT: .d = %.loc8_8 // CHECK:STDOUT: extend name_scope2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @AbstractDecl; -// CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Make() -> %return: %Derived { +// CHECK:STDOUT: fn @Access(%d: %Derived) -> %return: %.11 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc27_25: i32 = int_literal 1 [template = constants.%.13] -// CHECK:STDOUT: %.loc27_26: %.3 = struct_literal (%.loc27_25) -// CHECK:STDOUT: %.loc27_34: i32 = int_literal 7 [template = constants.%.14] -// CHECK:STDOUT: %.loc27_35: %.15 = struct_literal (%.loc27_26, %.loc27_34) -// CHECK:STDOUT: return to %return +// CHECK:STDOUT: %d.ref.loc12_11: %Derived = name_ref d, %d +// CHECK:STDOUT: %d.ref.loc12_12: %.7 = name_ref d, @Derived.%.loc8_8 [template = @Derived.%.loc8_8] +// CHECK:STDOUT: %.loc12_12.1: ref i32 = class_element_access %d.ref.loc12_11, element1 +// CHECK:STDOUT: %.loc12_12.2: i32 = bind_value %.loc12_12.1 +// CHECK:STDOUT: %d.ref.loc12_16: %Derived = name_ref d, %d +// CHECK:STDOUT: %base.ref: %.6 = name_ref base, @Derived.%.loc6 [template = @Derived.%.loc6] +// CHECK:STDOUT: %.loc12_17.1: ref %Abstract = class_element_access %d.ref.loc12_16, element0 +// CHECK:STDOUT: %.loc12_17.2: %Abstract = bind_value %.loc12_17.1 +// CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Abstract.%.loc2_8 [template = @Abstract.%.loc2_8] +// CHECK:STDOUT: %.loc12_22.1: ref i32 = class_element_access %.loc12_17.2, element0 +// CHECK:STDOUT: %.loc12_22.2: i32 = bind_value %.loc12_22.1 +// CHECK:STDOUT: %.loc12_24.1: %.11 = tuple_literal (%.loc12_12.2, %.loc12_22.2) +// CHECK:STDOUT: %.loc12_24.2: ref i32 = tuple_access %return, element0 +// CHECK:STDOUT: %.loc12_24.3: init i32 = initialize_from %.loc12_12.2 to %.loc12_24.2 +// CHECK:STDOUT: %.loc12_24.4: ref i32 = tuple_access %return, element1 +// CHECK:STDOUT: %.loc12_24.5: init i32 = initialize_from %.loc12_22.2 to %.loc12_24.4 +// CHECK:STDOUT: %.loc12_24.6: init %.11 = tuple_init (%.loc12_24.3, %.loc12_24.5) to %return +// CHECK:STDOUT: %.loc12_25: init %.11 = converted %.loc12_24.1, %.loc12_24.6 +// CHECK:STDOUT: return %.loc12_25 to %return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Access(%d: %Derived) -> %return: %.17 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %d.ref.loc31_11: %Derived = name_ref d, %d -// CHECK:STDOUT: %d.ref.loc31_12: %.7 = name_ref d, @Derived.%.loc18_8 [template = @Derived.%.loc18_8] -// CHECK:STDOUT: %.loc31_12.1: ref i32 = class_element_access %d.ref.loc31_11, element1 -// CHECK:STDOUT: %.loc31_12.2: i32 = bind_value %.loc31_12.1 -// CHECK:STDOUT: %d.ref.loc31_16: %Derived = name_ref d, %d -// CHECK:STDOUT: %base.ref: %.6 = name_ref base, @Derived.%.loc16 [template = @Derived.%.loc16] -// CHECK:STDOUT: %.loc31_17.1: ref %Abstract = class_element_access %d.ref.loc31_16, element0 -// CHECK:STDOUT: %.loc31_17.2: %Abstract = bind_value %.loc31_17.1 -// CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Abstract.%.loc12_8 [template = @Abstract.%.loc12_8] -// CHECK:STDOUT: %.loc31_22.1: ref i32 = class_element_access %.loc31_17.2, element0 -// CHECK:STDOUT: %.loc31_22.2: i32 = bind_value %.loc31_22.1 -// CHECK:STDOUT: %.loc31_24.1: %.17 = tuple_literal (%.loc31_12.2, %.loc31_22.2) -// CHECK:STDOUT: %.loc31_24.2: ref i32 = tuple_access %return, element0 -// CHECK:STDOUT: %.loc31_24.3: init i32 = initialize_from %.loc31_12.2 to %.loc31_24.2 -// CHECK:STDOUT: %.loc31_24.4: ref i32 = tuple_access %return, element1 -// CHECK:STDOUT: %.loc31_24.5: init i32 = initialize_from %.loc31_22.2 to %.loc31_24.4 -// CHECK:STDOUT: %.loc31_24.6: init %.17 = tuple_init (%.loc31_24.3, %.loc31_24.5) to %return -// CHECK:STDOUT: %.loc31_25: init %.17 = converted %.loc31_24.1, %.loc31_24.6 -// CHECK:STDOUT: return %.loc31_25 to %return +// CHECK:STDOUT: --- fail_abstract_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %AbstractDecl: type = class_type @AbstractDecl [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%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/as +// 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: } // CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .AbstractDecl = %AbstractDecl.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %AbstractDecl.decl: type = class_decl @AbstractDecl [template = constants.%AbstractDecl] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @AbstractDecl; +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_base_bad_type.carbon b/toolchain/check/testdata/class/fail_base_bad_type.carbon index 873debf1e4d10..4d65040223cd0 100644 --- a/toolchain/check/testdata/class/fail_base_bad_type.carbon +++ b/toolchain/check/testdata/class/fail_base_bad_type.carbon @@ -8,37 +8,42 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_base_bad_type.carbon -base class Base {} -class Final { - var a: i32; -} +// --- fail_derive_from_error.carbon class DeriveFromError { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: error: name `error` not found + // CHECK:STDERR: fail_derive_from_error.carbon:[[@LINE+6]]:16: error: name `error` not found // CHECK:STDERR: extend base: error; // CHECK:STDERR: ^~~~~ // CHECK:STDERR: + // CHECK:STDERR: fail_derive_from_non_type.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` + // CHECK:STDERR: extend base: error; } // This should not produce an error. fn AccessMemberWithInvalidBaseError(p: DeriveFromError*) -> i32 { return (*p).n; } +// --- fail_derive_from_non_type.carbon + class DeriveFromNonType { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:16: error: cannot implicitly convert from `i32` to `type` + // CHECK:STDERR: fail_derive_from_non_type.carbon:[[@LINE+9]]:16: error: cannot implicitly convert from `i32` to `type` // CHECK:STDERR: extend base: 32; // CHECK:STDERR: ^~ - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: note: type `i32` does not implement interface `ImplicitAs` + // CHECK:STDERR: fail_derive_from_non_type.carbon:[[@LINE+6]]:16: note: type `i32` does not implement interface `ImplicitAs` // CHECK:STDERR: extend base: 32; // CHECK:STDERR: ^~ // CHECK:STDERR: + // CHECK:STDERR: fail_derive_from_i32.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` + // CHECK:STDERR: extend base: 32; } fn AccessMemberWithInvalidBasNonType(p: DeriveFromNonType*) -> i32 { return (*p).n; } +// --- fail_derive_from_i32.carbon + class DeriveFromi32 { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: error: deriving from final type `i32`; base type must be an `abstract` or `base` class + // CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:16: error: deriving from final type `i32`; base type must be an `abstract` or `base` class // CHECK:STDERR: extend base: i32; // CHECK:STDERR: ^~~ // CHECK:STDERR: @@ -47,88 +52,110 @@ class DeriveFromi32 { // It's not really important whether this conversion produces an error or not, // but it shouldn't crash. -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:53: error: cannot implicitly convert from `DeriveFromi32*` to `i32*` +// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+9]]:53: error: cannot implicitly convert from `DeriveFromi32*` to `i32*` // CHECK:STDERR: fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; } // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:53: note: type `DeriveFromi32*` does not implement interface `ImplicitAs` +// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+6]]:53: note: type `DeriveFromi32*` does not implement interface `ImplicitAs` // CHECK:STDERR: fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; } // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: +// CHECK:STDERR: fail_derive_from_tuple.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` +// CHECK:STDERR: fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; } fn AccessMemberWithInvalidBasei32(p: DeriveFromi32*) -> i32 { return (*p).n; } +// --- fail_derive_from_tuple.carbon + +base class Base {} + class DeriveFromTuple { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: error: deriving from final type `(Base,)`; base type must be an `abstract` or `base` class + // CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+4]]:16: error: deriving from final type `(Base,)`; base type must be an `abstract` or `base` class // CHECK:STDERR: extend base: (Base,); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: extend base: (Base,); } -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:61: error: cannot implicitly convert from `DeriveFromTuple*` to `(Base,)*` +// CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+9]]:61: error: cannot implicitly convert from `DeriveFromTuple*` to `(Base,)*` // CHECK:STDERR: fn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; } // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:61: note: type `DeriveFromTuple*` does not implement interface `ImplicitAs` +// CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+6]]:61: note: type `DeriveFromTuple*` does not implement interface `ImplicitAs` // CHECK:STDERR: fn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; } // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: +// CHECK:STDERR: fail_derive_from_struct.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` +// CHECK:STDERR: fn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; } fn AccessMemberWithInvalidBaseTuple(p: DeriveFromTuple*) -> i32 { return (*p).n; } +// --- fail_derive_from_struct.carbon + // TODO: Should we allow this? // We do allow `{.base = {.a: i32, .b: i32}}`. class DeriveFromStruct { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: error: deriving from final type `{.a: i32, .b: i32}`; base type must be an `abstract` or `base` class + // CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+4]]:16: error: deriving from final type `{.a: i32, .b: i32}`; base type must be an `abstract` or `base` class // CHECK:STDERR: extend base: {.a: i32, .b: i32}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ // CHECK:STDERR: extend base: {.a: i32, .b: i32}; } -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:74: error: cannot implicitly convert from `DeriveFromStruct*` to `{.a: i32, .b: i32}*` +// CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+9]]:74: error: cannot implicitly convert from `DeriveFromStruct*` to `{.a: i32, .b: i32}*` // CHECK:STDERR: fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; } // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:74: note: type `DeriveFromStruct*` does not implement interface `ImplicitAs` +// CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+6]]:74: note: type `DeriveFromStruct*` does not implement interface `ImplicitAs` // CHECK:STDERR: fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; } // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: +// CHECK:STDERR: fail_derive_from_incomplete.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` +// CHECK:STDERR: fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; } // It would be OK to reject this if we start actually looking in the struct type. fn AccessMemberWithInvalidBaseStruct(p: DeriveFromStruct*) -> i32 { return (*p).n; } -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration, only definition +// --- fail_derive_from_incomplete.carbon + +// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` declaration, only definition // CHECK:STDERR: base class Incomplete; // CHECK:STDERR: ^~~~ // CHECK:STDERR: base class Incomplete; class DeriveFromIncomplete { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:16: error: base `Incomplete` is an incomplete type + // CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+7]]:16: error: base `Incomplete` is an incomplete type // CHECK:STDERR: extend base: Incomplete; // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE-6]]:1: note: class was forward declared here + // CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE-6]]:1: note: class was forward declared here // CHECK:STDERR: base class Incomplete; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: extend base: Incomplete; } -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+7]]:74: error: cannot implicitly convert from `DeriveFromIncomplete*` to `Incomplete*` +// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+9]]:74: error: cannot implicitly convert from `DeriveFromIncomplete*` to `Incomplete*` // CHECK:STDERR: fn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; } // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:74: note: type `DeriveFromIncomplete*` does not implement interface `ImplicitAs` +// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+6]]:74: note: type `DeriveFromIncomplete*` does not implement interface `ImplicitAs` // CHECK:STDERR: fn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; } // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: +// CHECK:STDERR: fail_derive_from_final.carbon: error: `Main//default` previously provided by `fail_derive_from_error.carbon` +// CHECK:STDERR: fn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; } fn AccessMemberWithInvalidBaseIncomplete(p: DeriveFromIncomplete*) -> i32 { return (*p).n; } +// --- fail_derive_from_final.carbon + +class Final { + var a: i32; +} + class DeriveFromFinal { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+4]]:16: error: deriving from final type `Final`; base type must be an `abstract` or `base` class + // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+4]]:16: error: deriving from final type `Final`; base type must be an `abstract` or `base` class // CHECK:STDERR: extend base: Final; // CHECK:STDERR: ^~~~~ // CHECK:STDERR: @@ -145,32 +172,89 @@ fn AccessMemberWithInvalidBaseFinal_WithMember(p: DeriveFromFinal*) -> i32 { } fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { - // CHECK:STDERR: fail_base_bad_type.carbon:[[@LINE+3]]:10: error: name `b` not found + // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+3]]:10: error: name `b` not found // CHECK:STDERR: return (*p).b; // CHECK:STDERR: ^~~~~~ return (*p).b; } -// CHECK:STDOUT: --- fail_base_bad_type.carbon +// CHECK:STDOUT: --- fail_derive_from_error.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %Base: type = class_type @Base [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %Final: type = class_type @Final [template] +// CHECK:STDOUT: %DeriveFromError: type = class_type @DeriveFromError [template] +// CHECK:STDOUT: %.1: type = ptr_type %DeriveFromError [template] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] -// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = unbound_element_type %Final, i32 [template] -// CHECK:STDOUT: %.5: type = struct_type {.a: i32} [template] -// CHECK:STDOUT: %.6: = complete_type_witness %.5 [template] -// CHECK:STDOUT: %DeriveFromError: type = class_type @DeriveFromError [template] -// CHECK:STDOUT: %.7: type = ptr_type %DeriveFromError [template] // CHECK:STDOUT: %AccessMemberWithInvalidBaseError.type: type = fn_type @AccessMemberWithInvalidBaseError [template] // CHECK:STDOUT: %AccessMemberWithInvalidBaseError: %AccessMemberWithInvalidBaseError.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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/as +// 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: %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 = imports.%Core +// CHECK:STDOUT: .DeriveFromError = %DeriveFromError.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseError = %AccessMemberWithInvalidBaseError.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %DeriveFromError.decl: type = class_decl @DeriveFromError [template = constants.%DeriveFromError] {} {} +// CHECK:STDOUT: %AccessMemberWithInvalidBaseError.decl: %AccessMemberWithInvalidBaseError.type = fn_decl @AccessMemberWithInvalidBaseError [template = constants.%AccessMemberWithInvalidBaseError] { +// CHECK:STDOUT: %p.patt: %.1 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromError.ref: type = name_ref DeriveFromError, file.%DeriveFromError.decl [template = constants.%DeriveFromError] +// CHECK:STDOUT: %.loc13_55: type = ptr_type %DeriveFromError [template = constants.%.1] +// CHECK:STDOUT: %p.param: %.1 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.1 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_61.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc13_61.2: type = converted %int.make_type_32, %.loc13_61.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @DeriveFromError { +// CHECK:STDOUT: %error.ref: = name_ref error, [template = ] +// CHECK:STDOUT: %.loc9: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness [template = ] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%DeriveFromError +// CHECK:STDOUT: .base = %.loc9 +// CHECK:STDOUT: has_error +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseError(%p: %.1) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.1 = name_ref p, %p +// CHECK:STDOUT: %.loc13_75: ref %DeriveFromError = deref %p.ref +// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_derive_from_non_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { // CHECK:STDOUT: %DeriveFromNonType: type = class_type @DeriveFromNonType [template] -// CHECK:STDOUT: %.8: i32 = int_literal 32 [template] +// CHECK:STDOUT: %.1: i32 = int_literal 32 [template] // CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] // CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] @@ -178,92 +262,25 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] -// CHECK:STDOUT: %.9: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] -// CHECK:STDOUT: %.10: %.9 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, imports.%import_ref.5 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(type) [template] // CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(type) [template] // CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] -// CHECK:STDOUT: %.11: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] -// CHECK:STDOUT: %.12: %.11 = assoc_entity element0, imports.%import_ref.6 [template] -// CHECK:STDOUT: %.13: %.9 = assoc_entity element0, imports.%import_ref.7 [symbolic] -// CHECK:STDOUT: %.14: type = ptr_type %DeriveFromNonType [template] +// CHECK:STDOUT: %.5: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.6: %.5 = assoc_entity element0, imports.%import_ref.5 [template] +// CHECK:STDOUT: %.7: %.3 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %.8: type = ptr_type %DeriveFromNonType [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %AccessMemberWithInvalidBasNonType.type: type = fn_type @AccessMemberWithInvalidBasNonType [template] // CHECK:STDOUT: %AccessMemberWithInvalidBasNonType: %AccessMemberWithInvalidBasNonType.type = struct_value () [template] -// CHECK:STDOUT: %DeriveFromi32: type = class_type @DeriveFromi32 [template] -// CHECK:STDOUT: %.15: type = ptr_type %DeriveFromi32 [template] -// CHECK:STDOUT: %.16: type = ptr_type i32 [template] -// CHECK:STDOUT: %ConvertToBadBasei32.type: type = fn_type @ConvertToBadBasei32 [template] -// CHECK:STDOUT: %ConvertToBadBasei32: %ConvertToBadBasei32.type = struct_value () [template] -// CHECK:STDOUT: %ImplicitAs.type.4: type = interface_type @ImplicitAs, @ImplicitAs(%.16) [template] -// CHECK:STDOUT: %Convert.type.3: type = fn_type @Convert, @ImplicitAs(%.16) [template] -// CHECK:STDOUT: %Convert.3: %Convert.type.3 = struct_value () [template] -// CHECK:STDOUT: %.17: type = assoc_entity_type %ImplicitAs.type.4, %Convert.type.3 [template] -// CHECK:STDOUT: %.18: %.17 = assoc_entity element0, imports.%import_ref.6 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBasei32.type: type = fn_type @AccessMemberWithInvalidBasei32 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBasei32: %AccessMemberWithInvalidBasei32.type = struct_value () [template] -// CHECK:STDOUT: %DeriveFromTuple: type = class_type @DeriveFromTuple [template] -// CHECK:STDOUT: %.19: type = tuple_type (type) [template] -// CHECK:STDOUT: %.20: type = tuple_type (%Base) [template] -// CHECK:STDOUT: %.21: type = ptr_type %.1 [template] -// CHECK:STDOUT: %.22: type = tuple_type (%.21) [template] -// CHECK:STDOUT: %.23: type = ptr_type %DeriveFromTuple [template] -// CHECK:STDOUT: %.24: type = ptr_type %.20 [template] -// CHECK:STDOUT: %ConvertToBadBaseTuple.type: type = fn_type @ConvertToBadBaseTuple [template] -// CHECK:STDOUT: %ConvertToBadBaseTuple: %ConvertToBadBaseTuple.type = struct_value () [template] -// CHECK:STDOUT: %ImplicitAs.type.5: type = interface_type @ImplicitAs, @ImplicitAs(%.24) [template] -// CHECK:STDOUT: %Convert.type.4: type = fn_type @Convert, @ImplicitAs(%.24) [template] -// CHECK:STDOUT: %Convert.4: %Convert.type.4 = struct_value () [template] -// CHECK:STDOUT: %.25: type = assoc_entity_type %ImplicitAs.type.5, %Convert.type.4 [template] -// CHECK:STDOUT: %.26: %.25 = assoc_entity element0, imports.%import_ref.6 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple.type: type = fn_type @AccessMemberWithInvalidBaseTuple [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple: %AccessMemberWithInvalidBaseTuple.type = struct_value () [template] -// CHECK:STDOUT: %DeriveFromStruct: type = class_type @DeriveFromStruct [template] -// CHECK:STDOUT: %.27: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %.28: type = ptr_type %.27 [template] -// CHECK:STDOUT: %.29: type = ptr_type %DeriveFromStruct [template] -// CHECK:STDOUT: %ConvertToBadBaseStruct.type: type = fn_type @ConvertToBadBaseStruct [template] -// CHECK:STDOUT: %ConvertToBadBaseStruct: %ConvertToBadBaseStruct.type = struct_value () [template] -// CHECK:STDOUT: %ImplicitAs.type.6: type = interface_type @ImplicitAs, @ImplicitAs(%.28) [template] -// CHECK:STDOUT: %Convert.type.5: type = fn_type @Convert, @ImplicitAs(%.28) [template] -// CHECK:STDOUT: %Convert.5: %Convert.type.5 = struct_value () [template] -// CHECK:STDOUT: %.30: type = assoc_entity_type %ImplicitAs.type.6, %Convert.type.5 [template] -// CHECK:STDOUT: %.31: %.30 = assoc_entity element0, imports.%import_ref.6 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct.type: type = fn_type @AccessMemberWithInvalidBaseStruct [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct: %AccessMemberWithInvalidBaseStruct.type = struct_value () [template] -// CHECK:STDOUT: %Incomplete: type = class_type @Incomplete [template] -// CHECK:STDOUT: %DeriveFromIncomplete: type = class_type @DeriveFromIncomplete [template] -// CHECK:STDOUT: %.32: type = ptr_type %DeriveFromIncomplete [template] -// CHECK:STDOUT: %.33: type = ptr_type %Incomplete [template] -// CHECK:STDOUT: %ConvertToBadBaseIncomplete.type: type = fn_type @ConvertToBadBaseIncomplete [template] -// CHECK:STDOUT: %ConvertToBadBaseIncomplete: %ConvertToBadBaseIncomplete.type = struct_value () [template] -// CHECK:STDOUT: %ImplicitAs.type.7: type = interface_type @ImplicitAs, @ImplicitAs(%.33) [template] -// CHECK:STDOUT: %Convert.type.6: type = fn_type @Convert, @ImplicitAs(%.33) [template] -// CHECK:STDOUT: %Convert.6: %Convert.type.6 = struct_value () [template] -// CHECK:STDOUT: %.34: type = assoc_entity_type %ImplicitAs.type.7, %Convert.type.6 [template] -// CHECK:STDOUT: %.35: %.34 = assoc_entity element0, imports.%import_ref.6 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete.type: type = fn_type @AccessMemberWithInvalidBaseIncomplete [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete: %AccessMemberWithInvalidBaseIncomplete.type = struct_value () [template] -// CHECK:STDOUT: %DeriveFromFinal: type = class_type @DeriveFromFinal [template] -// CHECK:STDOUT: %.36: type = ptr_type %.5 [template] -// CHECK:STDOUT: %.37: type = unbound_element_type %DeriveFromFinal, %Final [template] -// CHECK:STDOUT: %.38: type = struct_type {.base: %Final} [template] -// CHECK:STDOUT: %.39: = complete_type_witness %.38 [template] -// CHECK:STDOUT: %.40: type = ptr_type %DeriveFromFinal [template] -// CHECK:STDOUT: %.41: type = ptr_type %Final [template] -// CHECK:STDOUT: %ConvertToBadBaseFinal.type: type = fn_type @ConvertToBadBaseFinal [template] -// CHECK:STDOUT: %ConvertToBadBaseFinal: %ConvertToBadBaseFinal.type = struct_value () [template] -// CHECK:STDOUT: %.42: type = struct_type {.base: %.36} [template] -// CHECK:STDOUT: %.43: type = ptr_type %.38 [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember.type: type = fn_type @AccessMemberWithInvalidBaseFinal_WithMember [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember: %AccessMemberWithInvalidBaseFinal_WithMember.type = struct_value () [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember.type: type = fn_type @AccessMemberWithInvalidBaseFinal_NoMember [template] -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember: %AccessMemberWithInvalidBaseFinal_NoMember.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: .Int32 = %import_ref.1 -// CHECK:STDOUT: .ImplicitAs = %import_ref.2 +// CHECK:STDOUT: .ImplicitAs = %import_ref.1 +// CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/operators // CHECK:STDOUT: import Core//prelude/types @@ -273,212 +290,33 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: import Core//prelude/operators/comparison // CHECK:STDOUT: import Core//prelude/types/bool // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] -// CHECK:STDOUT: %import_ref.2: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] -// CHECK:STDOUT: %import_ref.3 = import_ref Core//prelude/operators/as, inst+45, unloaded -// CHECK:STDOUT: %import_ref.4: @ImplicitAs.%.1 (%.9) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.13)] +// CHECK:STDOUT: %import_ref.1: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.2 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.3: @ImplicitAs.%.1 (%.3) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.7)] +// CHECK:STDOUT: %import_ref.4 = import_ref Core//prelude/operators/as, inst+56, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.7: %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 = imports.%Core -// CHECK:STDOUT: .Base = %Base.decl -// CHECK:STDOUT: .Final = %Final.decl -// CHECK:STDOUT: .DeriveFromError = %DeriveFromError.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseError = %AccessMemberWithInvalidBaseError.decl // CHECK:STDOUT: .DeriveFromNonType = %DeriveFromNonType.decl // CHECK:STDOUT: .AccessMemberWithInvalidBasNonType = %AccessMemberWithInvalidBasNonType.decl -// CHECK:STDOUT: .DeriveFromi32 = %DeriveFromi32.decl -// CHECK:STDOUT: .ConvertToBadBasei32 = %ConvertToBadBasei32.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBasei32 = %AccessMemberWithInvalidBasei32.decl -// CHECK:STDOUT: .DeriveFromTuple = %DeriveFromTuple.decl -// CHECK:STDOUT: .ConvertToBadBaseTuple = %ConvertToBadBaseTuple.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseTuple = %AccessMemberWithInvalidBaseTuple.decl -// CHECK:STDOUT: .DeriveFromStruct = %DeriveFromStruct.decl -// CHECK:STDOUT: .ConvertToBadBaseStruct = %ConvertToBadBaseStruct.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseStruct = %AccessMemberWithInvalidBaseStruct.decl -// CHECK:STDOUT: .Incomplete = %Incomplete.decl -// CHECK:STDOUT: .DeriveFromIncomplete = %DeriveFromIncomplete.decl -// CHECK:STDOUT: .ConvertToBadBaseIncomplete = %ConvertToBadBaseIncomplete.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseIncomplete = %AccessMemberWithInvalidBaseIncomplete.decl -// CHECK:STDOUT: .DeriveFromFinal = %DeriveFromFinal.decl -// CHECK:STDOUT: .ConvertToBadBaseFinal = %ConvertToBadBaseFinal.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseFinal_WithMember = %AccessMemberWithInvalidBaseFinal_WithMember.decl -// CHECK:STDOUT: .AccessMemberWithInvalidBaseFinal_NoMember = %AccessMemberWithInvalidBaseFinal_NoMember.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {} {} -// CHECK:STDOUT: %Final.decl: type = class_decl @Final [template = constants.%Final] {} {} -// CHECK:STDOUT: %DeriveFromError.decl: type = class_decl @DeriveFromError [template = constants.%DeriveFromError] {} {} -// CHECK:STDOUT: %AccessMemberWithInvalidBaseError.decl: %AccessMemberWithInvalidBaseError.type = fn_decl @AccessMemberWithInvalidBaseError [template = constants.%AccessMemberWithInvalidBaseError] { -// CHECK:STDOUT: %p.patt: %.7 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromError.ref: type = name_ref DeriveFromError, file.%DeriveFromError.decl [template = constants.%DeriveFromError] -// CHECK:STDOUT: %.loc25_55: type = ptr_type %DeriveFromError [template = constants.%.7] -// CHECK:STDOUT: %p.param: %.7 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.7 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc25_61.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc25_61.2: type = converted %int.make_type_32, %.loc25_61.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } // CHECK:STDOUT: %DeriveFromNonType.decl: type = class_decl @DeriveFromNonType [template = constants.%DeriveFromNonType] {} {} // CHECK:STDOUT: %AccessMemberWithInvalidBasNonType.decl: %AccessMemberWithInvalidBasNonType.type = fn_decl @AccessMemberWithInvalidBasNonType [template = constants.%AccessMemberWithInvalidBasNonType] { -// CHECK:STDOUT: %p.patt: %.14 = binding_pattern p +// CHECK:STDOUT: %p.patt: %.8 = binding_pattern p // CHECK:STDOUT: } { // CHECK:STDOUT: %DeriveFromNonType.ref: type = name_ref DeriveFromNonType, file.%DeriveFromNonType.decl [template = constants.%DeriveFromNonType] -// CHECK:STDOUT: %.loc38_58: type = ptr_type %DeriveFromNonType [template = constants.%.14] -// CHECK:STDOUT: %p.param: %.14 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.14 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc38_64.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc38_64.2: type = converted %int.make_type_32, %.loc38_64.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %DeriveFromi32.decl: type = class_decl @DeriveFromi32 [template = constants.%DeriveFromi32] {} {} -// CHECK:STDOUT: %ConvertToBadBasei32.decl: %ConvertToBadBasei32.type = fn_decl @ConvertToBadBasei32 [template = constants.%ConvertToBadBasei32] { -// CHECK:STDOUT: %p.patt: %.15 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromi32.ref: type = name_ref DeriveFromi32, file.%DeriveFromi32.decl [template = constants.%DeriveFromi32] -// CHECK:STDOUT: %.loc57_40: type = ptr_type %DeriveFromi32 [template = constants.%.15] -// CHECK:STDOUT: %p.param: %.15 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.15 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc57_49.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc57_49.2: type = converted %int.make_type_32, %.loc57_49.1 [template = i32] -// CHECK:STDOUT: %.loc57_49.3: type = ptr_type i32 [template = constants.%.16] -// CHECK:STDOUT: %return: ref %.16 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBasei32.decl: %AccessMemberWithInvalidBasei32.type = fn_decl @AccessMemberWithInvalidBasei32 [template = constants.%AccessMemberWithInvalidBasei32] { -// CHECK:STDOUT: %p.patt: %.15 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromi32.ref: type = name_ref DeriveFromi32, file.%DeriveFromi32.decl [template = constants.%DeriveFromi32] -// CHECK:STDOUT: %.loc59_51: type = ptr_type %DeriveFromi32 [template = constants.%.15] -// CHECK:STDOUT: %p.param: %.15 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.15 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc59_57.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc59_57.2: type = converted %int.make_type_32, %.loc59_57.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %DeriveFromTuple.decl: type = class_decl @DeriveFromTuple [template = constants.%DeriveFromTuple] {} {} -// CHECK:STDOUT: %ConvertToBadBaseTuple.decl: %ConvertToBadBaseTuple.type = fn_decl @ConvertToBadBaseTuple [template = constants.%ConvertToBadBaseTuple] { -// CHECK:STDOUT: %p.patt: %.23 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromTuple.ref: type = name_ref DeriveFromTuple, file.%DeriveFromTuple.decl [template = constants.%DeriveFromTuple] -// CHECK:STDOUT: %.loc76_44: type = ptr_type %DeriveFromTuple [template = constants.%.23] -// CHECK:STDOUT: %p.param: %.23 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.23 = bind_name p, %p.param -// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base] -// CHECK:STDOUT: %.loc76_56: %.19 = tuple_literal (%Base.ref) -// CHECK:STDOUT: %.loc76_57.1: type = converted %.loc76_56, constants.%.20 [template = constants.%.20] -// CHECK:STDOUT: %.loc76_57.2: type = ptr_type %.20 [template = constants.%.24] -// CHECK:STDOUT: %return: ref %.24 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple.decl: %AccessMemberWithInvalidBaseTuple.type = fn_decl @AccessMemberWithInvalidBaseTuple [template = constants.%AccessMemberWithInvalidBaseTuple] { -// CHECK:STDOUT: %p.patt: %.23 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromTuple.ref: type = name_ref DeriveFromTuple, file.%DeriveFromTuple.decl [template = constants.%DeriveFromTuple] -// CHECK:STDOUT: %.loc78_55: type = ptr_type %DeriveFromTuple [template = constants.%.23] -// CHECK:STDOUT: %p.param: %.23 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.23 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc78_61.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc78_61.2: type = converted %int.make_type_32, %.loc78_61.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %DeriveFromStruct.decl: type = class_decl @DeriveFromStruct [template = constants.%DeriveFromStruct] {} {} -// CHECK:STDOUT: %ConvertToBadBaseStruct.decl: %ConvertToBadBaseStruct.type = fn_decl @ConvertToBadBaseStruct [template = constants.%ConvertToBadBaseStruct] { -// CHECK:STDOUT: %p.patt: %.29 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromStruct.ref: type = name_ref DeriveFromStruct, file.%DeriveFromStruct.decl [template = constants.%DeriveFromStruct] -// CHECK:STDOUT: %.loc97_46: type = ptr_type %DeriveFromStruct [template = constants.%.29] -// CHECK:STDOUT: %p.param: %.29 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.29 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32.loc97_57: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc97_57.1: type = value_of_initializer %int.make_type_32.loc97_57 [template = i32] -// CHECK:STDOUT: %.loc97_57.2: type = converted %int.make_type_32.loc97_57, %.loc97_57.1 [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc97_66: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc97_66.1: type = value_of_initializer %int.make_type_32.loc97_66 [template = i32] -// CHECK:STDOUT: %.loc97_66.2: type = converted %int.make_type_32.loc97_66, %.loc97_66.1 [template = i32] -// CHECK:STDOUT: %.loc97_69: type = struct_type {.a: i32, .b: i32} [template = constants.%.27] -// CHECK:STDOUT: %.loc97_70: type = ptr_type %.27 [template = constants.%.28] -// CHECK:STDOUT: %return: ref %.28 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct.decl: %AccessMemberWithInvalidBaseStruct.type = fn_decl @AccessMemberWithInvalidBaseStruct [template = constants.%AccessMemberWithInvalidBaseStruct] { -// CHECK:STDOUT: %p.patt: %.29 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromStruct.ref: type = name_ref DeriveFromStruct, file.%DeriveFromStruct.decl [template = constants.%DeriveFromStruct] -// CHECK:STDOUT: %.loc100_57: type = ptr_type %DeriveFromStruct [template = constants.%.29] -// CHECK:STDOUT: %p.param: %.29 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.29 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc100_63.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc100_63.2: type = converted %int.make_type_32, %.loc100_63.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {} {} -// CHECK:STDOUT: %DeriveFromIncomplete.decl: type = class_decl @DeriveFromIncomplete [template = constants.%DeriveFromIncomplete] {} {} -// CHECK:STDOUT: %ConvertToBadBaseIncomplete.decl: %ConvertToBadBaseIncomplete.type = fn_decl @ConvertToBadBaseIncomplete [template = constants.%ConvertToBadBaseIncomplete] { -// CHECK:STDOUT: %p.patt: %.32 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] -// CHECK:STDOUT: %.loc126_54: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] -// CHECK:STDOUT: %p.param: %.32 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.32 = bind_name p, %p.param -// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] -// CHECK:STDOUT: %.loc126_70: type = ptr_type %Incomplete [template = constants.%.33] -// CHECK:STDOUT: %return: ref %.33 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete.decl: %AccessMemberWithInvalidBaseIncomplete.type = fn_decl @AccessMemberWithInvalidBaseIncomplete [template = constants.%AccessMemberWithInvalidBaseIncomplete] { -// CHECK:STDOUT: %p.patt: %.32 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] -// CHECK:STDOUT: %.loc128_65: type = ptr_type %DeriveFromIncomplete [template = constants.%.32] -// CHECK:STDOUT: %p.param: %.32 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.32 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc128_71.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc128_71.2: type = converted %int.make_type_32, %.loc128_71.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %DeriveFromFinal.decl: type = class_decl @DeriveFromFinal [template = constants.%DeriveFromFinal] {} {} -// CHECK:STDOUT: %ConvertToBadBaseFinal.decl: %ConvertToBadBaseFinal.type = fn_decl @ConvertToBadBaseFinal [template = constants.%ConvertToBadBaseFinal] { -// CHECK:STDOUT: %p.patt: %.40 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc139_44: type = ptr_type %DeriveFromFinal [template = constants.%.40] -// CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.40 = bind_name p, %p.param -// CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] -// CHECK:STDOUT: %.loc139_55: type = ptr_type %Final [template = constants.%.41] -// CHECK:STDOUT: %return: ref %.41 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember.decl: %AccessMemberWithInvalidBaseFinal_WithMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember [template = constants.%AccessMemberWithInvalidBaseFinal_WithMember] { -// CHECK:STDOUT: %p.patt: %.40 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc143_66: type = ptr_type %DeriveFromFinal [template = constants.%.40] -// CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.40 = bind_name p, %p.param -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc143_72.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc143_72.2: type = converted %int.make_type_32, %.loc143_72.1 [template = i32] -// CHECK:STDOUT: %return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember.decl: %AccessMemberWithInvalidBaseFinal_NoMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember [template = constants.%AccessMemberWithInvalidBaseFinal_NoMember] { -// CHECK:STDOUT: %p.patt: %.40 = binding_pattern p -// CHECK:STDOUT: } { -// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] -// CHECK:STDOUT: %.loc147_64: type = ptr_type %DeriveFromFinal [template = constants.%.40] -// CHECK:STDOUT: %p.param: %.40 = param p, runtime_param0 -// CHECK:STDOUT: %p: %.40 = bind_name p, %p.param +// CHECK:STDOUT: %.loc15_58: type = ptr_type %DeriveFromNonType [template = constants.%.8] +// CHECK:STDOUT: %p.param: %.8 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.8 = bind_name p, %p.param // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc147_70.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc147_70.2: type = converted %int.make_type_32, %.loc147_70.1 [template = i32] +// CHECK:STDOUT: %.loc15_64.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc15_64.2: type = converted %int.make_type_32, %.loc15_64.1 [template = i32] // CHECK:STDOUT: %return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -491,136 +329,593 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] // CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] // CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] -// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.9)] -// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.9) = assoc_entity element0, imports.%import_ref.6 [symbolic = %.2 (constants.%.10)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.3) = assoc_entity element0, imports.%import_ref.5 [symbolic = %.2 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.3 -// CHECK:STDOUT: .Convert = imports.%import_ref.4 -// CHECK:STDOUT: witness = (imports.%import_ref.5) +// CHECK:STDOUT: .Self = imports.%import_ref.2 +// CHECK:STDOUT: .Convert = imports.%import_ref.3 +// CHECK:STDOUT: witness = (imports.%import_ref.4) // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @Base { -// CHECK:STDOUT: %.loc11: = complete_type_witness %.1 [template = constants.%.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Base -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @Final { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc13_10.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc13_10.2: type = converted %int.make_type_32, %.loc13_10.1 [template = i32] -// CHECK:STDOUT: %.loc13_8: %.4 = field_decl a, element0 [template] -// CHECK:STDOUT: %.loc14: = complete_type_witness %.5 [template = constants.%.6] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Final -// CHECK:STDOUT: .a = %.loc13_8 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromError { -// CHECK:STDOUT: %error.ref: = name_ref error, [template = ] -// CHECK:STDOUT: %.loc21: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc22: = complete_type_witness [template = ] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromError -// CHECK:STDOUT: .base = %.loc21 -// CHECK:STDOUT: has_error -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: class @DeriveFromNonType { -// CHECK:STDOUT: %.loc35_16.1: i32 = int_literal 32 [template = constants.%.8] +// CHECK:STDOUT: %.loc12_16.1: i32 = int_literal 32 [template = constants.%.1] // CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(type) [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %.loc35_16.2: %.11 = specific_constant imports.%import_ref.4, @ImplicitAs(type) [template = constants.%.12] -// CHECK:STDOUT: %Convert.ref: %.11 = name_ref Convert, %.loc35_16.2 [template = constants.%.12] -// CHECK:STDOUT: %.loc35_16.3: type = converted %.loc35_16.1, [template = ] -// CHECK:STDOUT: %.loc35_18: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc36: = complete_type_witness [template = ] +// CHECK:STDOUT: %.loc12_16.2: %.5 = specific_constant imports.%import_ref.3, @ImplicitAs(type) [template = constants.%.6] +// CHECK:STDOUT: %Convert.ref: %.5 = name_ref Convert, %.loc12_16.2 [template = constants.%.6] +// CHECK:STDOUT: %.loc12_16.3: type = converted %.loc12_16.1, [template = ] +// CHECK:STDOUT: %.loc12_18: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc13: = complete_type_witness [template = ] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%DeriveFromNonType -// CHECK:STDOUT: .base = %.loc35_18 +// CHECK:STDOUT: .base = %.loc12_18 // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromi32 { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc45_16.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc45_16.2: type = converted %int.make_type_32, %.loc45_16.1 [template = i32] -// CHECK:STDOUT: %.loc45_19: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc46: = complete_type_witness [template = ] +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromi32 -// CHECK:STDOUT: .base = %.loc45_19 -// CHECK:STDOUT: has_error +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromTuple { -// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base] -// CHECK:STDOUT: %.loc66_22.1: %.19 = tuple_literal (%Base.ref) -// CHECK:STDOUT: %.loc66_22.2: type = converted %.loc66_22.1, constants.%.20 [template = constants.%.20] -// CHECK:STDOUT: %.loc66_23: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc67: = complete_type_witness [template = ] +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromTuple -// CHECK:STDOUT: .base = %.loc66_23 -// CHECK:STDOUT: has_error +// CHECK:STDOUT: fn @AccessMemberWithInvalidBasNonType(%p: %.8) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.8 = name_ref p, %p +// CHECK:STDOUT: %.loc15_78: ref %DeriveFromNonType = deref %p.ref +// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromStruct { -// CHECK:STDOUT: %int.make_type_32.loc87_21: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc87_21.1: type = value_of_initializer %int.make_type_32.loc87_21 [template = i32] -// CHECK:STDOUT: %.loc87_21.2: type = converted %int.make_type_32.loc87_21, %.loc87_21.1 [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc87_30: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc87_30.1: type = value_of_initializer %int.make_type_32.loc87_30 [template = i32] -// CHECK:STDOUT: %.loc87_30.2: type = converted %int.make_type_32.loc87_30, %.loc87_30.1 [template = i32] -// CHECK:STDOUT: %.loc87_33: type = struct_type {.a: i32, .b: i32} [template = constants.%.27] -// CHECK:STDOUT: %.loc87_34: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc88: = complete_type_witness [template = ] +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(type) { +// CHECK:STDOUT: %Dest => type +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %.2 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_derive_from_i32.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %DeriveFromi32: type = class_type @DeriveFromi32 [template] +// 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: %.2: type = ptr_type %DeriveFromi32 [template] +// CHECK:STDOUT: %.3: type = ptr_type i32 [template] +// CHECK:STDOUT: %ConvertToBadBasei32.type: type = fn_type @ConvertToBadBasei32 [template] +// CHECK:STDOUT: %ConvertToBadBasei32: %ConvertToBadBasei32.type = struct_value () [template] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.4: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.6 [template] +// CHECK:STDOUT: %.8: %.4 = assoc_entity element0, imports.%import_ref.7 [symbolic] +// CHECK:STDOUT: %AccessMemberWithInvalidBasei32.type: type = fn_type @AccessMemberWithInvalidBasei32 [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBasei32: %AccessMemberWithInvalidBasei32.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.1 +// CHECK:STDOUT: .ImplicitAs = %import_ref.2 +// 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/as +// 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: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: %import_ref.2: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.3 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.4: @ImplicitAs.%.1 (%.4) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.8)] +// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .DeriveFromi32 = %DeriveFromi32.decl +// CHECK:STDOUT: .ConvertToBadBasei32 = %ConvertToBadBasei32.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBasei32 = %AccessMemberWithInvalidBasei32.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %DeriveFromi32.decl: type = class_decl @DeriveFromi32 [template = constants.%DeriveFromi32] {} {} +// CHECK:STDOUT: %ConvertToBadBasei32.decl: %ConvertToBadBasei32.type = fn_decl @ConvertToBadBasei32 [template = constants.%ConvertToBadBasei32] { +// CHECK:STDOUT: %p.patt: %.2 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromi32.ref: type = name_ref DeriveFromi32, file.%DeriveFromi32.decl [template = constants.%DeriveFromi32] +// CHECK:STDOUT: %.loc21_40: type = ptr_type %DeriveFromi32 [template = constants.%.2] +// CHECK:STDOUT: %p.param: %.2 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.2 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc21_49.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc21_49.2: type = converted %int.make_type_32, %.loc21_49.1 [template = i32] +// CHECK:STDOUT: %.loc21_49.3: type = ptr_type i32 [template = constants.%.3] +// CHECK:STDOUT: %return: ref %.3 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBasei32.decl: %AccessMemberWithInvalidBasei32.type = fn_decl @AccessMemberWithInvalidBasei32 [template = constants.%AccessMemberWithInvalidBasei32] { +// CHECK:STDOUT: %p.patt: %.2 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromi32.ref: type = name_ref DeriveFromi32, file.%DeriveFromi32.decl [template = constants.%DeriveFromi32] +// CHECK:STDOUT: %.loc23_51: type = ptr_type %DeriveFromi32 [template = constants.%.2] +// CHECK:STDOUT: %p.param: %.2 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.2 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc23_57.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc23_57.2: type = converted %int.make_type_32, %.loc23_57.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.4) = assoc_entity element0, imports.%import_ref.6 [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: .Convert = imports.%import_ref.4 +// CHECK:STDOUT: witness = (imports.%import_ref.5) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @DeriveFromi32 { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc7_16.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc7_16.2: type = converted %int.make_type_32, %.loc7_16.1 [template = i32] +// CHECK:STDOUT: %.loc7_19: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc8: = complete_type_witness [template = ] // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromStruct -// CHECK:STDOUT: .base = %.loc87_34 +// CHECK:STDOUT: .Self = constants.%DeriveFromi32 +// CHECK:STDOUT: .base = %.loc7_19 // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @Incomplete; +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @ConvertToBadBasei32(%p: %.2) -> %.3 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.2 = name_ref p, %p +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.3) [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %.loc21_61.1: %.6 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.3) [template = constants.%.7] +// CHECK:STDOUT: %Convert.ref: %.6 = name_ref Convert, %.loc21_61.1 [template = constants.%.7] +// CHECK:STDOUT: %.loc21_61.2: %.3 = converted %p.ref, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @AccessMemberWithInvalidBasei32(%p: %.2) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.2 = name_ref p, %p +// CHECK:STDOUT: %.loc23_71: ref %DeriveFromi32 = deref %p.ref +// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%.3) { +// CHECK:STDOUT: %Dest => constants.%.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %.2 => constants.%.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_derive_from_tuple.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Base: type = class_type @Base [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %DeriveFromTuple: type = class_type @DeriveFromTuple [template] +// CHECK:STDOUT: %.3: type = tuple_type (type) [template] +// CHECK:STDOUT: %.4: type = tuple_type (%Base) [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.7: type = tuple_type (%.6) [template] +// CHECK:STDOUT: %.8: type = ptr_type %DeriveFromTuple [template] +// CHECK:STDOUT: %.9: type = ptr_type %.4 [template] +// CHECK:STDOUT: %ConvertToBadBaseTuple.type: type = fn_type @ConvertToBadBaseTuple [template] +// CHECK:STDOUT: %ConvertToBadBaseTuple: %ConvertToBadBaseTuple.type = struct_value () [template] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.10: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.11: %.10 = assoc_entity element0, imports.%import_ref.5 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(%.9) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.9) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.12: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.5 [template] +// CHECK:STDOUT: %.14: %.10 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple.type: type = fn_type @AccessMemberWithInvalidBaseTuple [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple: %AccessMemberWithInvalidBaseTuple.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .ImplicitAs = %import_ref.1 +// CHECK:STDOUT: .Int32 = %import_ref.7 +// 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/as +// 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: %import_ref.1: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.2 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.3: @ImplicitAs.%.1 (%.10) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.14)] +// CHECK:STDOUT: %import_ref.4 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.7: %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 = imports.%Core +// CHECK:STDOUT: .Base = %Base.decl +// CHECK:STDOUT: .DeriveFromTuple = %DeriveFromTuple.decl +// CHECK:STDOUT: .ConvertToBadBaseTuple = %ConvertToBadBaseTuple.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseTuple = %AccessMemberWithInvalidBaseTuple.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {} {} +// CHECK:STDOUT: %DeriveFromTuple.decl: type = class_decl @DeriveFromTuple [template = constants.%DeriveFromTuple] {} {} +// CHECK:STDOUT: %ConvertToBadBaseTuple.decl: %ConvertToBadBaseTuple.type = fn_decl @ConvertToBadBaseTuple [template = constants.%ConvertToBadBaseTuple] { +// CHECK:STDOUT: %p.patt: %.8 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromTuple.ref: type = name_ref DeriveFromTuple, file.%DeriveFromTuple.decl [template = constants.%DeriveFromTuple] +// CHECK:STDOUT: %.loc21_44: type = ptr_type %DeriveFromTuple [template = constants.%.8] +// CHECK:STDOUT: %p.param: %.8 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.8 = bind_name p, %p.param +// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base] +// CHECK:STDOUT: %.loc21_56: %.3 = tuple_literal (%Base.ref) +// CHECK:STDOUT: %.loc21_57.1: type = converted %.loc21_56, constants.%.4 [template = constants.%.4] +// CHECK:STDOUT: %.loc21_57.2: type = ptr_type %.4 [template = constants.%.9] +// CHECK:STDOUT: %return: ref %.9 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBaseTuple.decl: %AccessMemberWithInvalidBaseTuple.type = fn_decl @AccessMemberWithInvalidBaseTuple [template = constants.%AccessMemberWithInvalidBaseTuple] { +// CHECK:STDOUT: %p.patt: %.8 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromTuple.ref: type = name_ref DeriveFromTuple, file.%DeriveFromTuple.decl [template = constants.%DeriveFromTuple] +// CHECK:STDOUT: %.loc23_55: type = ptr_type %DeriveFromTuple [template = constants.%.8] +// CHECK:STDOUT: %p.param: %.8 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.8 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc23_61.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc23_61.2: type = converted %int.make_type_32, %.loc23_61.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.10)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.10) = assoc_entity element0, imports.%import_ref.5 [symbolic = %.2 (constants.%.11)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.2 +// CHECK:STDOUT: .Convert = imports.%import_ref.3 +// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Base { +// CHECK:STDOUT: %.loc2: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Base +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @DeriveFromTuple { +// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base] +// CHECK:STDOUT: %.loc9_22.1: %.3 = tuple_literal (%Base.ref) +// CHECK:STDOUT: %.loc9_22.2: type = converted %.loc9_22.1, constants.%.4 [template = constants.%.4] +// CHECK:STDOUT: %.loc9_23: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness [template = ] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%DeriveFromTuple +// CHECK:STDOUT: .base = %.loc9_23 +// CHECK:STDOUT: has_error +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @ConvertToBadBaseTuple(%p: %.8) -> %.9 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.8 = name_ref p, %p +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.9) [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %.loc21_69.1: %.12 = specific_constant imports.%import_ref.3, @ImplicitAs(constants.%.9) [template = constants.%.13] +// CHECK:STDOUT: %Convert.ref: %.12 = name_ref Convert, %.loc21_69.1 [template = constants.%.13] +// CHECK:STDOUT: %.loc21_69.2: %.9 = converted %p.ref, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseTuple(%p: %.8) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.8 = name_ref p, %p +// CHECK:STDOUT: %.loc23_75: ref %DeriveFromTuple = deref %p.ref +// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%.9) { +// CHECK:STDOUT: %Dest => constants.%.9 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.12 +// CHECK:STDOUT: %.2 => constants.%.13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_derive_from_struct.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %DeriveFromStruct: type = class_type @DeriveFromStruct [template] +// 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: %.2: type = struct_type {.a: i32, .b: i32} [template] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [template] +// CHECK:STDOUT: %.4: type = ptr_type %DeriveFromStruct [template] +// CHECK:STDOUT: %ConvertToBadBaseStruct.type: type = fn_type @ConvertToBadBaseStruct [template] +// CHECK:STDOUT: %ConvertToBadBaseStruct: %ConvertToBadBaseStruct.type = struct_value () [template] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.5: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.6: %.5 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.7: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.8: %.7 = assoc_entity element0, imports.%import_ref.6 [template] +// CHECK:STDOUT: %.9: %.5 = assoc_entity element0, imports.%import_ref.7 [symbolic] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct.type: type = fn_type @AccessMemberWithInvalidBaseStruct [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct: %AccessMemberWithInvalidBaseStruct.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.1 +// CHECK:STDOUT: .ImplicitAs = %import_ref.2 +// 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/as +// 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: %import_ref.1: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: %import_ref.2: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.3 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.4: @ImplicitAs.%.1 (%.5) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.9)] +// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .DeriveFromStruct = %DeriveFromStruct.decl +// CHECK:STDOUT: .ConvertToBadBaseStruct = %ConvertToBadBaseStruct.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseStruct = %AccessMemberWithInvalidBaseStruct.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %DeriveFromStruct.decl: type = class_decl @DeriveFromStruct [template = constants.%DeriveFromStruct] {} {} +// CHECK:STDOUT: %ConvertToBadBaseStruct.decl: %ConvertToBadBaseStruct.type = fn_decl @ConvertToBadBaseStruct [template = constants.%ConvertToBadBaseStruct] { +// CHECK:STDOUT: %p.patt: %.4 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromStruct.ref: type = name_ref DeriveFromStruct, file.%DeriveFromStruct.decl [template = constants.%DeriveFromStruct] +// CHECK:STDOUT: %.loc21_46: type = ptr_type %DeriveFromStruct [template = constants.%.4] +// CHECK:STDOUT: %p.param: %.4 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.4 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32.loc21_57: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc21_57.1: type = value_of_initializer %int.make_type_32.loc21_57 [template = i32] +// CHECK:STDOUT: %.loc21_57.2: type = converted %int.make_type_32.loc21_57, %.loc21_57.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc21_66: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc21_66.1: type = value_of_initializer %int.make_type_32.loc21_66 [template = i32] +// CHECK:STDOUT: %.loc21_66.2: type = converted %int.make_type_32.loc21_66, %.loc21_66.1 [template = i32] +// CHECK:STDOUT: %.loc21_69: type = struct_type {.a: i32, .b: i32} [template = constants.%.2] +// CHECK:STDOUT: %.loc21_70: type = ptr_type %.2 [template = constants.%.3] +// CHECK:STDOUT: %return: ref %.3 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBaseStruct.decl: %AccessMemberWithInvalidBaseStruct.type = fn_decl @AccessMemberWithInvalidBaseStruct [template = constants.%AccessMemberWithInvalidBaseStruct] { +// CHECK:STDOUT: %p.patt: %.4 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromStruct.ref: type = name_ref DeriveFromStruct, file.%DeriveFromStruct.decl [template = constants.%DeriveFromStruct] +// CHECK:STDOUT: %.loc24_57: type = ptr_type %DeriveFromStruct [template = constants.%.4] +// CHECK:STDOUT: %p.param: %.4 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.4 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc24_63.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc24_63.2: type = converted %int.make_type_32, %.loc24_63.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] // CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromIncomplete { -// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] -// CHECK:STDOUT: %.loc116: = base_decl , element0 [template] -// CHECK:STDOUT: %.loc117: = complete_type_witness [template = ] +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.5) = assoc_entity element0, imports.%import_ref.6 [symbolic = %.2 (constants.%.6)] // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromIncomplete -// CHECK:STDOUT: .base = %.loc116 -// CHECK:STDOUT: has_error +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: .Convert = imports.%import_ref.4 +// CHECK:STDOUT: witness = (imports.%import_ref.5) +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @DeriveFromFinal { -// CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] -// CHECK:STDOUT: %.loc135: %.37 = base_decl %Final, element0 [template] -// CHECK:STDOUT: %.loc136: = complete_type_witness %.38 [template = constants.%.39] +// CHECK:STDOUT: class @DeriveFromStruct { +// CHECK:STDOUT: %int.make_type_32.loc9_21: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc9_21.1: type = value_of_initializer %int.make_type_32.loc9_21 [template = i32] +// CHECK:STDOUT: %.loc9_21.2: type = converted %int.make_type_32.loc9_21, %.loc9_21.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc9_30: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc9_30.1: type = value_of_initializer %int.make_type_32.loc9_30 [template = i32] +// CHECK:STDOUT: %.loc9_30.2: type = converted %int.make_type_32.loc9_30, %.loc9_30.1 [template = i32] +// CHECK:STDOUT: %.loc9_33: type = struct_type {.a: i32, .b: i32} [template = constants.%.2] +// CHECK:STDOUT: %.loc9_34: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness [template = ] // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%DeriveFromFinal -// CHECK:STDOUT: .base = %.loc135 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: .Self = constants.%DeriveFromStruct +// CHECK:STDOUT: .base = %.loc9_34 +// CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseError(%p: %.7) -> i32 { +// CHECK:STDOUT: fn @ConvertToBadBaseStruct(%p: %.4) -> %.3 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.7 = name_ref p, %p -// CHECK:STDOUT: %.loc25_75: ref %DeriveFromError = deref %p.ref -// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] +// CHECK:STDOUT: %p.ref: %.4 = name_ref p, %p +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.3) [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %.loc21_82.1: %.7 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.3) [template = constants.%.8] +// CHECK:STDOUT: %Convert.ref: %.7 = name_ref Convert, %.loc21_82.1 [template = constants.%.8] +// CHECK:STDOUT: %.loc21_82.2: %.3 = converted %p.ref, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -632,113 +927,191 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBasNonType(%p: %.14) -> i32 { +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseStruct(%p: %.4) -> i32 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.14 = name_ref p, %p -// CHECK:STDOUT: %.loc38_78: ref %DeriveFromNonType = deref %p.ref +// CHECK:STDOUT: %p.ref: %.4 = name_ref p, %p +// CHECK:STDOUT: %.loc24_77: ref %DeriveFromStruct = deref %p.ref // CHECK:STDOUT: %n.ref: = name_ref n, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ConvertToBadBasei32(%p: %.15) -> %.16 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.15 = name_ref p, %p -// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.16) [template = constants.%ImplicitAs.type.4] -// CHECK:STDOUT: %.loc57_61.1: %.17 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.16) [template = constants.%.18] -// CHECK:STDOUT: %Convert.ref: %.17 = name_ref Convert, %.loc57_61.1 [template = constants.%.18] -// CHECK:STDOUT: %.loc57_61.2: %.16 = converted %p.ref, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBasei32(%p: %.15) -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.15 = name_ref p, %p -// CHECK:STDOUT: %.loc59_71: ref %DeriveFromi32 = deref %p.ref -// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ConvertToBadBaseTuple(%p: %.23) -> %.24 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.23 = name_ref p, %p -// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.24) [template = constants.%ImplicitAs.type.5] -// CHECK:STDOUT: %.loc76_69.1: %.25 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.24) [template = constants.%.26] -// CHECK:STDOUT: %Convert.ref: %.25 = name_ref Convert, %.loc76_69.1 [template = constants.%.26] -// CHECK:STDOUT: %.loc76_69.2: %.24 = converted %p.ref, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseTuple(%p: %.23) -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.23 = name_ref p, %p -// CHECK:STDOUT: %.loc78_75: ref %DeriveFromTuple = deref %p.ref -// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ConvertToBadBaseStruct(%p: %.29) -> %.28 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.29 = name_ref p, %p -// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.28) [template = constants.%ImplicitAs.type.6] -// CHECK:STDOUT: %.loc97_82.1: %.30 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.28) [template = constants.%.31] -// CHECK:STDOUT: %Convert.ref: %.30 = name_ref Convert, %.loc97_82.1 [template = constants.%.31] -// CHECK:STDOUT: %.loc97_82.2: %.28 = converted %p.ref, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: specific @ImplicitAs(constants.%.3) { +// CHECK:STDOUT: %Dest => constants.%.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: %.2 => constants.%.8 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseStruct(%p: %.29) -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.29 = name_ref p, %p -// CHECK:STDOUT: %.loc100_77: ref %DeriveFromStruct = deref %p.ref -// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: --- fail_derive_from_incomplete.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Incomplete: type = class_type @Incomplete [template] +// CHECK:STDOUT: %DeriveFromIncomplete: type = class_type @DeriveFromIncomplete [template] +// CHECK:STDOUT: %.1: type = ptr_type %DeriveFromIncomplete [template] +// CHECK:STDOUT: %.2: type = ptr_type %Incomplete [template] +// CHECK:STDOUT: %ConvertToBadBaseIncomplete.type: type = fn_type @ConvertToBadBaseIncomplete [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %ConvertToBadBaseIncomplete: %ConvertToBadBaseIncomplete.type = struct_value () [template] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.4: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.5 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = interface_type @ImplicitAs, @ImplicitAs(%.2) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.2) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.5 [template] +// CHECK:STDOUT: %.8: %.4 = assoc_entity element0, imports.%import_ref.6 [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete.type: type = fn_type @AccessMemberWithInvalidBaseIncomplete [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete: %AccessMemberWithInvalidBaseIncomplete.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ConvertToBadBaseIncomplete(%p: %.32) -> %.33 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.32 = name_ref p, %p -// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.33) [template = constants.%ImplicitAs.type.7] -// CHECK:STDOUT: %.loc126_82.1: %.34 = specific_constant imports.%import_ref.4, @ImplicitAs(constants.%.33) [template = constants.%.35] -// CHECK:STDOUT: %Convert.ref: %.34 = name_ref Convert, %.loc126_82.1 [template = constants.%.35] -// CHECK:STDOUT: %.loc126_82.2: %.33 = converted %p.ref, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .ImplicitAs = %import_ref.1 +// CHECK:STDOUT: .Int32 = %import_ref.7 +// 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/as +// 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: %import_ref.1: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+40, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.2 = import_ref Core//prelude/operators/as, inst+45, unloaded +// CHECK:STDOUT: %import_ref.3: @ImplicitAs.%.1 (%.4) = import_ref Core//prelude/operators/as, inst+63, loaded [symbolic = @ImplicitAs.%.2 (constants.%.8)] +// CHECK:STDOUT: %import_ref.4 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Core//prelude/operators/as, inst+56, unloaded +// CHECK:STDOUT: %import_ref.7: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseIncomplete(%p: %.32) -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.32 = name_ref p, %p -// CHECK:STDOUT: %.loc128_85: ref %DeriveFromIncomplete = deref %p.ref -// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Incomplete = %Incomplete.decl +// CHECK:STDOUT: .DeriveFromIncomplete = %DeriveFromIncomplete.decl +// CHECK:STDOUT: .ConvertToBadBaseIncomplete = %ConvertToBadBaseIncomplete.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseIncomplete = %AccessMemberWithInvalidBaseIncomplete.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {} {} +// CHECK:STDOUT: %DeriveFromIncomplete.decl: type = class_decl @DeriveFromIncomplete [template = constants.%DeriveFromIncomplete] {} {} +// CHECK:STDOUT: %ConvertToBadBaseIncomplete.decl: %ConvertToBadBaseIncomplete.type = fn_decl @ConvertToBadBaseIncomplete [template = constants.%ConvertToBadBaseIncomplete] { +// CHECK:STDOUT: %p.patt: %.1 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] +// CHECK:STDOUT: %.loc28_54: type = ptr_type %DeriveFromIncomplete [template = constants.%.1] +// CHECK:STDOUT: %p.param: %.1 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.1 = bind_name p, %p.param +// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] +// CHECK:STDOUT: %.loc28_70: type = ptr_type %Incomplete [template = constants.%.2] +// CHECK:STDOUT: %return: ref %.2 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBaseIncomplete.decl: %AccessMemberWithInvalidBaseIncomplete.type = fn_decl @AccessMemberWithInvalidBaseIncomplete [template = constants.%AccessMemberWithInvalidBaseIncomplete] { +// CHECK:STDOUT: %p.patt: %.1 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromIncomplete.ref: type = name_ref DeriveFromIncomplete, file.%DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete] +// CHECK:STDOUT: %.loc30_65: type = ptr_type %DeriveFromIncomplete [template = constants.%.1] +// CHECK:STDOUT: %p.param: %.1 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.1 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc30_71.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc30_71.2: type = converted %int.make_type_32, %.loc30_71.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ConvertToBadBaseFinal(%p: %.40) -> %.41 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc140_11.1: ref %DeriveFromFinal = deref %p.ref -// CHECK:STDOUT: %.loc140_11.2: ref %Final = class_element_access %.loc140_11.1, element0 -// CHECK:STDOUT: %.loc140_11.3: %.41 = addr_of %.loc140_11.2 -// CHECK:STDOUT: %.loc140_11.4: %.41 = converted %p.ref, %.loc140_11.3 -// CHECK:STDOUT: return %.loc140_11.4 +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.4) = assoc_entity element0, imports.%import_ref.5 [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.2 +// CHECK:STDOUT: .Convert = imports.%import_ref.3 +// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Incomplete; +// CHECK:STDOUT: +// CHECK:STDOUT: class @DeriveFromIncomplete { +// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete] +// CHECK:STDOUT: %.loc16: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc17: = complete_type_witness [template = ] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%DeriveFromIncomplete +// CHECK:STDOUT: .base = %.loc16 +// CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_WithMember(%p: %.40) -> i32 { +// CHECK:STDOUT: fn @ConvertToBadBaseIncomplete(%p: %.1) -> %.2 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc144_11: ref %DeriveFromFinal = deref %p.ref -// CHECK:STDOUT: %a.ref: %.4 = name_ref a, @Final.%.loc13_8 [template = @Final.%.loc13_8] -// CHECK:STDOUT: %.loc144_14.1: ref %Final = class_element_access %.loc144_11, element0 -// CHECK:STDOUT: %.loc144_14.2: ref %Final = converted %.loc144_11, %.loc144_14.1 -// CHECK:STDOUT: %.loc144_14.3: ref i32 = class_element_access %.loc144_14.2, element0 -// CHECK:STDOUT: %.loc144_14.4: i32 = bind_value %.loc144_14.3 -// CHECK:STDOUT: return %.loc144_14.4 +// CHECK:STDOUT: %p.ref: %.1 = name_ref p, %p +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.2) [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %.loc28_82.1: %.6 = specific_constant imports.%import_ref.3, @ImplicitAs(constants.%.2) [template = constants.%.7] +// CHECK:STDOUT: %Convert.ref: %.6 = name_ref Convert, %.loc28_82.1 [template = constants.%.7] +// CHECK:STDOUT: %.loc28_82.2: %.2 = converted %p.ref, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_NoMember(%p: %.40) -> i32 { +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseIncomplete(%p: %.1) -> i32 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.40 = name_ref p, %p -// CHECK:STDOUT: %.loc151: ref %DeriveFromFinal = deref %p.ref -// CHECK:STDOUT: %b.ref: = name_ref b, [template = ] +// CHECK:STDOUT: %p.ref: %.1 = name_ref p, %p +// CHECK:STDOUT: %.loc30_85: ref %DeriveFromIncomplete = deref %p.ref +// CHECK:STDOUT: %n.ref: = name_ref n, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -760,63 +1133,161 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: %Self => constants.%Self.1 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @ImplicitAs(type) { -// CHECK:STDOUT: %Dest => type +// CHECK:STDOUT: specific @ImplicitAs(constants.%.2) { +// CHECK:STDOUT: %Dest => constants.%.2 // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 // CHECK:STDOUT: %Self => constants.%Self.2 // CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 // CHECK:STDOUT: %Convert => constants.%Convert.2 -// CHECK:STDOUT: %.1 => constants.%.11 -// CHECK:STDOUT: %.2 => constants.%.12 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %.2 => constants.%.7 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @ImplicitAs(constants.%.16) { -// CHECK:STDOUT: %Dest => constants.%.16 +// CHECK:STDOUT: --- fail_derive_from_final.carbon // CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.4 -// CHECK:STDOUT: %Self => constants.%Self.2 -// CHECK:STDOUT: %Convert.type => constants.%Convert.type.3 -// CHECK:STDOUT: %Convert => constants.%Convert.3 -// CHECK:STDOUT: %.1 => constants.%.17 -// CHECK:STDOUT: %.2 => constants.%.18 +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Final: type = class_type @Final [template] +// 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: %.2: type = unbound_element_type %Final, i32 [template] +// CHECK:STDOUT: %.3: type = struct_type {.a: i32} [template] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [template] +// CHECK:STDOUT: %DeriveFromFinal: type = class_type @DeriveFromFinal [template] +// CHECK:STDOUT: %.5: type = ptr_type %.3 [template] +// CHECK:STDOUT: %.6: type = unbound_element_type %DeriveFromFinal, %Final [template] +// CHECK:STDOUT: %.7: type = struct_type {.base: %Final} [template] +// CHECK:STDOUT: %.8: = complete_type_witness %.7 [template] +// CHECK:STDOUT: %.9: type = ptr_type %DeriveFromFinal [template] +// CHECK:STDOUT: %.10: type = ptr_type %Final [template] +// CHECK:STDOUT: %ConvertToBadBaseFinal.type: type = fn_type @ConvertToBadBaseFinal [template] +// CHECK:STDOUT: %ConvertToBadBaseFinal: %ConvertToBadBaseFinal.type = struct_value () [template] +// CHECK:STDOUT: %.11: type = struct_type {.base: %.5} [template] +// CHECK:STDOUT: %.12: type = ptr_type %.7 [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember.type: type = fn_type @AccessMemberWithInvalidBaseFinal_WithMember [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember: %AccessMemberWithInvalidBaseFinal_WithMember.type = struct_value () [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember.type: type = fn_type @AccessMemberWithInvalidBaseFinal_NoMember [template] +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember: %AccessMemberWithInvalidBaseFinal_NoMember.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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/as +// 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: %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 = imports.%Core +// CHECK:STDOUT: .Final = %Final.decl +// CHECK:STDOUT: .DeriveFromFinal = %DeriveFromFinal.decl +// CHECK:STDOUT: .ConvertToBadBaseFinal = %ConvertToBadBaseFinal.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseFinal_WithMember = %AccessMemberWithInvalidBaseFinal_WithMember.decl +// CHECK:STDOUT: .AccessMemberWithInvalidBaseFinal_NoMember = %AccessMemberWithInvalidBaseFinal_NoMember.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Final.decl: type = class_decl @Final [template = constants.%Final] {} {} +// CHECK:STDOUT: %DeriveFromFinal.decl: type = class_decl @DeriveFromFinal [template = constants.%DeriveFromFinal] {} {} +// CHECK:STDOUT: %ConvertToBadBaseFinal.decl: %ConvertToBadBaseFinal.type = fn_decl @ConvertToBadBaseFinal [template = constants.%ConvertToBadBaseFinal] { +// CHECK:STDOUT: %p.patt: %.9 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] +// CHECK:STDOUT: %.loc15_44: type = ptr_type %DeriveFromFinal [template = constants.%.9] +// CHECK:STDOUT: %p.param: %.9 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.9 = bind_name p, %p.param +// CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] +// CHECK:STDOUT: %.loc15_55: type = ptr_type %Final [template = constants.%.10] +// CHECK:STDOUT: %return: ref %.10 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_WithMember.decl: %AccessMemberWithInvalidBaseFinal_WithMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember [template = constants.%AccessMemberWithInvalidBaseFinal_WithMember] { +// CHECK:STDOUT: %p.patt: %.9 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] +// CHECK:STDOUT: %.loc19_66: type = ptr_type %DeriveFromFinal [template = constants.%.9] +// CHECK:STDOUT: %p.param: %.9 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.9 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc19_72.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc19_72.2: type = converted %int.make_type_32, %.loc19_72.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AccessMemberWithInvalidBaseFinal_NoMember.decl: %AccessMemberWithInvalidBaseFinal_NoMember.type = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember [template = constants.%AccessMemberWithInvalidBaseFinal_NoMember] { +// CHECK:STDOUT: %p.patt: %.9 = binding_pattern p +// CHECK:STDOUT: } { +// CHECK:STDOUT: %DeriveFromFinal.ref: type = name_ref DeriveFromFinal, file.%DeriveFromFinal.decl [template = constants.%DeriveFromFinal] +// CHECK:STDOUT: %.loc23_64: type = ptr_type %DeriveFromFinal [template = constants.%.9] +// CHECK:STDOUT: %p.param: %.9 = param p, runtime_param0 +// CHECK:STDOUT: %p: %.9 = bind_name p, %p.param +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc23_70.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc23_70.2: type = converted %int.make_type_32, %.loc23_70.1 [template = i32] +// CHECK:STDOUT: %return: ref i32 = var +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @ImplicitAs(constants.%.24) { -// CHECK:STDOUT: %Dest => constants.%.24 +// CHECK:STDOUT: class @Final { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc3_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc3_10.2: type = converted %int.make_type_32, %.loc3_10.1 [template = i32] +// CHECK:STDOUT: %.loc3_8: %.2 = field_decl a, element0 [template] +// CHECK:STDOUT: %.loc4: = complete_type_witness %.3 [template = constants.%.4] // CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.5 -// CHECK:STDOUT: %Self => constants.%Self.2 -// CHECK:STDOUT: %Convert.type => constants.%Convert.type.4 -// CHECK:STDOUT: %Convert => constants.%Convert.4 -// CHECK:STDOUT: %.1 => constants.%.25 -// CHECK:STDOUT: %.2 => constants.%.26 +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Final +// CHECK:STDOUT: .a = %.loc3_8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @DeriveFromFinal { +// CHECK:STDOUT: %Final.ref: type = name_ref Final, file.%Final.decl [template = constants.%Final] +// CHECK:STDOUT: %.loc11: %.6 = base_decl %Final, element0 [template] +// CHECK:STDOUT: %.loc12: = complete_type_witness %.7 [template = constants.%.8] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%DeriveFromFinal +// CHECK:STDOUT: .base = %.loc11 +// CHECK:STDOUT: extend name_scope2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @ImplicitAs(constants.%.28) { -// CHECK:STDOUT: %Dest => constants.%.28 +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.6 -// CHECK:STDOUT: %Self => constants.%Self.2 -// CHECK:STDOUT: %Convert.type => constants.%Convert.type.5 -// CHECK:STDOUT: %Convert => constants.%Convert.5 -// CHECK:STDOUT: %.1 => constants.%.30 -// CHECK:STDOUT: %.2 => constants.%.31 +// CHECK:STDOUT: fn @ConvertToBadBaseFinal(%p: %.9) -> %.10 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.9 = name_ref p, %p +// CHECK:STDOUT: %.loc16_11.1: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %.loc16_11.2: ref %Final = class_element_access %.loc16_11.1, element0 +// CHECK:STDOUT: %.loc16_11.3: %.10 = addr_of %.loc16_11.2 +// CHECK:STDOUT: %.loc16_11.4: %.10 = converted %p.ref, %.loc16_11.3 +// CHECK:STDOUT: return %.loc16_11.4 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @ImplicitAs(constants.%.33) { -// CHECK:STDOUT: %Dest => constants.%.33 +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_WithMember(%p: %.9) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.9 = name_ref p, %p +// CHECK:STDOUT: %.loc20_11: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Final.%.loc3_8 [template = @Final.%.loc3_8] +// CHECK:STDOUT: %.loc20_14.1: ref %Final = class_element_access %.loc20_11, element0 +// CHECK:STDOUT: %.loc20_14.2: ref %Final = converted %.loc20_11, %.loc20_14.1 +// CHECK:STDOUT: %.loc20_14.3: ref i32 = class_element_access %.loc20_14.2, element0 +// CHECK:STDOUT: %.loc20_14.4: i32 = bind_value %.loc20_14.3 +// CHECK:STDOUT: return %.loc20_14.4 +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.7 -// CHECK:STDOUT: %Self => constants.%Self.2 -// CHECK:STDOUT: %Convert.type => constants.%Convert.type.6 -// CHECK:STDOUT: %Convert => constants.%Convert.6 -// CHECK:STDOUT: %.1 => constants.%.34 -// CHECK:STDOUT: %.2 => constants.%.35 +// CHECK:STDOUT: fn @AccessMemberWithInvalidBaseFinal_NoMember(%p: %.9) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.9 = name_ref p, %p +// CHECK:STDOUT: %.loc27: ref %DeriveFromFinal = deref %p.ref +// CHECK:STDOUT: %b.ref: = name_ref b, [template = ] +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: From bf9c0cf6ff1d0cf7da3b1433a1bab8358c8b196b Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 10 Oct 2024 00:19:58 +0000 Subject: [PATCH 8/9] Pull out a common subexpression --- toolchain/check/handle_class.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 75145bf9c4320..1bb98cd4efd8e 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -181,13 +181,13 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, auto introducer = context.decl_introducer_state_stack().Pop(); CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); + auto always_acceptable_modifiers = + KeywordModifierSet::Access | KeywordModifierSet::Extern; LimitModifiersOnDecl(context, introducer, - KeywordModifierSet::Access | KeywordModifierSet::Extern | - KeywordModifierSet::Class); + always_acceptable_modifiers | KeywordModifierSet::Class); if (!is_definition) { - LimitModifiersOnNotDefinition( - context, introducer, - KeywordModifierSet::Access | KeywordModifierSet::Extern); + LimitModifiersOnNotDefinition(context, introducer, + always_acceptable_modifiers); } RestrictExternModifierOnDecl(context, introducer, parent_scope_inst, is_definition); From cfc5940c43421c4a82d3869e8ef0c6b9d1b59247 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 10 Oct 2024 00:27:04 +0000 Subject: [PATCH 9/9] Bit more fixing for tests now that I understand split tests better --- .../check/testdata/class/fail_abstract.carbon | 139 +++++------------- 1 file changed, 37 insertions(+), 102 deletions(-) diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index b1ebd03c374e5..676de7cd67f32 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -9,7 +9,7 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_abstract.carbon -// --- fail_rejects_valid_abstract_subobject_construction.carbon +// --- fail_todo_rejects_valid_abstract_subobject_construction.carbon abstract class Abstract { var a: i32; } @@ -22,28 +22,23 @@ class Derived { fn Make() -> Derived { // TODO: This should be valid, and should construct an instance of `partial Abstract` as the base. - // CHECK:STDERR: fail_rejects_valid_abstract_subobject_construction.carbon:[[@LINE+8]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead + // CHECK:STDERR: fail_todo_rejects_valid_abstract_subobject_construction.carbon:[[@LINE+6]]:19: error: cannot construct instance of abstract class; consider using `partial Abstract` instead // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: - // CHECK:STDERR: base_abstract_subobject_access.carbon: error: `Main//default` previously provided by `fail_rejects_valid_abstract_subobject_construction.carbon` - // CHECK:STDERR: - // CHECK:STDERR: fail_abstract_decl.carbon: error: `Main//default` previously provided by `fail_rejects_valid_abstract_subobject_construction.carbon` + // CHECK:STDERR: fail_todo_rejects_valid_abstract_subobject_access.carbon: error: `Main//default` previously provided by `fail_todo_rejects_valid_abstract_subobject_construction.carbon` // CHECK:STDERR: return {.base = {.a = 1}, .d = 7}; } -// --- base_abstract_subobject_access.carbon -abstract class Abstract { - var a: i32; -} - -class Derived { - extend base: Abstract; - - var d: i32; -} +// --- fail_todo_rejects_valid_abstract_subobject_access.carbon +// CHECK:STDERR: fail_todo_rejects_valid_abstract_subobject_access.carbon:[[@LINE+6]]:14: error: name `Derived` not found +// CHECK:STDERR: fn Access(d: Derived) -> (i32, i32) { +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_abstract_decl.carbon: error: `Main//default` previously provided by `fail_todo_rejects_valid_abstract_subobject_construction.carbon` +// CHECK:STDERR: fn Access(d: Derived) -> (i32, i32) { return (d.d, d.base.a); } @@ -54,7 +49,7 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDERR: ^~~~~~~~ abstract class AbstractDecl; -// CHECK:STDOUT: --- fail_rejects_valid_abstract_subobject_construction.carbon +// CHECK:STDOUT: --- fail_todo_rejects_valid_abstract_subobject_construction.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %Abstract: type = class_type @Abstract [template] @@ -143,37 +138,24 @@ abstract class AbstractDecl; // CHECK:STDOUT: // CHECK:STDOUT: fn @Make() -> %return: %Derived { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc21_25: i32 = int_literal 1 [template = constants.%.13] -// CHECK:STDOUT: %.loc21_26: %.3 = struct_literal (%.loc21_25) -// CHECK:STDOUT: %.loc21_34: i32 = int_literal 7 [template = constants.%.14] -// CHECK:STDOUT: %.loc21_35: %.15 = struct_literal (%.loc21_26, %.loc21_34) +// CHECK:STDOUT: %.loc19_25: i32 = int_literal 1 [template = constants.%.13] +// CHECK:STDOUT: %.loc19_26: %.3 = struct_literal (%.loc19_25) +// CHECK:STDOUT: %.loc19_34: i32 = int_literal 7 [template = constants.%.14] +// CHECK:STDOUT: %.loc19_35: %.15 = struct_literal (%.loc19_26, %.loc19_34) // CHECK:STDOUT: return to %return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- base_abstract_subobject_access.carbon +// CHECK:STDOUT: --- fail_todo_rejects_valid_abstract_subobject_access.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %Abstract: type = class_type @Abstract [template] // 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: %.2: type = unbound_element_type %Abstract, i32 [template] -// CHECK:STDOUT: %.3: type = struct_type {.a: i32} [template] -// CHECK:STDOUT: %.4: = complete_type_witness %.3 [template] -// CHECK:STDOUT: %Derived: type = class_type @Derived [template] -// CHECK:STDOUT: %.5: type = ptr_type %.3 [template] -// CHECK:STDOUT: %.6: type = unbound_element_type %Derived, %Abstract [template] -// CHECK:STDOUT: %.7: type = unbound_element_type %Derived, i32 [template] -// CHECK:STDOUT: %.8: type = struct_type {.base: %Abstract, .d: i32} [template] -// CHECK:STDOUT: %.9: = complete_type_witness %.8 [template] -// CHECK:STDOUT: %.10: type = tuple_type (type, type) [template] -// CHECK:STDOUT: %.11: type = tuple_type (i32, i32) [template] +// CHECK:STDOUT: %.2: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] // CHECK:STDOUT: %Access.type: type = fn_type @Access [template] // CHECK:STDOUT: %Access: %Access.type = struct_value () [template] -// CHECK:STDOUT: %.12: type = ptr_type %.11 [template] -// CHECK:STDOUT: %.13: type = struct_type {.base: %.5, .d: i32} [template] -// CHECK:STDOUT: %.14: type = ptr_type %.13 [template] -// CHECK:STDOUT: %.15: type = ptr_type %.8 [template] +// CHECK:STDOUT: %.4: type = ptr_type %.3 [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -194,82 +176,35 @@ abstract class AbstractDecl; // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .Abstract = %Abstract.decl -// CHECK:STDOUT: .Derived = %Derived.decl // CHECK:STDOUT: .Access = %Access.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %Abstract.decl: type = class_decl @Abstract [template = constants.%Abstract] {} {} -// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [template = constants.%Derived] {} {} // CHECK:STDOUT: %Access.decl: %Access.type = fn_decl @Access [template = constants.%Access] { -// CHECK:STDOUT: %d.patt: %Derived = binding_pattern d +// CHECK:STDOUT: %d.patt: = binding_pattern d // CHECK:STDOUT: } { -// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived] -// CHECK:STDOUT: %d.param: %Derived = param d, runtime_param0 -// CHECK:STDOUT: %d: %Derived = bind_name d, %d.param -// CHECK:STDOUT: %int.make_type_32.loc11_27: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc11_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc11_35.1: %.10 = tuple_literal (%int.make_type_32.loc11_27, %int.make_type_32.loc11_32) -// CHECK:STDOUT: %.loc11_35.2: type = value_of_initializer %int.make_type_32.loc11_27 [template = i32] -// CHECK:STDOUT: %.loc11_35.3: type = converted %int.make_type_32.loc11_27, %.loc11_35.2 [template = i32] -// CHECK:STDOUT: %.loc11_35.4: type = value_of_initializer %int.make_type_32.loc11_32 [template = i32] -// CHECK:STDOUT: %.loc11_35.5: type = converted %int.make_type_32.loc11_32, %.loc11_35.4 [template = i32] -// CHECK:STDOUT: %.loc11_35.6: type = converted %.loc11_35.1, constants.%.11 [template = constants.%.11] -// CHECK:STDOUT: %return: ref %.11 = var +// CHECK:STDOUT: %Derived.ref: = name_ref Derived, [template = ] +// CHECK:STDOUT: %d.param: = param d, runtime_param0 +// CHECK:STDOUT: %d: = bind_name d, %d.param +// CHECK:STDOUT: %int.make_type_32.loc8_27: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc8_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_35.1: %.2 = tuple_literal (%int.make_type_32.loc8_27, %int.make_type_32.loc8_32) +// CHECK:STDOUT: %.loc8_35.2: type = value_of_initializer %int.make_type_32.loc8_27 [template = i32] +// CHECK:STDOUT: %.loc8_35.3: type = converted %int.make_type_32.loc8_27, %.loc8_35.2 [template = i32] +// CHECK:STDOUT: %.loc8_35.4: type = value_of_initializer %int.make_type_32.loc8_32 [template = i32] +// CHECK:STDOUT: %.loc8_35.5: type = converted %int.make_type_32.loc8_32, %.loc8_35.4 [template = i32] +// CHECK:STDOUT: %.loc8_35.6: type = converted %.loc8_35.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %return: ref %.3 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @Abstract { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc2_10.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc2_10.2: type = converted %int.make_type_32, %.loc2_10.1 [template = i32] -// CHECK:STDOUT: %.loc2_8: %.2 = field_decl a, element0 [template] -// CHECK:STDOUT: %.loc3: = complete_type_witness %.3 [template = constants.%.4] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Abstract -// CHECK:STDOUT: .a = %.loc2_8 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @Derived { -// CHECK:STDOUT: %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract] -// CHECK:STDOUT: %.loc6: %.6 = base_decl %Abstract, element0 [template] -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc8_10.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc8_10.2: type = converted %int.make_type_32, %.loc8_10.1 [template = i32] -// CHECK:STDOUT: %.loc8_8: %.7 = field_decl d, element1 [template] -// CHECK:STDOUT: %.loc9: = complete_type_witness %.8 [template = constants.%.9] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .base = %.loc6 -// CHECK:STDOUT: .d = %.loc8_8 -// CHECK:STDOUT: extend name_scope2 -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Access(%d: %Derived) -> %return: %.11 { +// CHECK:STDOUT: fn @Access(%d: ) -> %return: %.3 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %d.ref.loc12_11: %Derived = name_ref d, %d -// CHECK:STDOUT: %d.ref.loc12_12: %.7 = name_ref d, @Derived.%.loc8_8 [template = @Derived.%.loc8_8] -// CHECK:STDOUT: %.loc12_12.1: ref i32 = class_element_access %d.ref.loc12_11, element1 -// CHECK:STDOUT: %.loc12_12.2: i32 = bind_value %.loc12_12.1 -// CHECK:STDOUT: %d.ref.loc12_16: %Derived = name_ref d, %d -// CHECK:STDOUT: %base.ref: %.6 = name_ref base, @Derived.%.loc6 [template = @Derived.%.loc6] -// CHECK:STDOUT: %.loc12_17.1: ref %Abstract = class_element_access %d.ref.loc12_16, element0 -// CHECK:STDOUT: %.loc12_17.2: %Abstract = bind_value %.loc12_17.1 -// CHECK:STDOUT: %a.ref: %.2 = name_ref a, @Abstract.%.loc2_8 [template = @Abstract.%.loc2_8] -// CHECK:STDOUT: %.loc12_22.1: ref i32 = class_element_access %.loc12_17.2, element0 -// CHECK:STDOUT: %.loc12_22.2: i32 = bind_value %.loc12_22.1 -// CHECK:STDOUT: %.loc12_24.1: %.11 = tuple_literal (%.loc12_12.2, %.loc12_22.2) -// CHECK:STDOUT: %.loc12_24.2: ref i32 = tuple_access %return, element0 -// CHECK:STDOUT: %.loc12_24.3: init i32 = initialize_from %.loc12_12.2 to %.loc12_24.2 -// CHECK:STDOUT: %.loc12_24.4: ref i32 = tuple_access %return, element1 -// CHECK:STDOUT: %.loc12_24.5: init i32 = initialize_from %.loc12_22.2 to %.loc12_24.4 -// CHECK:STDOUT: %.loc12_24.6: init %.11 = tuple_init (%.loc12_24.3, %.loc12_24.5) to %return -// CHECK:STDOUT: %.loc12_25: init %.11 = converted %.loc12_24.1, %.loc12_24.6 -// CHECK:STDOUT: return %.loc12_25 to %return +// CHECK:STDOUT: %d.ref.loc9_11: = name_ref d, %d +// CHECK:STDOUT: %d.ref.loc9_16: = name_ref d, %d +// CHECK:STDOUT: %.loc9: = tuple_literal (, ) +// CHECK:STDOUT: return to %return // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_abstract_decl.carbon