Skip to content

Commit

Permalink
Import the full list of extended scopes. (carbon-language#4562)
Browse files Browse the repository at this point in the history
Replace the special case adding the base class to the list of extended
scopes with a fully general approach. We use an ImportRef to lazily
import the extended scopes on first lookup.
  • Loading branch information
zygoloid authored Nov 21, 2024
1 parent 4cf2c07 commit 5e40380
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 66 deletions.
1 change: 1 addition & 0 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ auto Context::LookupQualifiedName(SemIRLoc loc, SemIR::NameId name_id,
// Substitute into the constant describing the extended scope to
// determine its corresponding specific.
CARBON_CHECK(extended_id.is_valid());
LoadImportRef(*this, extended_id);
SemIR::ConstantId const_id =
GetConstantValueInSpecific(sem_ir(), specific_id, extended_id);

Expand Down
39 changes: 24 additions & 15 deletions toolchain/check/import_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,10 @@ class ImportRefResolver {
.inst_id = ref_id,
.access_kind = entry.access_kind});
}
for (auto scope_inst_id : import_scope.extended_scopes) {
new_scope.extended_scopes.push_back(AddImportRef(
context_, {.ir_id = import_ir_id_, .inst_id = scope_inst_id}));
}
}

// Given a block ID for a list of associated entities of a witness, returns a
Expand Down Expand Up @@ -1253,11 +1257,25 @@ class ImportRefResolver {
case CARBON_KIND(SemIR::UnboundElementType inst): {
return TryResolveTypedInst(inst);
}
default:
context_.TODO(
SemIR::LocId(AddImportIRInst(inst_id)),
llvm::formatv("TryResolveInst on {0}", untyped_inst.kind()).str());
return {.const_id = SemIR::ConstantId::Error};
default: {
// This instruction might have a constant value of a different kind.
auto constant_inst_id =
import_ir_.constant_values().GetConstantInstId(inst_id);
if (constant_inst_id == inst_id) {
context_.TODO(
SemIR::LocId(AddImportIRInst(inst_id)),
llvm::formatv("TryResolveInst on {0}", untyped_inst.kind())
.str());
return {.const_id = SemIR::ConstantId::Error};
}
// Try to resolve the constant value instead. Note that this can only
// retry once.
CARBON_DCHECK(import_ir_.constant_values().GetConstantInstId(
constant_inst_id) == constant_inst_id,
"Constant value of constant instruction should refer to "
"the same instruction");
return TryResolveInstCanonical(constant_inst_id, const_id);
}
}
}

Expand Down Expand Up @@ -1455,16 +1473,7 @@ class ImportRefResolver {

if (import_class.base_id.is_valid()) {
new_class.base_id = base_id;
// Add the base scope to extended scopes.
auto base_inst_id = context_.types().GetInstId(
context_.insts()
.GetAs<SemIR::BaseDecl>(new_class.base_id)
.base_type_id);
new_scope.extended_scopes.push_back(base_inst_id);
}
// TODO: `extended_scopes` from `extend impl` are currently not imported.
// CARBON_CHECK(new_scope.extended_scopes.size() ==
// import_scope.extended_scopes.size());
}
}

