Skip to content

Commit

Permalink
Fix impl lookup to look in the arguments of a specific. (#4601)
Browse files Browse the repository at this point in the history
  • Loading branch information
zygoloid authored Dec 2, 2024
1 parent 2ae35d5 commit d0e067a
Show file tree
Hide file tree
Showing 3 changed files with 850 additions and 15 deletions.
25 changes: 21 additions & 4 deletions toolchain/check/impl_lookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ static auto FindAssociatedImportIRs(Context& context,
worklist.push_back(context.constant_values().GetInstId(type_const_id));
worklist.push_back(context.constant_values().GetInstId(interface_const_id));

// Push the contents of an instruction block onto our worklist.
auto push_block = [&](SemIR::InstBlockId block_id) {
if (block_id.is_valid()) {
auto block = context.inst_blocks().Get(block_id);
worklist.append(block.begin(), block.end());
}
};

// Add the arguments of a specific to the worklist.
auto push_args = [&](SemIR::SpecificId specific_id) {
if (specific_id.is_valid()) {
push_block(context.specifics().Get(specific_id).args_id);
}
};

while (!worklist.empty()) {
auto inst_id = worklist.pop_back_val();

Expand All @@ -52,10 +67,7 @@ static auto FindAssociatedImportIRs(Context& context,
break;
}
case SemIR::IdKind::For<SemIR::InstBlockId>: {
if (auto id = SemIR::InstBlockId(arg); id.is_valid()) {
auto block = context.inst_blocks().Get(id);
worklist.append(block.begin(), block.end());
}
push_block(SemIR::InstBlockId(arg));
break;
}
case SemIR::IdKind::For<SemIR::ClassId>: {
Expand All @@ -71,13 +83,18 @@ static auto FindAssociatedImportIRs(Context& context,
context.facet_types().Get(SemIR::FacetTypeId(arg));
for (const auto& impl : facet_type_info.impls_constraints) {
add_entity(context.interfaces().Get(impl.interface_id));
push_args(impl.specific_id);
}
break;
}
case SemIR::IdKind::For<SemIR::FunctionId>: {
add_entity(context.functions().Get(SemIR::FunctionId(arg)));
break;
}
case SemIR::IdKind::For<SemIR::SpecificId>: {
push_args(SemIR::SpecificId(arg));
break;
}
default: {
break;
}
Expand Down
34 changes: 23 additions & 11 deletions toolchain/check/testdata/impl/lookup/no_prelude/import.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn L() {
obj.(PackageHasParam.Y.K)();
}

// --- fail_todo_use_generic_interface_as_param.carbon
// --- use_generic_interface_as_param.carbon

library "[[@TEST_NAME]]";

Expand All @@ -152,10 +152,6 @@ import PackageGenericInterface;
fn M() {
var obj: PackageHasParam.AnyParam(
PackageGenericInterface.GenericInterface) = {};
// CHECK:STDERR: fail_todo_use_generic_interface_as_param.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Y` in type `AnyParam(<cannot stringify inst+38 kind StructValue>)` that does not implement that interface [MissingImplInMemberAccess]
// CHECK:STDERR: obj.(PackageHasParam.Y.K)();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
obj.(PackageHasParam.Y.K)();
}

Expand Down Expand Up @@ -1344,10 +1340,11 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @K.2(constants.%.3) {}
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_generic_interface_as_param.carbon
// CHECK:STDOUT: --- use_generic_interface_as_param.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %M.type: type = fn_type @M [template]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template]
// CHECK:STDOUT: %M: %M.type = struct_value () [template]
// CHECK:STDOUT: %AnyParam.type: type = generic_class_type @AnyParam [template]
// CHECK:STDOUT: %AnyParam.1: %AnyParam.type = struct_value () [template]
Expand All @@ -1368,9 +1365,12 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT: %struct: %AnyParam.3 = struct_value () [template]
// CHECK:STDOUT: %Y.type: type = facet_type <@Y> [template]
// CHECK:STDOUT: %Self.3: %Y.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %K.type: type = fn_type @K [template]
// CHECK:STDOUT: %.4: type = assoc_entity_type %Y.type, %K.type [template]
// CHECK:STDOUT: %K.type.1: type = fn_type @K.1 [template]
// CHECK:STDOUT: %.4: type = assoc_entity_type %Y.type, %K.type.1 [template]
// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.10 [template]
// CHECK:STDOUT: %K.type.2: type = fn_type @K.2 [template]
// CHECK:STDOUT: %K.2: %K.type.2 = struct_value () [template]
// CHECK:STDOUT: %.6: <witness> = interface_witness (%K.2) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
Expand All @@ -1392,6 +1392,9 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT: %import_ref.7 = import_ref PackageHasParam//default, inst+28, unloaded
// CHECK:STDOUT: %import_ref.8: %.4 = import_ref PackageHasParam//default, inst+34, loaded [template = constants.%.5]
// CHECK:STDOUT: %import_ref.9 = import_ref PackageHasParam//default, inst+30, unloaded
// CHECK:STDOUT: %import_ref.11: type = import_ref PackageGenericInterface//default, inst+46, loaded [template = constants.%AnyParam.3]
// CHECK:STDOUT: %import_ref.12: type = import_ref PackageGenericInterface//default, inst+56, loaded [template = constants.%Y.type]
// CHECK:STDOUT: %import_ref.13: <witness> = import_ref PackageGenericInterface//default, inst+65, loaded [template = constants.%.6]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand Down Expand Up @@ -1427,6 +1430,11 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT: witness = (imports.%import_ref.9)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl: imports.%import_ref.11 as imports.%import_ref.12 {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: witness = imports.%import_ref.13
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic class @AnyParam(constants.%T: type, constants.%X.2: @AnyParam.%T (%T)) {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt)]
Expand Down Expand Up @@ -1456,18 +1464,22 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT: %.loc9_51: init %AnyParam.3 = converted %.loc9_50.1, %.loc9_50.2 [template = constants.%struct]
// CHECK:STDOUT: assign %obj.var, %.loc9_51
// CHECK:STDOUT: %obj.ref: ref %AnyParam.3 = name_ref obj, %obj
// CHECK:STDOUT: %PackageHasParam.ref.loc14: <namespace> = name_ref PackageHasParam, imports.%PackageHasParam [template = imports.%PackageHasParam]
// CHECK:STDOUT: %PackageHasParam.ref.loc10: <namespace> = name_ref PackageHasParam, imports.%PackageHasParam [template = imports.%PackageHasParam]
// CHECK:STDOUT: %Y.ref: type = name_ref Y, imports.%import_ref.6 [template = constants.%Y.type]
// CHECK:STDOUT: %K.ref: %.4 = name_ref K, imports.%import_ref.8 [template = constants.%.5]
// CHECK:STDOUT: %.loc10: %K.type.1 = interface_witness_access constants.%.6, element0 [template = constants.%K.2]
// CHECK:STDOUT: %K.call: init %empty_tuple.type = call %.loc10()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @K(constants.%Self.3: %Y.type) {
// CHECK:STDOUT: generic fn @K.1(constants.%Self.3: %Y.type) {
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: fn();
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @K.2();
// CHECK:STDOUT:
// CHECK:STDOUT: specific @AnyParam(constants.%T, constants.%X.1) {
// CHECK:STDOUT: %T => constants.%T
// CHECK:STDOUT: %T.patt => constants.%T
Expand Down Expand Up @@ -1501,7 +1513,7 @@ fn Test(c: HasExtraInterfaces.C(type)) {
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @K(constants.%Self.3) {}
// CHECK:STDOUT: specific @K.1(constants.%Self.3) {}
// CHECK:STDOUT:
// CHECK:STDOUT: --- has_extra_interfaces.carbon
// CHECK:STDOUT:
Expand Down
Loading

0 comments on commit d0e067a

Please sign in to comment.