Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build a generic representing the parameterization of the body of an interface by its implicit Self parameter. #4190

Draft
wants to merge 3 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Build a generic representing the parameterization of the body of an
interface by its implicit `Self` parameter.

This is distinct from the generic representing the interface itself,
which may or may not exist but doesn't have the `Self` parameter.

For formatting purposes, I've merged the inner generic into the
interface definition rather than adding a separate nested `generic`
block. That seemed like the most logical option given that an interface
definition is always generic and doesn't have parameters of its own, and
this avoids an extra level of indentation for every interface. I'm also
using the same SemIR scope name for the two generics and the interface
itself, to minimize scope qualifications.
  • Loading branch information
zygoloid committed Aug 5, 2024
commit d2fd178085b7f5219e881213f640b3554fdf68a4
4 changes: 0 additions & 4 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,10 1014,6 @@ auto Context::TryToDefineType(
builder.Emit();
return false;
}

if (interface->specific_id.is_valid()) {
ResolveSpecificDefinition(*this, interface->specific_id);
}
}

return true;
Expand Down
14 changes: 12 additions & 2 deletions toolchain/check/handle_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 145,6 @@ auto HandleParseNode(Context& context,
context.scope_stack().Push(
interface_decl_id, interface_info.scope_id,
context.generics().GetSelfSpecific(interface_info.generic_id));
StartGenericDefinition(context);

context.inst_block_stack().Push();
context.node_stack().Push(node_id, interface_id);
Expand All @@ -155,6 154,10 @@ auto HandleParseNode(Context& context,

// Declare and introduce `Self`.
if (!interface_info.is_defined()) {
// The body of the interface is treated as a separate generic because it has
// an extra generic parameter: the implicit `Self` parameter.
StartGenericDecl(context);

SemIR::TypeId self_type_id = SemIR::TypeId::Invalid;
if (interface_info.is_generic()) {
auto specific_id =
Expand Down Expand Up @@ -183,8 186,15 @@ auto HandleParseNode(Context& context,
context.name_scopes().AddRequiredName(interface_info.scope_id,
SemIR::NameId::SelfType,
interface_info.self_param_id);

interface_info.generic_with_self_id =
FinishGenericDecl(context, interface_info.self_param_id);
CARBON_CHECK(interface_info.generic_with_self_id.is_valid())
<< "Interface should always have a generic definition.";
}

StartGenericDefinition(context);

// TODO: Handle the case where there's control flow in the interface body. For
// example:
//
Expand All @@ -211,7 221,7 @@ auto HandleParseNode(Context& context, Parse::InterfaceDefinitionId /*node_id*/)
interface_info.associated_entities_id = associated_entities_id;
}

FinishGenericDefinition(context, interface_info.generic_id);
FinishGenericDefinition(context, interface_info.generic_with_self_id);

// The decl_name_stack and scopes are popped by `ProcessNodeIds`.
return true;
Expand Down
23 changes: 20 additions & 3 deletions toolchain/check/import_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 574,11 @@ class ImportRefResolver {
.Get(interface_type.interface_id)
.generic_id;
}
case CARBON_KIND(SemIR::InterfaceType interface_type): {
return context_.interfaces()
.Get(interface_type.interface_id)
.generic_with_self_id;
}
default: {
CARBON_FATAL() << "Unexpected type for generic declaration: " << type;
}
Expand Down Expand Up @@ -1496,7 1501,8 @@ class ImportRefResolver {
// Start with an incomplete interface.
interface_decl.interface_id = context_.interfaces().Add(
{GetIncompleteLocalEntityBase(interface_decl_id, import_interface),
{}});
{.generic_with_self_id = MakeIncompleteGeneric(
SemIR::InstId::Invalid, import_interface.generic_with_self_id)}});

if (import_interface.is_generic()) {
interface_decl.type_id =
Expand All @@ -1513,7 1519,9 @@ class ImportRefResolver {
// declaration.
auto AddInterfaceDefinition(const SemIR::Interface& import_interface,
SemIR::Interface& new_interface,
SemIR::InstId self_param_id) -> void {
SemIR::InstId self_param_id,
const GenericData& generic_with_self_data)
-> void {
new_interface.scope_id = context_.name_scopes().Add(
new_interface.decl_id, SemIR::NameId::Invalid,
new_interface.parent_scope_id);
Expand All @@ -1529,6 1537,12 @@ class ImportRefResolver {
new_interface.body_block_id = context_.inst_block_stack().Pop();
new_interface.self_param_id = self_param_id;

// Import the generic corresponding to the interface body.
context_.generics().Get(new_interface.generic_with_self_id).decl_id =
new_interface.self_param_id;
SetGenericData(import_interface.generic_with_self_id,
new_interface.generic_with_self_id, generic_with_self_data);

CARBON_CHECK(import_scope.extended_scopes.empty())
<< "Interfaces don't currently have extended scopes to support.";
}
Expand Down Expand Up @@ -1569,6 1583,8 @@ class ImportRefResolver {
llvm::SmallVector<SemIR::ConstantId> param_const_ids =
GetLocalParamConstantIds(import_interface.param_refs_id);
auto generic_data = GetLocalGenericData(import_interface.generic_id);
auto generic_with_self_data =
GetLocalGenericData(import_interface.generic_with_self_id);

std::optional<SemIR::InstId> self_param_id;
if (import_interface.is_defined()) {
Expand All @@ -1590,7 1606,8 @@ class ImportRefResolver {

if (import_interface.is_defined()) {
CARBON_CHECK(self_param_id);
AddInterfaceDefinition(import_interface, new_interface, *self_param_id);
AddInterfaceDefinition(import_interface, new_interface, *self_param_id,
generic_with_self_data);
}
return {.const_id = interface_const_id};
}
Expand Down
30 changes: 24 additions & 6 deletions toolchain/check/testdata/class/fail_adapt_bad_decl.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -288,21 288,31 @@ class C {
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I.1 {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1]
// CHECK:STDOUT: interface @I.1[%Self.1: %.2] {
// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.2 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self.1)]
// CHECK:STDOUT: %.loc15: %.1 = struct_literal ()
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I.2 {
// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2]
// CHECK:STDOUT: interface @I.2[%Self.1: %.3] {
// CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.3 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self.2)]
// CHECK:STDOUT: %.loc23: %.1 = struct_literal ()
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand All @@ -314,3 324,11 @@ class C {
// CHECK:STDOUT: .I = %I.decl
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @I.1[constants.%Self.1] {
// CHECK:STDOUT: %Self.2 => constants.%Self.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @I.2[constants.%Self.2] {
// CHECK:STDOUT: %Self.2 => constants.%Self.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
23 changes: 16 additions & 7 deletions toolchain/check/testdata/function/builtin/method.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -84,28 84,33 @@ var arr: [i32; 1.(I.F)(2)];
// CHECK:STDOUT: %arr: ref %.10 = bind_name arr, %arr.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self]
// CHECK:STDOUT: interface @I[%Self.1: %.1] {
// CHECK:STDOUT: %Self.2: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {
// CHECK:STDOUT: %Self.ref.loc12_14: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc12_14: %.1 = name_ref Self, %Self.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_14.1: type = facet_type_access %Self.ref.loc12_14 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_14.2: type = converted %Self.ref.loc12_14, %.loc12_14.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %self.loc12_8.1: @F.1.%Self (%Self) = param self
// CHECK:STDOUT: %self.loc12_8.2: @F.1.%Self (%Self) = bind_name self, %self.loc12_8.1
// CHECK:STDOUT: %Self.ref.loc12_27: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc12_27: %.1 = name_ref Self, %Self.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_27.1: type = facet_type_access %Self.ref.loc12_27 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_27.2: type = converted %Self.ref.loc12_27, %.loc12_27.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %other.loc12_20.1: @F.1.%Self (%Self) = param other
// CHECK:STDOUT: %other.loc12_20.2: @F.1.%Self (%Self) = bind_name other, %other.loc12_20.1
// CHECK:STDOUT: %Self.ref.loc12_36: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc12_36: %.1 = name_ref Self, %Self.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_36.1: type = facet_type_access %Self.ref.loc12_36 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc12_36.2: type = converted %Self.ref.loc12_36, %.loc12_36.1 [symbolic = @F.1.%Self (constants.%Self)]
// CHECK:STDOUT: %return.var: ref @F.1.%Self (%Self) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc12_40: %.3 = assoc_entity element0, %F.decl [template = constants.%.4]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: .F = %.loc12_40
// CHECK:STDOUT: witness = (%F.decl)
// CHECK:STDOUT: }
Expand Down Expand Up @@ -134,7 139,7 @@ var arr: [i32; 1.(I.F)(2)];
// CHECK:STDOUT: witness = %.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @F.1(@I.%Self: %.1) {
// CHECK:STDOUT: generic fn @F.1(@I.%Self.1: %.1) {
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[@I.%self.loc12_8.2: @F.1.%Self (%Self)](@I.%other.loc12_20.2: @F.1.%Self (%Self)) -> @F.1.%Self (%Self);
Expand All @@ -144,6 149,10 @@ var arr: [i32; 1.(I.F)(2)];
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F.2[@impl.%self.loc16_8.2: i32](@impl.%other.loc16_19.2: i32) -> i32 = "int.sadd";
// CHECK:STDOUT:
// CHECK:STDOUT: specific @I[constants.%Self] {
// CHECK:STDOUT: %Self.2 => constants.%Self
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%Self) {
// CHECK:STDOUT: %Self => constants.%Self
// CHECK:STDOUT: }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,40 55,49 @@ var arr: [i32; 1 2] = (3, 4, 3 4);
// CHECK:STDOUT: �d.decl: type = interface_decl @Add [template = constants.%.2] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Add {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = constants.%Self]
// CHECK:STDOUT: interface @Add[%Self.1: %.2] {
// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.2 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT: %Op.decl: %Op.type = fn_decl @Op [template = constants.%Op] {
// CHECK:STDOUT: %Self.ref.loc7_15: %.2 = name_ref Self, %Self [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc7_15: %.2 = name_ref Self, %Self.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_15.1: type = facet_type_access %Self.ref.loc7_15 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_15.2: type = converted %Self.ref.loc7_15, %.loc7_15.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %self.loc7_9.1: @Op.%Self (%Self) = param self
// CHECK:STDOUT: %self.loc7_9.2: @Op.%Self (%Self) = bind_name self, %self.loc7_9.1
// CHECK:STDOUT: %Self.ref.loc7_28: %.2 = name_ref Self, %Self [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc7_28: %.2 = name_ref Self, %Self.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_28.1: type = facet_type_access %Self.ref.loc7_28 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_28.2: type = converted %Self.ref.loc7_28, %.loc7_28.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %other.loc7_21.1: @Op.%Self (%Self) = param other
// CHECK:STDOUT: %other.loc7_21.2: @Op.%Self (%Self) = bind_name other, %other.loc7_21.1
// CHECK:STDOUT: %Self.ref.loc7_37: %.2 = name_ref Self, %Self [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref.loc7_37: %.2 = name_ref Self, %Self.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_37.1: type = facet_type_access %Self.ref.loc7_37 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc7_37.2: type = converted %Self.ref.loc7_37, %.loc7_37.1 [symbolic = @Op.%Self (constants.%Self)]
// CHECK:STDOUT: %return.var: ref @Op.%Self (%Self) = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc7_41: %.3 = assoc_entity element0, %Op.decl [template = constants.%.4]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: .Op = %.loc7_41
// CHECK:STDOUT: witness = (%Op.decl)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @Op(@Add.%Self: %.2) {
// CHECK:STDOUT: generic fn @Op(@Add.%Self.1: %.2) {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[@Add.%self.loc7_9.2: @Op.%Self (%Self)](@Add.%other.loc7_21.2: @Op.%Self (%Self)) -> @Op.%Self (%Self);
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Add[constants.%Self] {
// CHECK:STDOUT: %Self.2 => constants.%Self
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Op(constants.%Self) {
// CHECK:STDOUT: %Self => constants.%Self
// CHECK:STDOUT: }
Expand Down Expand Up @@ -131,9 140,9 @@ var arr: [i32; 1 2] = (3, 4, 3 4);
// CHECK:STDOUT: %import_ref.1: %Int32.type = import_ref Core//default, inst 2, loaded [template = constants.%Int32]
// CHECK:STDOUT: %import_ref.2: type = import_ref Core//default, inst 6, loaded [template = constants.%.2]
// CHECK:STDOUT: %import_ref.3 = import_ref Core//default, inst 8, unloaded
// CHECK:STDOUT: %import_ref.4: %.6 = import_ref Core//default, inst 29, loaded [template = constants.%.7]
// CHECK:STDOUT: %import_ref.5: %Op.type.2 = import_ref Core//default, inst 24, loaded [template = constants.%Op.2]
// CHECK:STDOUT: %import_ref.6 = import_ref Core//default, inst 24, unloaded
// CHECK:STDOUT: %import_ref.4: %.6 = import_ref Core//default, inst 30, loaded [template = constants.%.7]
// CHECK:STDOUT: %import_ref.5: %Op.type.2 = import_ref Core//default, inst 25, loaded [template = constants.%Op.2]
// CHECK:STDOUT: %import_ref.6 = import_ref Core//default, inst 25, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand Down Expand Up @@ -162,7 171,13 @@ var arr: [i32; 1 2] = (3, 4, 3 4);
// CHECK:STDOUT: %arr: ref %.10 = bind_name arr, %arr.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Add {
// CHECK:STDOUT: interface @Add[constants.%Self: %.2] {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.3
// CHECK:STDOUT: .Op = imports.%import_ref.4
Expand Down
21 changes: 15 additions & 6 deletions toolchain/check/testdata/impl/compound.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 129,17 @@ fn InstanceCallIndirect(p: i32*) {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Simple {
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self]
// CHECK:STDOUT: interface @Simple[%Self.1: %.1] {
// CHECK:STDOUT: %Self.2: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {}
// CHECK:STDOUT: %.loc12: %.3 = assoc_entity element0, %F.decl [template = constants.%.4]
// CHECK:STDOUT: %G.decl: %G.type.1 = fn_decl @G.1 [template = constants.%G.1] {
// CHECK:STDOUT: %Self.ref: %.1 = name_ref Self, %Self [symbolic = @G.1.%Self (constants.%Self)]
// CHECK:STDOUT: %Self.ref: %.1 = name_ref Self, %Self.1 [symbolic = @G.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc13_14.1: type = facet_type_access %Self.ref [symbolic = @G.1.%Self (constants.%Self)]
// CHECK:STDOUT: %.loc13_14.2: type = converted %Self.ref, %.loc13_14.1 [symbolic = @G.1.%Self (constants.%Self)]
// CHECK:STDOUT: %self.loc13_8.1: @G.1.%Self (%Self) = param self
Expand All @@ -143,7 148,7 @@ fn InstanceCallIndirect(p: i32*) {
// CHECK:STDOUT: %.loc13_21: %.5 = assoc_entity element1, %G.decl [template = constants.%.6]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: .F = %.loc12
// CHECK:STDOUT: .G = %.loc13_21
// CHECK:STDOUT: witness = (%F.decl, %G.decl)
Expand All @@ -166,12 171,12 @@ fn InstanceCallIndirect(p: i32*) {
// CHECK:STDOUT: witness = %.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @F.1(@Simple.%Self: %.1) {
// CHECK:STDOUT: generic fn @F.1(@Simple.%Self.1: %.1) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn();
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @G.1(@Simple.%Self: %.1) {
// CHECK:STDOUT: generic fn @G.1(@Simple.%Self.1: %.1) {
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[@Simple.%self.loc13_8.2: @G.1.%Self (%Self)]();
Expand Down Expand Up @@ -228,6 233,10 @@ fn InstanceCallIndirect(p: i32*) {
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Simple[constants.%Self] {
// CHECK:STDOUT: %Self.2 => constants.%Self
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%Self) {}
// CHECK:STDOUT:
// CHECK:STDOUT: specific @G.1(constants.%Self) {
Expand Down
15 changes: 12 additions & 3 deletions toolchain/check/testdata/impl/declaration.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 51,24 @@ impl i32 as I;
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self]
// CHECK:STDOUT: interface @I[%Self.1: %.1] {
// CHECK:STDOUT: %Self.2: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: !body:
// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: .Self = %Self.1
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl: i32 as %.1;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
// CHECK:STDOUT:
// CHECK:STDOUT: specific @I[constants.%Self] {
// CHECK:STDOUT: %Self.2 => constants.%Self
// CHECK:STDOUT: }
// CHECK:STDOUT:
Loading
Loading