auto TryResolveTypedInst(SemIR::ClassDecl inst,
Expand Down
75 changes: 38 additions & 37 deletions toolchain/check/testdata/class/generic/base_is_generic.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ fn ImportedDoubleFieldAccess(d: Derived) -> i32 {
library "[[@TEST_NAME]]";

class C(T:! type) {
// CHECK:STDERR: fail_todo_extend_symbolic_base.carbon:[[@LINE+4]]:16: error: deriving from final type `T`; base type must be an `abstract` or `base` class [BaseIsFinal]
// CHECK:STDERR: fail_todo_extend_symbolic_base.carbon:[[@LINE+3]]:16: error: deriving from final type `T`; base type must be an `abstract` or `base` class [BaseIsFinal]
// CHECK:STDERR: extend base: T;
// CHECK:STDERR: ^
// CHECK:STDERR:
extend base: T;
}

Expand Down Expand Up @@ -75,19 +74,13 @@ fn F() {
}


// --- fail_todo_import_extend_generic_symbolic_base.carbon
// --- import_extend_generic_symbolic_base.carbon

library "[[@TEST_NAME]]";

import library "extend_generic_symbolic_base";

fn H() {
// CHECK:STDERR: fail_todo_import_extend_generic_symbolic_base.carbon:[[@LINE+6]]:3: error: cannot implicitly convert from `T` to `i32` [ImplicitAsConversionFailure]
// CHECK:STDERR: let j: i32 = C(i32).G();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_todo_import_extend_generic_symbolic_base.carbon:[[@LINE+3]]:3: note: type `T` does not implement interface `ImplicitAs(i32)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: let j: i32 = C(i32).G();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
let j: i32 = C(i32).G();
}

Expand Down Expand Up @@ -277,7 +270,7 @@ fn H() {
// CHECK:STDOUT: %import_ref.3: type = import_ref Main//extend_generic_base, inst+50, loaded [template = constants.%Derived]
// CHECK:STDOUT: %import_ref.4 = import_ref Main//extend_generic_base, inst+80, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref.11
// CHECK:STDOUT: .Int = %import_ref.12
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
Expand All @@ -287,6 +280,7 @@ fn H() {
// CHECK:STDOUT: %import_ref.8: @Base.%.1 (%.9) = import_ref Main//extend_generic_base, inst+18, loaded [template = %.2]
// CHECK:STDOUT: %import_ref.9 = import_ref Main//extend_generic_base, inst+51, unloaded
// CHECK:STDOUT: %import_ref.10 = import_ref Main//extend_generic_base, inst+63, unloaded
// CHECK:STDOUT: %import_ref.11: type = import_ref Main//extend_generic_base, inst+54, loaded [template = constants.%Base.3]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand Down Expand Up @@ -322,7 +316,7 @@ fn H() {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.9
// CHECK:STDOUT: .base = imports.%import_ref.10
// CHECK:STDOUT: extend constants.%Base.3
// CHECK:STDOUT: extend imports.%import_ref.11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Param {
Expand Down Expand Up @@ -434,19 +428,19 @@ fn H() {
// CHECK:STDOUT:
// CHECK:STDOUT: class {
// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_9.1 [symbolic = %T.loc4_9.2 (constants.%T)]
// CHECK:STDOUT: %.loc9: <error> = base_decl <error>, element0 [template]
// CHECK:STDOUT: %.loc10: <witness> = complete_type_witness <error> [template = <error>]
// CHECK:STDOUT: %.loc8: <error> = base_decl <error>, element0 [template]
// CHECK:STDOUT: %.loc9: <witness> = complete_type_witness <error> [template = <error>]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%C.2
// CHECK:STDOUT: .base = %.loc9
// CHECK:STDOUT: .base = %.loc8
// CHECK:STDOUT: has_error
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @X {
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} {}
// CHECK:STDOUT: %.loc14: <witness> = complete_type_witness %.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc13: <witness> = complete_type_witness %.1 [template = constants.%.2]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%X
Expand Down Expand Up @@ -730,7 +724,7 @@ fn H() {
// CHECK:STDOUT: %.loc5_24.3 => constants.%.14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_import_extend_generic_symbolic_base.carbon
// CHECK:STDOUT: --- import_extend_generic_symbolic_base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %H.type: type = fn_type @H [template]
Expand Down Expand Up @@ -760,7 +754,9 @@ fn H() {
// CHECK:STDOUT: %.8: type = unbound_element_type %C.3, %X.4 [template]
// CHECK:STDOUT: %.9: type = struct_type {.base: %X.4} [template]
// CHECK:STDOUT: %.10: <witness> = complete_type_witness %.9 [template]
// CHECK:STDOUT: %.14: <specific function> = specific_function %G.2, @G(%T) [symbolic]
// CHECK:STDOUT: %G.type.3: type = fn_type @G, @X(%i32) [template]
// CHECK:STDOUT: %G.3: %G.type.3 = struct_value () [template]
// CHECK:STDOUT: %.14: <specific function> = specific_function %G.3, @G(%i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
Expand All @@ -769,14 +765,14 @@ fn H() {
// CHECK:STDOUT: %import_ref.3 = import_ref Main//extend_generic_symbolic_base, inst+70, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref.4
// CHECK:STDOUT: .ImplicitAs = %import_ref.9
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.5 = import_ref Main//extend_generic_symbolic_base, inst+15, unloaded
// CHECK:STDOUT: %import_ref.6: @X.%G.type (%G.type.1) = import_ref Main//extend_generic_symbolic_base, inst+21, loaded [symbolic = @X.%G (constants.%G.1)]
// CHECK:STDOUT: %import_ref.7 = import_ref Main//extend_generic_symbolic_base, inst+52, unloaded
// CHECK:STDOUT: %import_ref.8 = import_ref Main//extend_generic_symbolic_base, inst+61, unloaded
// CHECK:STDOUT: %import_ref.9: type = import_ref Main//extend_generic_symbolic_base, inst+55, loaded [symbolic = @C.%X (constants.%X.3)]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand Down Expand Up @@ -807,7 +803,7 @@ fn H() {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.7
// CHECK:STDOUT: .base = imports.%import_ref.8
// CHECK:STDOUT: extend constants.%X.3
// CHECK:STDOUT: extend imports.%import_ref.9
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand All @@ -828,22 +824,23 @@ fn H() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @H() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc13_10.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed.loc13_10: init type = call constants.%Int(%.loc13_10.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc13_10.2: type = value_of_initializer %int.make_type_signed.loc13_10 [template = constants.%i32]
// CHECK:STDOUT: %.loc13_10.3: type = converted %int.make_type_signed.loc13_10, %.loc13_10.2 [template = constants.%i32]
// CHECK:STDOUT: %.loc7_10.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed.loc7_10: init type = call constants.%Int(%.loc7_10.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc7_10.2: type = value_of_initializer %int.make_type_signed.loc7_10 [template = constants.%i32]
// CHECK:STDOUT: %.loc7_10.3: type = converted %int.make_type_signed.loc7_10, %.loc7_10.2 [template = constants.%i32]
// CHECK:STDOUT: %C.ref: %C.type = name_ref C, imports.%import_ref.2 [template = constants.%C.1]
// CHECK:STDOUT: %.loc13_18: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed.loc13_18: init type = call constants.%Int(%.loc13_18) [template = constants.%i32]
// CHECK:STDOUT: %.loc13_17.1: type = value_of_initializer %int.make_type_signed.loc13_18 [template = constants.%i32]
// CHECK:STDOUT: %.loc13_17.2: type = converted %int.make_type_signed.loc13_18, %.loc13_17.1 [template = constants.%i32]
// CHECK:STDOUT: %.loc7_18: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed.loc7_18: init type = call constants.%Int(%.loc7_18) [template = constants.%i32]
// CHECK:STDOUT: %.loc7_17.1: type = value_of_initializer %int.make_type_signed.loc7_18 [template = constants.%i32]
// CHECK:STDOUT: %.loc7_17.2: type = converted %int.make_type_signed.loc7_18, %.loc7_17.1 [template = constants.%i32]
// CHECK:STDOUT: %C: type = class_type @C, @C(constants.%i32) [template = constants.%C.3]
// CHECK:STDOUT: %.loc13_22.1: %G.type.2 = specific_constant imports.%import_ref.6, @X(constants.%T) [symbolic = constants.%G.2]
// CHECK:STDOUT: %G.ref: %G.type.2 = name_ref G, %.loc13_22.1 [symbolic = constants.%G.2]
// CHECK:STDOUT: %.loc13_22.2: <specific function> = specific_function %G.ref, @G(constants.%T) [symbolic = constants.%.14]
// CHECK:STDOUT: %G.call: init %T = call %.loc13_22.2()
// CHECK:STDOUT: %.loc13_26: %i32 = converted %G.call, <error> [template = <error>]
// CHECK:STDOUT: %j: %i32 = bind_name j, <error>
// CHECK:STDOUT: %.loc7_22.1: %G.type.3 = specific_constant imports.%import_ref.6, @X(constants.%i32) [template = constants.%G.3]
// CHECK:STDOUT: %G.ref: %G.type.3 = name_ref G, %.loc7_22.1 [template = constants.%G.3]
// CHECK:STDOUT: %.loc7_22.2: <specific function> = specific_function %G.ref, @G(constants.%i32) [template = constants.%.14]
// CHECK:STDOUT: %G.call: init %i32 = call %.loc7_22.2()
// CHECK:STDOUT: %.loc7_26.1: %i32 = value_of_initializer %G.call
// CHECK:STDOUT: %.loc7_26.2: %i32 = converted %G.call, %.loc7_26.1
// CHECK:STDOUT: %j: %i32 = bind_name j, %.loc7_26.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand Down Expand Up @@ -929,14 +926,18 @@ fn H() {
// CHECK:STDOUT: specific @X(constants.%i32) {
// CHECK:STDOUT: %U => constants.%i32
// CHECK:STDOUT: %U.patt => constants.%i32
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %G.type => constants.%G.type.3
// CHECK:STDOUT: %G => constants.%G.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @G(constants.%T) {
// CHECK:STDOUT: %U => constants.%T
// CHECK:STDOUT: specific @G(constants.%i32) {
// CHECK:STDOUT: %U => constants.%i32
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %G.type => constants.%G.type.2
// CHECK:STDOUT: %G => constants.%G.2
// CHECK:STDOUT: %G.type => constants.%G.type.3
// CHECK:STDOUT: %G => constants.%G.3
// CHECK:STDOUT: %.1 => constants.%.14
// CHECK:STDOUT: }
// CHECK:STDOUT:
5 changes: 3 additions & 2 deletions toolchain/check/testdata/class/import_base.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn Run() {
// CHECK:STDOUT: %import_ref.1 = import_ref Main//a, inst+3, unloaded
// CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+49, loaded [template = constants.%Child]
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.10
// CHECK:STDOUT: .ImplicitAs = %import_ref.11
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
Expand All @@ -178,6 +178,7 @@ fn Run() {
// CHECK:STDOUT: %import_ref.7 = import_ref Main//a, inst+45, unloaded
// CHECK:STDOUT: %import_ref.8 = import_ref Main//a, inst+50, unloaded
// CHECK:STDOUT: %import_ref.9 = import_ref Main//a, inst+54, unloaded
// CHECK:STDOUT: %import_ref.10: type = import_ref Main//a, inst+51, loaded [template = constants.%Base]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand All @@ -196,7 +197,7 @@ fn Run() {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.8
// CHECK:STDOUT: .base = imports.%import_ref.9
// CHECK:STDOUT: extend constants.%Base
// CHECK:STDOUT: extend imports.%import_ref.10
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Base {
Expand Down
59 changes: 47 additions & 12 deletions toolchain/check/testdata/impl/no_prelude/import_extend_impl.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,14 @@ class C {
}
}

// --- fail_todo_use_imported_class_extend_impl.carbon
// --- use_imported_class_extend_impl.carbon

library "[[@TEST_NAME]]";

import library "extend_impl_library";

fn G(c: C) {
// CHECK:STDERR: fail_todo_use_imported_class_extend_impl.carbon:[[@LINE+4]]:3: error: name `F` not found [NameNotFound]
// CHECK:STDERR: C.F();
// CHECK:STDERR: ^~~
// CHECK:STDERR:
C.F();
// CHECK:STDERR: fail_todo_use_imported_class_extend_impl.carbon:[[@LINE+3]]:3: error: name `F` not found [NameNotFound]
// CHECK:STDERR: c.F();
// CHECK:STDERR: ^~~
c.F();
}

Expand Down Expand Up @@ -112,18 +105,34 @@ fn G(c: C) {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%C) {}
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_use_imported_class_extend_impl.carbon
// CHECK:STDOUT: --- use_imported_class_extend_impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %C: type = class_type @C [template]
// CHECK:STDOUT: %G.type: type = fn_type @G [template]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template]
// CHECK:STDOUT: %G: %G.type = struct_value () [template]
// CHECK:STDOUT: %I.type: type = facet_type <@I> [template]
// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template]
// CHECK:STDOUT: %.4: type = assoc_entity_type %I.type, %F.type.1 [template]
// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.8 [template]
// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template]
// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template]
// CHECK:STDOUT: %.6: <witness> = interface_witness (%F.2) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %import_ref.1 = import_ref Main//extend_impl_library, inst+1, unloaded
// CHECK:STDOUT: %import_ref.2: type = import_ref Main//extend_impl_library, inst+12, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.3 = import_ref Main//extend_impl_library, inst+13, unloaded
// CHECK:STDOUT: %import_ref.4: type = import_ref Main//extend_impl_library, inst+15, loaded [template = constants.%I.type]
// CHECK:STDOUT: %import_ref.5 = import_ref Main//extend_impl_library, inst+3, unloaded
// CHECK:STDOUT: %import_ref.6: %.4 = import_ref Main//extend_impl_library, inst+10, loaded [template = constants.%.5]
// CHECK:STDOUT: %import_ref.7 = import_ref Main//extend_impl_library, inst+5, unloaded
// CHECK:STDOUT: %import_ref.9: type = import_ref Main//extend_impl_library, inst+14, loaded [template = constants.%C]
// CHECK:STDOUT: %import_ref.10: type = import_ref Main//extend_impl_library, inst+15, loaded [template = constants.%I.type]
// CHECK:STDOUT: %import_ref.11: <witness> = import_ref Main//extend_impl_library, inst+20, loaded [template = constants.%.6]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
Expand All @@ -143,17 +152,43 @@ fn G(c: C) {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @I {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.5
// CHECK:STDOUT: .F = imports.%import_ref.6
// CHECK:STDOUT: witness = (imports.%import_ref.7)
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl: imports.%import_ref.9 as imports.%import_ref.10 {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: witness = imports.%import_ref.11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @C {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.3
// CHECK:STDOUT: extend imports.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%c.param_patt: %C) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %C.ref.loc11: type = name_ref C, imports.%import_ref.2 [template = constants.%C]
// CHECK:STDOUT: %F.ref.loc11: <error> = name_ref F, <error> [template = <error>]
// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, imports.%import_ref.2 [template = constants.%C]
// CHECK:STDOUT: %F.ref.loc7: %.4 = name_ref F, imports.%import_ref.6 [template = constants.%.5]
// CHECK:STDOUT: %.loc7: %F.type.1 = interface_witness_access constants.%.6, element0 [template = constants.%F.2]
// CHECK:STDOUT: %F.call.loc7: init %empty_tuple.type = call %.loc7()
// CHECK:STDOUT: %c.ref: %C = name_ref c, %c
// CHECK:STDOUT: %F.ref.loc15: <error> = name_ref F, <error> [template = <error>]
// CHECK:STDOUT: %F.ref.loc8: %.4 = name_ref F, imports.%import_ref.6 [template = constants.%.5]
// CHECK:STDOUT: %.loc8: %F.type.1 = interface_witness_access constants.%.6, element0 [template = constants.%F.2]
// CHECK:STDOUT: %F.call.loc8: init %empty_tuple.type = call %.loc8()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @F.1(constants.%Self: %I.type) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn();
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F.2();
// CHECK:STDOUT:
// CHECK:STDOUT: specific @F.1(constants.%Self) {}
// CHECK:STDOUT:

0 comments on commit 5e40380

Please sign in to comment.