Skip to content

Commit

Permalink
Track an interface type, not an interface ID, on an associated entity. (
Browse files Browse the repository at this point in the history
carbon-language#4188)

This prepares us for modeling associated entities of parameterized
interfaces.

We don't use the interface parameters when type-checking `impl`s or uses
of interface members yet, but we do now check interface arguments during
`impl` lookup.
  • Loading branch information
zygoloid authored Aug 5, 2024
1 parent 183c8c0 commit 8a8c227
Show file tree
Hide file tree
Showing 73 changed files with 729 additions and 166 deletions.
4 changes: 2 additions & 2 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1071,10 +1071,10 @@ auto Context::GetTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids)
type_blocks().AddCanonical(type_ids));
}

auto Context::GetAssociatedEntityType(SemIR::InterfaceId interface_id,
auto Context::GetAssociatedEntityType(SemIR::TypeId interface_type_id,
SemIR::TypeId entity_type_id)
-> SemIR::TypeId {
return GetTypeImpl<SemIR::AssociatedEntityType>(*this, interface_id,
return GetTypeImpl<SemIR::AssociatedEntityType>(*this, interface_type_id,
entity_type_id);
}

Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class Context {
// TODO: Consider moving these `Get*Type` functions to a separate class.

// Gets the type for the name of an associated entity.
auto GetAssociatedEntityType(SemIR::InterfaceId interface_id,
auto GetAssociatedEntityType(SemIR::TypeId interface_type_id,
SemIR::TypeId entity_type_id) -> SemIR::TypeId;

// Gets a builtin type. The returned type will be complete.
Expand Down
4 changes: 2 additions & 2 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,10 +1190,10 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
case SemIR::AssociatedEntity::Kind:
return RebuildIfFieldsAreConstant(eval_context, inst,
&SemIR::AssociatedEntity::type_id);

case SemIR::AssociatedEntityType::Kind:
return RebuildIfFieldsAreConstant(
eval_context, inst, &SemIR::AssociatedEntityType::entity_type_id);
eval_context, inst, &SemIR::AssociatedEntityType::interface_type_id,
&SemIR::AssociatedEntityType::entity_type_id);
case SemIR::BoundMethod::Kind:
return RebuildIfFieldsAreConstant(
eval_context, inst, &SemIR::BoundMethod::type_id,
Expand Down
12 changes: 7 additions & 5 deletions toolchain/check/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,17 @@ static auto CheckAssociatedFunctionImplementation(

// Builds a witness that the specified impl implements the given interface.
static auto BuildInterfaceWitness(
Context& context, const SemIR::Impl& impl, SemIR::InterfaceId interface_id,
Context& context, const SemIR::Impl& impl,
SemIR::InterfaceType interface_type,
llvm::SmallVectorImpl<SemIR::InstId>& used_decl_ids) -> SemIR::InstId {
const auto& interface = context.interfaces().Get(interface_id);
const auto& interface = context.interfaces().Get(interface_type.interface_id);
if (!interface.is_defined()) {
CARBON_DIAGNOSTIC(ImplOfUndefinedInterface, Error,
"Implementation of undefined interface {0}.",
SemIR::NameId);
auto builder = context.emitter().Build(
impl.definition_id, ImplOfUndefinedInterface, interface.name_id);
context.NoteUndefinedInterface(interface_id, builder);
context.NoteUndefinedInterface(interface_type.interface_id, builder);
builder.Emit();
return SemIR::InstId::BuiltinError;
}
Expand All @@ -85,6 +86,7 @@ static auto BuildInterfaceWitness(
table.reserve(assoc_entities.size());

// Substitute `Self` with the impl's self type when associated functions.
// TODO: Also substitute the arguments from interface_type.specific_id.
auto self_bind =
context.insts().GetAs<SemIR::BindSymbolicName>(interface.self_param_id);
Substitution substitutions[1] = {
Expand Down Expand Up @@ -160,8 +162,8 @@ auto BuildImplWitness(Context& context, SemIR::ImplId impl_id)

llvm::SmallVector<SemIR::InstId> used_decl_ids;

auto witness_id = BuildInterfaceWitness(
context, impl, interface_type->interface_id, used_decl_ids);
auto witness_id =
BuildInterfaceWitness(context, impl, *interface_type, used_decl_ids);

// TODO: Diagnose if any declarations in the impl are not in used_decl_ids.

Expand Down
19 changes: 3 additions & 16 deletions toolchain/check/import_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1059,28 +1059,15 @@ class ImportRefResolver {

auto initial_work = work_stack_.size();
auto entity_type_const_id = GetLocalConstantId(inst.entity_type_id);
auto interface_inst_id = GetLocalConstantInstId(
import_ir_.interfaces().Get(inst.interface_id).decl_id);
auto interface_inst_id = GetLocalConstantId(inst.interface_type_id);
if (HasNewWork(initial_work)) {
return ResolveResult::Retry();
}

// TODO: Track an interface type, not an interface ID, on
// AssociatedEntityType.
auto interface_inst = context_.insts().Get(interface_inst_id);
SemIR::InterfaceId interface_id = SemIR::InterfaceId::Invalid;
if (interface_inst.Is<SemIR::InterfaceType>()) {
interface_id = interface_inst.As<SemIR::InterfaceType>().interface_id;
} else {
interface_id =
context_.types()
.GetAs<SemIR::GenericInterfaceType>(interface_inst.type_id())
.interface_id;
}

return ResolveAs<SemIR::AssociatedEntityType>(
{.type_id = SemIR::TypeId::TypeType,
.interface_id = interface_id,
.interface_type_id =
context_.GetTypeIdForTypeConstant(interface_inst_id),
.entity_type_id =
context_.GetTypeIdForTypeConstant(entity_type_const_id)});
}
Expand Down
6 changes: 5 additions & 1 deletion toolchain/check/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
return SemIR::InstId::BuiltinError;
}

// The interface type is the type of `Self`.
auto self_type_id =
context.insts().Get(interface_info.self_param_id).type_id();

// Register this declaration as declaring an associated entity.
auto index = SemIR::ElementIndex(
context.args_type_info_stack().PeekCurrentBlockContents().size());
Expand All @@ -29,7 +33,7 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
// Name lookup for the declaration's name should name the associated entity,
// not the declaration itself.
auto type_id = context.GetAssociatedEntityType(
interface_id, context.insts().Get(decl_id).type_id());
self_type_id, context.insts().Get(decl_id).type_id());
return context.AddInst<SemIR::AssociatedEntity>(
context.insts().GetLocId(decl_id),
{.type_id = type_id, .index = index, .decl_id = decl_id});
Expand Down
22 changes: 10 additions & 12 deletions toolchain/check/member_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static auto ScopeNeedsImplLookup(Context& context, LookupScope scope) -> bool {
// Returns an invalid InstId if no matching impl is found.
static auto LookupInterfaceWitness(Context& context,
SemIR::ConstantId type_const_id,
SemIR::InterfaceId interface_id)
SemIR::TypeId interface_type_id)
-> SemIR::InstId {
// TODO: Add a better impl lookup system. At the very least, we should only be
// considering impls that are for the same interface we're querying. We can
Expand All @@ -138,16 +138,11 @@ static auto LookupInterfaceWitness(Context& context,
context.types().GetConstantId(impl.self_id), type_const_id)) {
continue;
}
auto interface_type =
context.types().TryGetAs<SemIR::InterfaceType>(impl.constraint_id);
if (!interface_type) {
if (impl.constraint_id != interface_type_id) {
// TODO: An impl of a constraint type should be treated as implementing
// the constraint's interfaces.
continue;
}
if (interface_type->interface_id != interface_id) {
continue;
}
if (!impl.witness_id.is_valid()) {
// TODO: Diagnose if the impl isn't defined yet?
return SemIR::InstId::Invalid;
Expand All @@ -164,9 +159,11 @@ static auto PerformImplLookup(Context& context, Parse::NodeId node_id,
SemIR::ConstantId type_const_id,
SemIR::AssociatedEntityType assoc_type,
SemIR::InstId member_id) -> SemIR::InstId {
auto& interface = context.interfaces().Get(assoc_type.interface_id);
auto witness_id =
LookupInterfaceWitness(context, type_const_id, assoc_type.interface_id);
auto interface_type =
context.types().GetAs<SemIR::InterfaceType>(assoc_type.interface_type_id);
auto& interface = context.interfaces().Get(interface_type.interface_id);
auto witness_id = LookupInterfaceWitness(context, type_const_id,
assoc_type.interface_type_id);
if (!witness_id.is_valid()) {
CARBON_DIAGNOSTIC(MissingImplInMemberAccess, Error,
"Cannot access member of interface {0} in type {1} "
Expand Down Expand Up @@ -194,6 +191,7 @@ static auto PerformImplLookup(Context& context, Parse::NodeId node_id,
}

// Substitute into the type declared in the interface.
// TODO: Also substitute the arguments from interface_type.specific_id.
auto self_param =
context.insts().GetAs<SemIR::BindSymbolicName>(interface.self_param_id);
Substitution substitutions[1] = {
Expand Down Expand Up @@ -252,8 +250,8 @@ static auto LookupMemberNameInScope(Context& context, Parse::NodeId node_id,
// TODO: We need to do this as part of searching extended scopes, because a
// lookup that finds an associated entity and also finds the corresponding
// impl member is not supposed to be treated as ambiguous.
if (auto assoc_type = context.types().TryGetAs<SemIR::AssociatedEntityType>(
inst.type_id())) {
if (auto assoc_type =
context.types().TryGetAs<SemIR::AssociatedEntityType>(type_id)) {
if (ScopeNeedsImplLookup(context, lookup_scope)) {
member_id = PerformImplLookup(context, node_id, name_scope_const_id,
*assoc_type, member_id);
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/function/builtin/method.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var arr: [i32; 1.(I.F)(2)];
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @I, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %Op.type: type = fn_type @Op [template]
// CHECK:STDOUT: %Op: %Op.type = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Add, %Op.type [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.2, %Op.type [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Add.%Op.decl [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand Down Expand Up @@ -108,7 +108,7 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
// CHECK:STDOUT: %.3: <witness> = interface_witness (%Op.1) [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: type = assoc_entity_type @Add, %Op.type.2 [template]
// CHECK:STDOUT: %.6: type = assoc_entity_type %.2, %Op.type.2 [template]
// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.6 [template]
// CHECK:STDOUT: %.8: <bound method> = bound_method %.4, %Op.1 [template]
// CHECK:STDOUT: %.9: i32 = int_literal 3 [template]
Expand Down
4 changes: 2 additions & 2 deletions toolchain/check/testdata/impl/compound.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ fn InstanceCallIndirect(p: i32*) {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Simple, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Simple.%F.decl [template]
// CHECK:STDOUT: %G.type.1: type = fn_type @G.1 [template]
// CHECK:STDOUT: %G.1: %G.type.1 = struct_value () [template]
// CHECK:STDOUT: %.5: type = assoc_entity_type @Simple, %G.type.1 [template]
// CHECK:STDOUT: %.5: type = assoc_entity_type %.1, %G.type.1 [template]
// CHECK:STDOUT: %.6: %.5 = assoc_entity element1, @Simple.%G.decl [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/extend_impl.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn G(c: C) {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @HasF, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @HasF.%F.decl [template]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/fail_call_invalid.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn InstanceCall(n: i32) {
// CHECK:STDOUT: %G.type.1: type = fn_type @G.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %G.1: %G.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Simple, %G.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %G.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Simple.%G.decl [template]
// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template]
// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template]
Expand Down
4 changes: 2 additions & 2 deletions toolchain/check/testdata/impl/fail_extend_impl_forall.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class C {
// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic]
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @GenericInterface(%T) [symbolic]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic]
// CHECK:STDOUT: %.3: type = assoc_entity_type @GenericInterface, %F.type.1 [symbolic]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.2, %F.type.1 [symbolic]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @GenericInterface.%F.decl [symbolic]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
Expand Down Expand Up @@ -75,7 +75,7 @@ class C {
// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)]
// CHECK:STDOUT: %F.type: type = fn_type @F.1, @GenericInterface(%T) [symbolic = %F.type (constants.%F.type.1)]
// CHECK:STDOUT: %F: @GenericInterface.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)]
// CHECK:STDOUT: %.2: type = assoc_entity_type @GenericInterface, @GenericInterface.%F.type (%F.type.1) [symbolic = %.2 (constants.%.3)]
// CHECK:STDOUT: %.2: type = assoc_entity_type @GenericInterface.%.1 (%.2), @GenericInterface.%F.type (%F.type.1) [symbolic = %.2 (constants.%.3)]
// CHECK:STDOUT: %.3: @GenericInterface.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)]
// CHECK:STDOUT:
// CHECK:STDOUT: interface {
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/fail_impl_as_scope.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl as Simple {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Simple, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Simple.%F.decl [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl bool as I {}
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = interface_type @I [template]
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %.2: type = assoc_entity_type @I, type [template]
// CHECK:STDOUT: %.2: type = assoc_entity_type %.1, type [template]
// CHECK:STDOUT: %.3: %.2 = assoc_entity element0, @I.%T [template]
// CHECK:STDOUT: %Bool.type: type = fn_type @Bool [template]
// CHECK:STDOUT: %.4: type = tuple_type () [template]
Expand Down
6 changes: 3 additions & 3 deletions toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class SelfNestedBadReturnType {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @I, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [template]
// CHECK:STDOUT: %NoF: type = class_type @NoF [template]
// CHECK:STDOUT: %.5: type = struct_type {} [template]
Expand All @@ -245,7 +245,7 @@ class SelfNestedBadReturnType {
// CHECK:STDOUT: %Self.2: %.6 = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %F.type.5: type = fn_type @F.5 [template]
// CHECK:STDOUT: %F.6: %F.type.5 = struct_value () [template]
// CHECK:STDOUT: %.7: type = assoc_entity_type @J, %F.type.5 [template]
// CHECK:STDOUT: %.7: type = assoc_entity_type %.6, %F.type.5 [template]
// CHECK:STDOUT: %.8: %.7 = assoc_entity element0, @J.%F.decl [template]
// CHECK:STDOUT: %FMissingParam: type = class_type @FMissingParam [template]
// CHECK:STDOUT: %F.type.6: type = fn_type @F.6 [template]
Expand Down Expand Up @@ -280,7 +280,7 @@ class SelfNestedBadReturnType {
// CHECK:STDOUT: %.15: type = array_type %.14, %Self.3 [symbolic]
// CHECK:STDOUT: %F.type.13: type = fn_type @F.13 [template]
// CHECK:STDOUT: %F.14: %F.type.13 = struct_value () [template]
// CHECK:STDOUT: %.16: type = assoc_entity_type @SelfNested, %F.type.13 [template]
// CHECK:STDOUT: %.16: type = assoc_entity_type %.9, %F.type.13 [template]
// CHECK:STDOUT: %.17: %.16 = assoc_entity element0, @SelfNested.%F.decl [template]
// CHECK:STDOUT: %SelfNestedBadParam: type = class_type @SelfNestedBadParam [template]
// CHECK:STDOUT: %.18: type = ptr_type %SelfNestedBadParam [template]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl bool as I where .T = bool {}
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = interface_type @I [template]
// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic]
// CHECK:STDOUT: %.2: type = assoc_entity_type @I, type [template]
// CHECK:STDOUT: %.2: type = assoc_entity_type %.1, type [template]
// CHECK:STDOUT: %.3: %.2 = assoc_entity element0, @I.%T [template]
// CHECK:STDOUT: %Bool.type: type = fn_type @Bool [template]
// CHECK:STDOUT: %.4: type = tuple_type () [template]
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/impl_as.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class C {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Simple, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Simple.%F.decl [template]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/impl_forall.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl forall [T:! type] T as Simple {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @Simple, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @Simple.%F.decl [template]
// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
Expand Down
2 changes: 1 addition & 1 deletion toolchain/check/testdata/impl/lookup/alias.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn G(c: C) {
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type @HasF, %F.type.1 [template]
// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, %F.type.1 [template]
// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @HasF.%F.decl [template]
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %.5: type = struct_type {} [template]
Expand Down
Loading

0 comments on commit 8a8c227

Please sign in to comment.