diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 012ed23d9017..c48bc18b05e0 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1109,7 +1109,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc, eval_context.insts().Get(call.callee_id).type_id()); CARBON_KIND_SWITCH(type_inst) { case CARBON_KIND(SemIR::GenericClassType generic_class): { - auto specific_id = MakeSpecific( + auto specific_id = MakeSpecificIfGeneric( eval_context.context(), eval_context.classes().Get(generic_class.class_id).generic_id, call.args_id); @@ -1121,11 +1121,12 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc, phase); } case CARBON_KIND(SemIR::GenericInterfaceType generic_interface): { - auto specific_id = MakeSpecific(eval_context.context(), - eval_context.interfaces() - .Get(generic_interface.interface_id) - .generic_id, - call.args_id); + auto specific_id = + MakeSpecificIfGeneric(eval_context.context(), + eval_context.interfaces() + .Get(generic_interface.interface_id) + .generic_id, + call.args_id); return MakeConstantResult( eval_context.context(), SemIR::InterfaceType{.type_id = call.type_id, @@ -1286,7 +1287,7 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, case CARBON_KIND(SemIR::ClassDecl class_decl): { // If the class has generic parameters, we don't produce a class type, but // a callable whose return value is a class type. - if (eval_context.classes().Get(class_decl.class_id).is_generic()) { + if (eval_context.classes().Get(class_decl.class_id).has_parameters()) { return TransformIfFieldsAreConstant( eval_context, class_decl, [&](SemIR::ClassDecl result) { @@ -1309,7 +1310,7 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, // type, but a callable whose return value is an interface type. if (eval_context.interfaces() .Get(interface_decl.interface_id) - .is_generic()) { + .has_parameters()) { return TransformIfFieldsAreConstant( eval_context, interface_decl, [&](SemIR::InterfaceDecl result) { diff --git a/toolchain/check/generic.h b/toolchain/check/generic.h index 4008bd1f1746..2065353f7829 100644 --- a/toolchain/check/generic.h +++ b/toolchain/check/generic.h @@ -47,6 +47,15 @@ auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id, auto MakeSpecific(Context& context, SemIR::GenericId generic_id, SemIR::InstBlockId args_id) -> SemIR::SpecificId; +// Builds a new specific if the given generic is valid. Otherwise returns an +// invalid specific. +inline auto MakeSpecificIfGeneric(Context& context, SemIR::GenericId generic_id, + SemIR::InstBlockId args_id) + -> SemIR::SpecificId { + return generic_id.is_valid() ? MakeSpecific(context, generic_id, args_id) + : SemIR::SpecificId::Invalid; +} + // Builds the specific that describes how the generic should refer to itself. // For example, for a generic `G(T:! type)`, this is the specific `G(T)`. For an // invalid `generic_id`, returns an invalid specific ID. diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 49da8614a86c..cfc2bbf7bcf9 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -236,7 +236,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, // here. We should keep track of it even if the name is invalid. class_info.generic_id = FinishGenericDecl(context, class_decl_id); class_decl.class_id = context.classes().Add(class_info); - if (class_info.is_generic()) { + if (class_info.has_parameters()) { class_decl.type_id = context.GetGenericClassType(class_decl.class_id); } } else { @@ -251,17 +251,13 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, // TODO: Form this as part of building the definition, not as part of the // declaration. auto& class_info = context.classes().Get(class_decl.class_id); - if (class_info.is_generic()) { - auto specific_id = - context.generics().GetSelfSpecific(class_info.generic_id); - class_info.self_type_id = context.GetTypeIdForTypeConstant( - TryEvalInst(context, SemIR::InstId::Invalid, - SemIR::ClassType{.type_id = SemIR::TypeId::TypeType, - .class_id = class_decl.class_id, - .specific_id = specific_id})); - } else { - class_info.self_type_id = context.GetTypeIdForTypeInst(class_decl_id); - } + auto specific_id = + context.generics().GetSelfSpecific(class_info.generic_id); + class_info.self_type_id = context.GetTypeIdForTypeConstant( + TryEvalInst(context, SemIR::InstId::Invalid, + SemIR::ClassType{.type_id = SemIR::TypeId::TypeType, + .class_id = class_decl.class_id, + .specific_id = specific_id})); } if (!is_definition && context.IsImplFile() && !is_extern) { diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index fac3f83586fa..b3d2e855d2c6 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -97,7 +97,7 @@ static auto BuildInterfaceDecl(Context& context, .param_refs_id = name.params_id, .decl_id = interface_decl_id}}; interface_decl.interface_id = context.interfaces().Add(interface_info); - if (interface_info.is_generic()) { + if (interface_info.has_parameters()) { interface_decl.type_id = context.GetGenericInterfaceType(interface_decl.interface_id); } @@ -141,10 +141,9 @@ auto HandleParseNode(Context& context, interface_info.parent_scope_id); } - // Enter the interface scope. - context.scope_stack().Push( - interface_decl_id, interface_info.scope_id, - context.generics().GetSelfSpecific(interface_info.generic_id)); + auto self_specific_id = + context.generics().GetSelfSpecific(interface_info.generic_id); + StartGenericDefinition(context); context.inst_block_stack().Push(); @@ -155,18 +154,12 @@ auto HandleParseNode(Context& context, // Declare and introduce `Self`. if (!interface_info.is_defined()) { - SemIR::TypeId self_type_id = SemIR::TypeId::Invalid; - if (interface_info.is_generic()) { - auto specific_id = - context.generics().GetSelfSpecific(interface_info.generic_id); - self_type_id = context.GetTypeIdForTypeConstant( - TryEvalInst(context, SemIR::InstId::Invalid, - SemIR::InterfaceType{.type_id = SemIR::TypeId::TypeType, - .interface_id = interface_id, - .specific_id = specific_id})); - } else { - self_type_id = context.GetTypeIdForTypeInst(interface_decl_id); - } + auto interface_type = + SemIR::InterfaceType{.type_id = SemIR::TypeId::TypeType, + .interface_id = interface_id, + .specific_id = self_specific_id}; + SemIR::TypeId self_type_id = context.GetTypeIdForTypeConstant( + TryEvalInst(context, SemIR::InstId::Invalid, interface_type)); // We model `Self` as a symbolic binding whose type is the interface. // Because there is no equivalent non-symbolic value, we use `Invalid` as @@ -185,6 +178,10 @@ auto HandleParseNode(Context& context, interface_info.self_param_id); } + // Enter the interface scope. + context.scope_stack().Push(interface_decl_id, interface_info.scope_id, + self_specific_id); + // TODO: Handle the case where there's control flow in the interface body. For // example: // diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 6ffe22aa07b4..5879e6b750b8 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -1137,7 +1137,7 @@ class ImportRefResolver { {.self_type_id = SemIR::TypeId::Invalid, .inheritance_kind = import_class.inheritance_kind}}); - if (import_class.is_generic()) { + if (import_class.has_parameters()) { class_decl.type_id = context_.GetGenericClassType(class_decl.class_id); } @@ -1498,7 +1498,7 @@ class ImportRefResolver { {GetIncompleteLocalEntityBase(interface_decl_id, import_interface), {}}); - if (import_interface.is_generic()) { + if (import_interface.has_parameters()) { interface_decl.type_id = context_.GetGenericInterfaceType(interface_decl.interface_id); } diff --git a/toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon b/toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon new file mode 100644 index 000000000000..018d0c85f02a --- /dev/null +++ b/toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon @@ -0,0 +1,241 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/generic_vs_params.carbon + +class NotGenericNoParams {} +class NotGenericButParams() {} +class GenericAndParams(T:! type) {} + +class C(T:! type) { + class GenericNoParams {} + class GenericAndParams(U:! type) {} +} + +class X {} + +var a: NotGenericNoParams = {}; +var b: NotGenericButParams() = {}; +var c: GenericAndParams(X) = {}; +var d: C(X).GenericNoParams = {}; +var e: C(X).GenericAndParams(X) = {}; + +// CHECK:STDOUT: --- generic_vs_params.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %NotGenericNoParams: type = class_type @NotGenericNoParams [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %NotGenericButParams.type: type = generic_class_type @NotGenericButParams [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %NotGenericButParams.1: %NotGenericButParams.type = struct_value () [template] +// CHECK:STDOUT: %NotGenericButParams.2: type = class_type @NotGenericButParams [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %GenericAndParams.type.1: type = generic_class_type @GenericAndParams.1 [template] +// CHECK:STDOUT: %GenericAndParams.1: %GenericAndParams.type.1 = struct_value () [template] +// CHECK:STDOUT: %GenericAndParams.2: type = class_type @GenericAndParams.1, @GenericAndParams.1(%T) [symbolic] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %GenericNoParams.1: type = class_type @GenericNoParams [template] +// CHECK:STDOUT: %GenericNoParams.2: type = class_type @GenericNoParams, @GenericNoParams(%T) [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic] +// CHECK:STDOUT: %GenericAndParams.type.2: type = generic_class_type @GenericAndParams.2 [template] +// CHECK:STDOUT: %GenericAndParams.3: %GenericAndParams.type.2 = struct_value () [template] +// CHECK:STDOUT: %GenericAndParams.4: type = class_type @GenericAndParams.2, @GenericAndParams.2(%T, %U) [symbolic] +// CHECK:STDOUT: %X: type = class_type @X [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct.1: %NotGenericNoParams = struct_value () [template] +// CHECK:STDOUT: %struct.2: %NotGenericButParams.2 = struct_value () [template] +// CHECK:STDOUT: %GenericAndParams.5: type = class_type @GenericAndParams.1, @GenericAndParams.1(%X) [template] +// CHECK:STDOUT: %struct.3: %GenericAndParams.5 = struct_value () [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%X) [template] +// CHECK:STDOUT: %struct.4: %GenericNoParams.1 = struct_value () [template] +// CHECK:STDOUT: %GenericAndParams.6: type = class_type @GenericAndParams.2, @GenericAndParams.2(%X) [template] +// CHECK:STDOUT: %struct.5: %GenericAndParams.6 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .NotGenericNoParams = %NotGenericNoParams.decl +// CHECK:STDOUT: .NotGenericButParams = %NotGenericButParams.decl +// CHECK:STDOUT: .GenericAndParams = %GenericAndParams.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: .a = %a +// CHECK:STDOUT: .b = %b +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: .d = %d +// CHECK:STDOUT: .e = %e +// CHECK:STDOUT: } +// CHECK:STDOUT: %NotGenericNoParams.decl: type = class_decl @NotGenericNoParams [template = constants.%NotGenericNoParams] {} +// CHECK:STDOUT: %NotGenericButParams.decl: %NotGenericButParams.type = class_decl @NotGenericButParams [template = constants.%NotGenericButParams.1] {} +// CHECK:STDOUT: %GenericAndParams.decl: %GenericAndParams.type.1 = class_decl @GenericAndParams.1 [template = constants.%GenericAndParams.1] { +// CHECK:STDOUT: %T.loc13_24.1: type = param T +// CHECK:STDOUT: %T.loc13_24.2: type = bind_symbolic_name T 0, %T.loc13_24.1 [symbolic = @GenericAndParams.1.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %T.loc15_9.1: type = param T +// CHECK:STDOUT: %T.loc15_9.2: type = bind_symbolic_name T 0, %T.loc15_9.1 [symbolic = @C.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.decl: type = class_decl @X [template = constants.%X] {} +// CHECK:STDOUT: %NotGenericNoParams.ref: type = name_ref NotGenericNoParams, %NotGenericNoParams.decl [template = constants.%NotGenericNoParams] +// CHECK:STDOUT: %a.var: ref %NotGenericNoParams = var a +// CHECK:STDOUT: %a: ref %NotGenericNoParams = bind_name a, %a.var +// CHECK:STDOUT: %NotGenericButParams.ref: %NotGenericButParams.type = name_ref NotGenericButParams, %NotGenericButParams.decl [template = constants.%NotGenericButParams.1] +// CHECK:STDOUT: %.loc23_27: init type = call %NotGenericButParams.ref() [template = constants.%NotGenericButParams.2] +// CHECK:STDOUT: %.loc23_28.1: type = value_of_initializer %.loc23_27 [template = constants.%NotGenericButParams.2] +// CHECK:STDOUT: %.loc23_28.2: type = converted %.loc23_27, %.loc23_28.1 [template = constants.%NotGenericButParams.2] +// CHECK:STDOUT: %b.var: ref %NotGenericButParams.2 = var b +// CHECK:STDOUT: %b: ref %NotGenericButParams.2 = bind_name b, %b.var +// CHECK:STDOUT: %GenericAndParams.ref.loc24: %GenericAndParams.type.1 = name_ref GenericAndParams, %GenericAndParams.decl [template = constants.%GenericAndParams.1] +// CHECK:STDOUT: %X.ref.loc24: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc24_24: init type = call %GenericAndParams.ref.loc24(%X.ref.loc24) [template = constants.%GenericAndParams.5] +// CHECK:STDOUT: %.loc24_26.1: type = value_of_initializer %.loc24_24 [template = constants.%GenericAndParams.5] +// CHECK:STDOUT: %.loc24_26.2: type = converted %.loc24_24, %.loc24_26.1 [template = constants.%GenericAndParams.5] +// CHECK:STDOUT: %c.var: ref %GenericAndParams.5 = var c +// CHECK:STDOUT: %c: ref %GenericAndParams.5 = bind_name c, %c.var +// CHECK:STDOUT: %C.ref.loc25: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %X.ref.loc25: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc25: init type = call %C.ref.loc25(%X.ref.loc25) [template = constants.%C.3] +// CHECK:STDOUT: %GenericNoParams.ref: type = name_ref GenericNoParams, @C.%GenericNoParams.decl [template = constants.%GenericNoParams.1] +// CHECK:STDOUT: %d.var: ref %GenericNoParams.1 = var d +// CHECK:STDOUT: %d: ref %GenericNoParams.1 = bind_name d, %d.var +// CHECK:STDOUT: %C.ref.loc26: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %X.ref.loc26_10: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc26_9: init type = call %C.ref.loc26(%X.ref.loc26_10) [template = constants.%C.3] +// CHECK:STDOUT: %GenericAndParams.ref.loc26: %GenericAndParams.type.2 = name_ref GenericAndParams, @C.%GenericAndParams.decl [template = constants.%GenericAndParams.3] +// CHECK:STDOUT: %X.ref.loc26_30: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc26_29: init type = call %GenericAndParams.ref.loc26(%X.ref.loc26_30) [template = constants.%GenericAndParams.6] +// CHECK:STDOUT: %.loc26_31.1: type = value_of_initializer %.loc26_29 [template = constants.%GenericAndParams.6] +// CHECK:STDOUT: %.loc26_31.2: type = converted %.loc26_29, %.loc26_31.1 [template = constants.%GenericAndParams.6] +// CHECK:STDOUT: %e.var: ref %GenericAndParams.6 = var e +// CHECK:STDOUT: %e: ref %GenericAndParams.6 = bind_name e, %e.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @NotGenericNoParams { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%NotGenericNoParams +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @NotGenericButParams { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%NotGenericButParams.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @GenericAndParams.1(file.%T.loc13_24.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%GenericAndParams.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(file.%T.loc15_9.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %GenericNoParams.decl: type = class_decl @GenericNoParams [template = constants.%GenericNoParams.1] {} +// CHECK:STDOUT: %GenericAndParams.decl: %GenericAndParams.type.2 = class_decl @GenericAndParams.2 [template = constants.%GenericAndParams.3] { +// CHECK:STDOUT: %U.loc17_26.1: type = param U +// CHECK:STDOUT: %U.loc17_26.2: type = bind_symbolic_name U 1, %U.loc17_26.1 [symbolic = @GenericAndParams.2.%U (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: .GenericNoParams = %GenericNoParams.decl +// CHECK:STDOUT: .GenericAndParams = %GenericAndParams.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @GenericNoParams(file.%T.loc15_9.2: type) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%GenericNoParams.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @GenericAndParams.2(file.%T.loc15_9.2: type, @C.%U.loc17_26.2: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%GenericAndParams.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @X { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%X +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc22_30.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc22_30.2: init %NotGenericNoParams = class_init (), file.%a.var [template = constants.%struct.1] +// CHECK:STDOUT: %.loc22_31: init %NotGenericNoParams = converted %.loc22_30.1, %.loc22_30.2 [template = constants.%struct.1] +// CHECK:STDOUT: assign file.%a.var, %.loc22_31 +// CHECK:STDOUT: %.loc23_33.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc23_33.2: init %NotGenericButParams.2 = class_init (), file.%b.var [template = constants.%struct.2] +// CHECK:STDOUT: %.loc23_34: init %NotGenericButParams.2 = converted %.loc23_33.1, %.loc23_33.2 [template = constants.%struct.2] +// CHECK:STDOUT: assign file.%b.var, %.loc23_34 +// CHECK:STDOUT: %.loc24_31.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc24_31.2: init %GenericAndParams.5 = class_init (), file.%c.var [template = constants.%struct.3] +// CHECK:STDOUT: %.loc24_32: init %GenericAndParams.5 = converted %.loc24_31.1, %.loc24_31.2 [template = constants.%struct.3] +// CHECK:STDOUT: assign file.%c.var, %.loc24_32 +// CHECK:STDOUT: %.loc25_32.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc25_32.2: init %GenericNoParams.1 = class_init (), file.%d.var [template = constants.%struct.4] +// CHECK:STDOUT: %.loc25_33: init %GenericNoParams.1 = converted %.loc25_32.1, %.loc25_32.2 [template = constants.%struct.4] +// CHECK:STDOUT: assign file.%d.var, %.loc25_33 +// CHECK:STDOUT: %.loc26_36.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc26_36.2: init %GenericAndParams.6 = class_init (), file.%e.var [template = constants.%struct.5] +// CHECK:STDOUT: %.loc26_37: init %GenericAndParams.6 = converted %.loc26_36.1, %.loc26_36.2 [template = constants.%struct.5] +// CHECK:STDOUT: assign file.%e.var, %.loc26_37 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.1(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericNoParams(constants.%T) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.2(constants.%T, constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.1(constants.%X) { +// CHECK:STDOUT: %T => constants.%X +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %T => constants.%X +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.2(constants.%X) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon index 4b5bb43068b5..ee68f6d8866e 100644 --- a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon +++ b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon @@ -25,7 +25,8 @@ interface I { // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = interface_type @I [template] // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] -// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %C.1: type = class_type @C [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%Self) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -52,7 +53,7 @@ interface I { // CHECK:STDOUT: // CHECK:STDOUT: interface @I { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] -// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C.1] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -60,7 +61,7 @@ interface I { // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.1; +// CHECK:STDOUT: impl @impl: %C.2 as %.1; // CHECK:STDOUT: // CHECK:STDOUT: generic class @C(@I.%Self: %.1) { // CHECK:STDOUT: !definition: @@ -71,7 +72,7 @@ interface I { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .Self = constants.%C.2 // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon b/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon index 21fcd72fe854..b7b9315f383e 100644 --- a/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon +++ b/toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon @@ -193,7 +193,8 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = interface_type @Interface [template] // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] -// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %C.1: type = class_type @C [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%Self) [symbolic] // CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F, @C(%Self) [symbolic] // CHECK:STDOUT: %.2: type = tuple_type () [template] @@ -223,9 +224,10 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %Interface.decl: type = interface_decl @Interface [template = constants.%.1] {} // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [symbolic = constants.%F.1] { -// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] -// CHECK:STDOUT: %self.loc20_18.1: %C = param self -// CHECK:STDOUT: @F.%self: %C = bind_name self, %self.loc20_18.1 +// CHECK:STDOUT: %.loc20: type = specific_constant constants.%C.2, @C(constants.%Self) [symbolic = constants.%C.2] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc20 [symbolic = constants.%C.2] +// CHECK:STDOUT: %self.loc20_18.1: %C.2 = param self +// CHECK:STDOUT: @F.%self: %C.2 = bind_name self, %self.loc20_18.1 // CHECK:STDOUT: %U.loc20_30.1: type = param U // CHECK:STDOUT: @F.%U.loc20: type = bind_symbolic_name U 1, %U.loc20_30.1 [symbolic = constants.%U] // CHECK:STDOUT: %U.ref.loc20_43: type = name_ref U, @F.%U.loc20 [symbolic = constants.%U] @@ -238,7 +240,7 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: // CHECK:STDOUT: interface @Interface { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] -// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C.1] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -254,9 +256,10 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: // CHECK:STDOUT: class { // CHECK:STDOUT: %F.decl: @C.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { -// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] -// CHECK:STDOUT: %self.loc14_10.1: %C = param self -// CHECK:STDOUT: %self.loc14_10.2: %C = bind_name self, %self.loc14_10.1 +// CHECK:STDOUT: %.loc14: type = specific_constant constants.%C.2, @C(constants.%Self) [symbolic = @F.%C (constants.%C.2)] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc14 [symbolic = @F.%C (constants.%C.2)] +// CHECK:STDOUT: %self.loc14_10.1: @F.%C (%C.2) = param self +// CHECK:STDOUT: %self.loc14_10.2: @F.%C (%C.2) = bind_name self, %self.loc14_10.1 // CHECK:STDOUT: %U.loc14_22.1: type = param U // CHECK:STDOUT: %U.loc14_22.2: type = bind_symbolic_name U 1, %U.loc14_22.1 [symbolic = @F.%U.1 (constants.%U)] // CHECK:STDOUT: %U.ref.loc14_35: type = name_ref U, %U.loc14_22.2 [symbolic = @F.%U.1 (constants.%U)] @@ -267,17 +270,19 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .Self = constants.%C.2 // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F(@Interface.%Self: %.1, @C.%U.loc14_22.2: type) { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C.2)] // CHECK:STDOUT: %U.1: type = bind_symbolic_name U 1 [symbolic = %U.1 (constants.%U)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn[%self: %C](%U.loc20: type, %u: %U) -> %U { +// CHECK:STDOUT: fn[%self: %C.2](%U.loc20: type, %u: %U) -> %U { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %u.ref: @F.%U.1 (%U) = name_ref u, %u // CHECK:STDOUT: return %u.ref @@ -291,7 +296,11 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; } // CHECK:STDOUT: %F => constants.%F.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @C(@F.%Self) {} +// CHECK:STDOUT: // CHECK:STDOUT: specific @F(constants.%Self, constants.%U) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %C => constants.%C.2 // CHECK:STDOUT: %U.1 => constants.%U // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon index e88b08f03173..86b98150eee7 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon @@ -42,10 +42,11 @@ interface Outer { // CHECK:STDOUT: %.3: type = interface_type @Outer [template] // CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %.4: type = interface_type @Inner [template] -// CHECK:STDOUT: %Self.3: %.4 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %.5: type = interface_type @Inner, @Inner(%Self.2) [symbolic] +// CHECK:STDOUT: %Self.3: %.5 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.type: type = fn_type @.1, @Inner(%Self.2) [symbolic] -// CHECK:STDOUT: %.5: %.type = struct_value () [symbolic] // CHECK:STDOUT: %.6: %.type = struct_value () [symbolic] +// CHECK:STDOUT: %.7: %.type = struct_value () [symbolic] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2, @Inner(%Self.2) [symbolic] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] // CHECK:STDOUT: } @@ -82,14 +83,15 @@ interface Outer { // CHECK:STDOUT: // CHECK:STDOUT: generic interface @Inner(@Outer.%Self: %.3) { // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] -// CHECK:STDOUT: %Self.3: %.3 = bind_symbolic_name Self 0 [symbolic = %Self.3 (constants.%Self.2)] -// CHECK:STDOUT: %.type: type = fn_type @.1, @Inner(%Self.3) [symbolic = %.type (constants.%.type)] -// CHECK:STDOUT: %.1: @Inner.%.type (%.type) = struct_value () [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self.2)] +// CHECK:STDOUT: %.1: type = interface_type @Inner, @Inner(%Self.2) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %Self.3: %.5 = bind_symbolic_name Self 1 [symbolic = %Self.3 (constants.%Self.3)] +// CHECK:STDOUT: %.type: type = fn_type @.1, @Inner(%Self.2) [symbolic = %.type (constants.%.type)] +// CHECK:STDOUT: %.2: @Inner.%.type (%.type) = struct_value () [symbolic = %.2 (constants.%.6)] // CHECK:STDOUT: // CHECK:STDOUT: interface { -// CHECK:STDOUT: %Self.1: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] -// CHECK:STDOUT: %.decl: @Inner.%.type (%.type) = fn_decl @.1 [symbolic = %.1 (constants.%.5)] {} +// CHECK:STDOUT: %Self.1: @Inner.%.1 (%.5) = bind_symbolic_name Self 1 [symbolic = %Self.3 (constants.%Self.3)] +// CHECK:STDOUT: %.decl: @Inner.%.type (%.type) = fn_decl @.1 [symbolic = %.2 (constants.%.6)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 @@ -107,12 +109,12 @@ interface Outer { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @.1(@Outer.%Self: %.3, @Inner.%Self.1: %.4) { +// CHECK:STDOUT: generic fn @.1(@Outer.%Self: %.3, @Inner.%Self.1: @Inner.%.1 (%.5)) { // CHECK:STDOUT: // CHECK:STDOUT: fn(); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.2(@Outer.%Self: %.3, @Inner.%Self.1: %.4) { +// CHECK:STDOUT: generic fn @F.2(@Outer.%Self: %.3, @Inner.%Self.1: @Inner.%.1 (%.5)) { // CHECK:STDOUT: // CHECK:STDOUT: fn(); // CHECK:STDOUT: } @@ -121,15 +123,16 @@ interface Outer { // CHECK:STDOUT: // CHECK:STDOUT: specific @Inner(constants.%Self.2) { // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Self.2 => constants.%Self.3 -// CHECK:STDOUT: %Self.3 => constants.%Self.2 +// CHECK:STDOUT: %Self.2 => constants.%Self.2 +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %Self.3 => constants.%Self.3 // CHECK:STDOUT: %.type => constants.%.type -// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %.2 => constants.%.7 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @.1(constants.%Self.2, constants.%Self.3) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @Inner(@Inner.%Self.3) {} +// CHECK:STDOUT: specific @Inner(@Inner.%Self.2) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @F.2(constants.%Self.2, constants.%Self.3) {} // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic_vs_params.carbon b/toolchain/check/testdata/interface/no_prelude/generic_vs_params.carbon new file mode 100644 index 000000000000..c00228d06ca9 --- /dev/null +++ b/toolchain/check/testdata/interface/no_prelude/generic_vs_params.carbon @@ -0,0 +1,280 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interface/no_prelude/generic_vs_params.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interface/no_prelude/generic_vs_params.carbon + +interface NotGenericNoParams {} +interface NotGenericButParams() {} +interface GenericAndParams(T:! type) {} + +class C(T:! type) { + interface GenericNoParams {} + interface GenericAndParams(U:! type) {} +} + +class X {} +impl X as NotGenericNoParams {} +impl X as NotGenericButParams() {} +impl X as GenericAndParams(X) {} +impl X as C(X).GenericNoParams {} +impl X as C(X).GenericAndParams(X) {} + +// CHECK:STDOUT: --- generic_vs_params.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @NotGenericNoParams [template] +// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %NotGenericButParams.type: type = generic_interface_type @NotGenericButParams [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %NotGenericButParams: %NotGenericButParams.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = interface_type @NotGenericButParams [template] +// CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %GenericAndParams.type.1: type = generic_interface_type @GenericAndParams.1 [template] +// CHECK:STDOUT: %GenericAndParams.1: %GenericAndParams.type.1 = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @GenericAndParams.1, @GenericAndParams.1(%T) [symbolic] +// CHECK:STDOUT: %Self.3: %.4 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %.5: type = interface_type @GenericNoParams [template] +// CHECK:STDOUT: %.6: type = interface_type @GenericNoParams, @GenericNoParams(%T) [symbolic] +// CHECK:STDOUT: %Self.4: %.6 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic] +// CHECK:STDOUT: %GenericAndParams.type.2: type = generic_interface_type @GenericAndParams.2 [template] +// CHECK:STDOUT: %GenericAndParams.2: %GenericAndParams.type.2 = struct_value () [template] +// CHECK:STDOUT: %.7: type = interface_type @GenericAndParams.2, @GenericAndParams.2(%T, %U) [symbolic] +// CHECK:STDOUT: %Self.5: %.7 = bind_symbolic_name Self 2 [symbolic] +// CHECK:STDOUT: %.8: type = struct_type {} [template] +// CHECK:STDOUT: %X: type = class_type @X [template] +// CHECK:STDOUT: %.9: = interface_witness () [template] +// CHECK:STDOUT: %.10: type = interface_type @GenericAndParams.1, @GenericAndParams.1(%X) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%X) [template] +// CHECK:STDOUT: %.11: type = ptr_type %.8 [template] +// CHECK:STDOUT: %.12: type = interface_type @GenericAndParams.2, @GenericAndParams.2(%X) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .NotGenericNoParams = %NotGenericNoParams.decl +// CHECK:STDOUT: .NotGenericButParams = %NotGenericButParams.decl +// CHECK:STDOUT: .GenericAndParams = %GenericAndParams.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %NotGenericNoParams.decl: type = interface_decl @NotGenericNoParams [template = constants.%.1] {} +// CHECK:STDOUT: %NotGenericButParams.decl: %NotGenericButParams.type = interface_decl @NotGenericButParams [template = constants.%NotGenericButParams] {} +// CHECK:STDOUT: %GenericAndParams.decl: %GenericAndParams.type.1 = interface_decl @GenericAndParams.1 [template = constants.%GenericAndParams.1] { +// CHECK:STDOUT: %T.loc13_28.1: type = param T +// CHECK:STDOUT: %T.loc13_28.2: type = bind_symbolic_name T 0, %T.loc13_28.1 [symbolic = @GenericAndParams.1.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %T.loc15_9.1: type = param T +// CHECK:STDOUT: %T.loc15_9.2: type = bind_symbolic_name T 0, %T.loc15_9.1 [symbolic = @C.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.decl: type = class_decl @X [template = constants.%X] {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %X.ref.loc21: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %NotGenericNoParams.ref: type = name_ref NotGenericNoParams, %NotGenericNoParams.decl [template = constants.%.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc22_31.1: type = value_of_initializer %.loc22_30 [template = constants.%.3] +// CHECK:STDOUT: %.loc22_31.2: type = converted %.loc22_30, %.loc22_31.1 [template = constants.%.3] +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %X.ref.loc22: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %NotGenericButParams.ref: %NotGenericButParams.type = name_ref NotGenericButParams, %NotGenericButParams.decl [template = constants.%NotGenericButParams] +// CHECK:STDOUT: %.loc22_30: init type = call %NotGenericButParams.ref() [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc23_29.1: type = value_of_initializer %.loc23_27 [template = constants.%.10] +// CHECK:STDOUT: %.loc23_29.2: type = converted %.loc23_27, %.loc23_29.1 [template = constants.%.10] +// CHECK:STDOUT: impl_decl @impl.3 { +// CHECK:STDOUT: %X.ref.loc23_6: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %GenericAndParams.ref.loc23: %GenericAndParams.type.1 = name_ref GenericAndParams, %GenericAndParams.decl [template = constants.%GenericAndParams.1] +// CHECK:STDOUT: %X.ref.loc23_28: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc23_27: init type = call %GenericAndParams.ref.loc23(%X.ref.loc23_28) [template = constants.%.10] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.4 { +// CHECK:STDOUT: %X.ref.loc24_6: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %C.ref.loc24: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %X.ref.loc24_13: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc24: init type = call %C.ref.loc24(%X.ref.loc24_13) [template = constants.%C.3] +// CHECK:STDOUT: %GenericNoParams.ref: type = name_ref GenericNoParams, @C.%GenericNoParams.decl [template = constants.%.5] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc25_34.1: type = value_of_initializer %.loc25_32 [template = constants.%.12] +// CHECK:STDOUT: %.loc25_34.2: type = converted %.loc25_32, %.loc25_34.1 [template = constants.%.12] +// CHECK:STDOUT: impl_decl @impl.5 { +// CHECK:STDOUT: %X.ref.loc25_6: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %C.ref.loc25: %C.type = name_ref C, %C.decl [template = constants.%C.1] +// CHECK:STDOUT: %X.ref.loc25_13: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc25_12: init type = call %C.ref.loc25(%X.ref.loc25_13) [template = constants.%C.3] +// CHECK:STDOUT: %GenericAndParams.ref.loc25: %GenericAndParams.type.2 = name_ref GenericAndParams, @C.%GenericAndParams.decl [template = constants.%GenericAndParams.2] +// CHECK:STDOUT: %X.ref.loc25_33: type = name_ref X, %X.decl [template = constants.%X] +// CHECK:STDOUT: %.loc25_32: init type = call %GenericAndParams.ref.loc25(%X.ref.loc25_33) [template = constants.%.12] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @NotGenericNoParams { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @NotGenericButParams { +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @GenericAndParams.1(file.%T.loc13_28.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @GenericAndParams.1, @GenericAndParams.1(%T) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @GenericAndParams.1.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @GenericNoParams(file.%T.loc15_9.2: type) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @GenericNoParams, @GenericNoParams(%T) [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: %Self.2: %.6 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @GenericNoParams.%.1 (%.6) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @GenericAndParams.2(file.%T.loc15_9.2: type, @C.%U.loc17_30.2: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @GenericAndParams.2, @GenericAndParams.2(%T, %U) [symbolic = %.1 (constants.%.7)] +// CHECK:STDOUT: %Self.2: %.7 = bind_symbolic_name Self 2 [symbolic = %Self.2 (constants.%Self.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @GenericAndParams.2.%.1 (%.7) = bind_symbolic_name Self 2 [symbolic = %Self.2 (constants.%Self.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: %X as %.1 { +// CHECK:STDOUT: %.1: = interface_witness () [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: %X as %.3 { +// CHECK:STDOUT: %.1: = interface_witness () [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.3: %X as %.10 { +// CHECK:STDOUT: %.1: = interface_witness () [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.4: %X as %.5 { +// CHECK:STDOUT: %.1: = interface_witness () [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.5: %X as %.12 { +// CHECK:STDOUT: %.1: = interface_witness () [template = constants.%.9] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(file.%T.loc15_9.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %GenericNoParams.decl: type = interface_decl @GenericNoParams [template = constants.%.5] {} +// CHECK:STDOUT: %GenericAndParams.decl: %GenericAndParams.type.2 = interface_decl @GenericAndParams.2 [template = constants.%GenericAndParams.2] { +// CHECK:STDOUT: %U.loc17_30.1: type = param U +// CHECK:STDOUT: %U.loc17_30.2: type = bind_symbolic_name U 1, %U.loc17_30.1 [symbolic = @GenericAndParams.2.%U (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: .GenericNoParams = %GenericNoParams.decl +// CHECK:STDOUT: .GenericAndParams = %GenericAndParams.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @X { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%X +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.1(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.1(@GenericAndParams.1.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericNoParams(constants.%T) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericNoParams(@GenericNoParams.%T) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.2(constants.%T, constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.2(@GenericAndParams.2.%T, @GenericAndParams.2.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.1(constants.%X) { +// CHECK:STDOUT: %T => constants.%X +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %T => constants.%X +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericAndParams.2(constants.%X) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/sem_ir/entity_with_params_base.h b/toolchain/sem_ir/entity_with_params_base.h index e4d6da09a063..7a6c27e4aeec 100644 --- a/toolchain/sem_ir/entity_with_params_base.h +++ b/toolchain/sem_ir/entity_with_params_base.h @@ -54,8 +54,8 @@ struct EntityWithParamsBase { return definition_id.is_valid() ? definition_id : decl_id; } - // Determines whether this is a generic entity. - auto is_generic() const -> bool { + // Determines whether this entity has any parameter lists. + auto has_parameters() const -> bool { return implicit_param_refs_id.is_valid() || param_refs_id.is_valid(); }