Always import canonical instructions except for exceptional Decl cases (#6009)

There are a few instructions that import in multiple phases, which
receive the `const_id` and use it to construct multiple constants until
building the final constant value. These include
`AssociatedConstantDecl`, `FunctionDecl`, and `InterfaceDecl`.

Other instructions just construct a constant value in a single attempt,
once all their dependencies are imported. For these instruction types,
avoid importing the non-canonical instruction. Always get the canonical
constant instruction and import that.

Since the constant value of an instruction can have a very different
structure than its non-canonical value, this ensures import has a
consistent structure to work with, by only working with canonical values
as much as possible.

The `VtableDecl` and `VtablePtr` were set up to pass along `const_id`
but do not actually require multiple phases, so they have been changed
to stop passing along the unused (and always empty) `const_id`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Dana Jansens
2025-09-03 22:36:27 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent cb5e2e1597
commit 70f104aa40
4 changed files with 118 additions and 88 deletions
+82 -76
View File
@@ -2046,9 +2046,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
}
static auto TryResolveTypedInst(ImportRefResolver& resolver,
SemIR::VtableDecl inst,
SemIR::ConstantId /*vtable_const_id*/)
-> ResolveResult {
SemIR::VtableDecl inst) -> ResolveResult {
const auto& import_vtable = resolver.import_vtables().Get(inst.vtable_id);
auto class_const_id =
GetLocalConstantId(resolver, resolver.import_classes()
@@ -2117,9 +2115,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
}
static auto TryResolveTypedInst(ImportRefResolver& resolver,
SemIR::VtablePtr inst,
SemIR::ConstantId /*vtable_const_id*/)
-> ResolveResult {
SemIR::VtablePtr inst) -> ResolveResult {
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
auto vtable_const_id = GetLocalConstantId(
@@ -2147,6 +2143,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
auto fn_val_id = GetLocalConstantInstId(
resolver,
resolver.import_functions().Get(inst.function_id).first_decl_id());
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
if (resolver.HasNewWork()) {
return ResolveResult::Retry();
@@ -3058,26 +3055,70 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
SemIR::InstId inst_id,
SemIR::ConstantId const_id)
-> ResolveResult {
if (SemIR::IsSingletonInstId(inst_id)) {
CARBON_CHECK(!const_id.has_value());
// Constants for builtins can be directly copied.
return ResolveResult::Done(resolver.local_constant_values().Get(inst_id));
}
// These instruction types are imported across multiple phases to arrive at
// their constant value. We can't just import their constant value instruction
// directly.
auto untyped_inst = resolver.import_insts().GetWithAttachedType(inst_id);
CARBON_KIND_SWITCH(untyped_inst) {
case CARBON_KIND(SemIR::AssociatedConstantDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::ClassDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::FunctionDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::ImplDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::InterfaceDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
default:
break;
}
// Other instructions are imported in a single phase (once their dependencies
// are all imported).
CARBON_CHECK(!const_id.has_value());
auto inst_constant_id = resolver.import_constant_values().Get(inst_id);
if (!inst_constant_id.is_constant()) {
// TODO: Import of non-constant BindNames happens when importing `let`
// declarations.
CARBON_CHECK(resolver.import_insts().Is<SemIR::BindName>(inst_id),
"TryResolveInst on non-constant instruction {0}", inst_id);
return ResolveResult::Done(SemIR::ConstantId::NotConstant);
}
// Import the canonical constant value instruction for `inst_id` directly. We
// don't try to import the non-canonical `inst_id`.
auto constant_inst_id =
resolver.import_constant_values().GetInstId(inst_constant_id);
CARBON_DCHECK(resolver.import_constant_values().GetConstantInstId(
constant_inst_id) == constant_inst_id,
"Constant value of constant instruction should refer to "
"the same instruction");
if (SemIR::IsSingletonInstId(constant_inst_id)) {
// Constants for builtins can be directly copied.
return ResolveResult::Done(
resolver.local_constant_values().Get(constant_inst_id));
}
auto untyped_constant_inst =
resolver.import_insts().GetWithAttachedType(constant_inst_id);
CARBON_KIND_SWITCH(untyped_constant_inst) {
case CARBON_KIND(SemIR::AdaptDecl inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::AddrPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::ArrayType inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::AssociatedConstantDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::AssociatedEntity inst): {
return TryResolveTypedInst(resolver, inst);
}
@@ -3085,13 +3126,13 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::BaseDecl inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::BindAlias inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::BindingPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::BindSymbolicName inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3108,9 +3149,6 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
case CARBON_KIND(SemIR::CharLiteralValue inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::ClassDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::ClassType inst): {
return TryResolveTypedInst(resolver, inst);
}
@@ -3133,7 +3171,7 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::FieldDecl inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::FloatLiteralValue inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3144,9 +3182,6 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
case CARBON_KIND(SemIR::FloatValue inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::FunctionDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::FunctionType inst): {
return TryResolveTypedInst(resolver, inst);
}
@@ -3159,9 +3194,6 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
case CARBON_KIND(SemIR::GenericInterfaceType inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::ImplDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
case CARBON_KIND(SemIR::LookupImplWitness inst): {
return TryResolveTypedInst(resolver, inst);
}
@@ -3172,13 +3204,10 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::ImplWitnessTable inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::ImportRefLoaded inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
}
case CARBON_KIND(SemIR::InterfaceDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::IntValue inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3190,10 +3219,10 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::Namespace inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::OutParamPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::PartialType inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3205,13 +3234,13 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::RefParamPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::RequireCompleteType inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::ReturnSlotPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::SpecificFunction inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3229,13 +3258,13 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::SymbolicBindingPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::TupleAccess inst): {
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::TuplePattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::TupleType inst): {
return TryResolveTypedInst(resolver, inst);
@@ -3247,51 +3276,28 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::ValueParamPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::VarPattern inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::VarStorage inst): {
return TryResolveTypedInst(resolver, inst, inst_id);
return TryResolveTypedInst(resolver, inst, constant_inst_id);
}
case CARBON_KIND(SemIR::VtableDecl inst): {
return TryResolveTypedInst(resolver, inst, const_id);
return TryResolveTypedInst(resolver, inst);
}
case CARBON_KIND(SemIR::VtablePtr inst): {
return TryResolveTypedInst(resolver, inst, const_id);
}
default: {
auto inst_constant_id = resolver.import_constant_values().Get(inst_id);
if (!inst_constant_id.is_constant()) {
// TODO: Import of non-constant BindNames happens when importing `let`
// declarations.
CARBON_CHECK(untyped_inst.Is<SemIR::BindName>(),
"TryResolveInst on non-constant instruction {0}",
untyped_inst);
return ResolveResult::Done(SemIR::ConstantId::NotConstant);
}
// This instruction might have a constant value of a different kind.
auto constant_inst_id =
resolver.import_constant_values().GetInstId(inst_constant_id);
if (constant_inst_id == inst_id) {
// Produce a diagnostic to provide a source location with the CHECK
// failure.
resolver.local_context().TODO(
SemIR::LocId(AddImportIRInst(resolver, inst_id)),
llvm::formatv("TryResolveInst on {0}", untyped_inst.kind()).str());
CARBON_FATAL("TryResolveInst on unsupported instruction kind {0}",
untyped_inst.kind());
}
// Try to resolve the constant value instead. Note that this can only
// retry once.
CARBON_DCHECK(resolver.import_constant_values().GetConstantInstId(
constant_inst_id) == constant_inst_id,
"Constant value of constant instruction should refer to "
"the same instruction");
return TryResolveInstCanonical(resolver, constant_inst_id, const_id);
return TryResolveTypedInst(resolver, inst);
}
default:
// Found a canonical instruction which needs to be resolved, but which is
// not yet handled.
//
// TODO: Could we turn this into a compile-time error?
CARBON_FATAL(
"Missing case in TryResolveInstCanonical for instruction kind {0}",
untyped_constant_inst.kind());
}
}
+9 -9
View File
@@ -222,26 +222,26 @@ fn Read() {
// CHECK:STDOUT: %Core.import_ref.9e6: type = import_ref Core//prelude/iterate, loc13_17, loaded [concrete = %CursorType]
// CHECK:STDOUT: %Core.import_ref.f49: @Optional.%Optional.None.type (%Optional.None.type.ef2) = import_ref Core//prelude/iterate, inst137 [indirect], loaded [symbolic = @Optional.%Optional.None (constants.%Optional.None.fd6)]
// CHECK:STDOUT: %Core.import_ref.1a8: @Optional.%Optional.Some.type (%Optional.Some.type.b2c) = import_ref Core//prelude/iterate, inst138 [indirect], loaded [symbolic = @Optional.%Optional.Some (constants.%Optional.Some.d0d)]
// CHECK:STDOUT: %Core.import_ref.36a9: @Optional.as.Destroy.impl.%Optional.as.Destroy.impl.Op.type (%Optional.as.Destroy.impl.Op.type.764) = import_ref Core//prelude/iterate, inst6889 [indirect], loaded [symbolic = @Optional.as.Destroy.impl.%Optional.as.Destroy.impl.Op (constants.%Optional.as.Destroy.impl.Op.bf8)]
// CHECK:STDOUT: %Core.import_ref.36a9: @Optional.as.Destroy.impl.%Optional.as.Destroy.impl.Op.type (%Optional.as.Destroy.impl.Op.type.764) = import_ref Core//prelude/iterate, inst6900 [indirect], loaded [symbolic = @Optional.as.Destroy.impl.%Optional.as.Destroy.impl.Op (constants.%Optional.as.Destroy.impl.Op.bf8)]
// CHECK:STDOUT: %Destroy.impl_witness_table.2ff = impl_witness_table (%Core.import_ref.36a9), @Optional.as.Destroy.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.cf4: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.0f9) = import_ref Core//prelude/iterate, inst482 [indirect], loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f06)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.2b9 = impl_witness_table (%Core.import_ref.cf4), @Core.IntLiteral.as.ImplicitAs.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.741: @Int.as.Destroy.impl.%Int.as.Destroy.impl.Op.type (%Int.as.Destroy.impl.Op.type) = import_ref Core//prelude/iterate, inst450 [indirect], loaded [symbolic = @Int.as.Destroy.impl.%Int.as.Destroy.impl.Op (constants.%Int.as.Destroy.impl.Op)]
// CHECK:STDOUT: %Destroy.impl_witness_table.1b4 = impl_witness_table (%Core.import_ref.741), @Int.as.Destroy.impl [concrete]
// CHECK:STDOUT: %Core.import_ref.19a: @OrderedWith.%OrderedWith.assoc_type (%OrderedWith.assoc_type.03c) = import_ref Core//prelude/iterate, inst862 [indirect], loaded [symbolic = @OrderedWith.%assoc0 (constants.%assoc0.5db)]
// CHECK:STDOUT: %Core.import_ref.b2b: @Int.as.OrderedWith.impl.db3.%Int.as.OrderedWith.impl.Less.type (%Int.as.OrderedWith.impl.Less.type.2c7) = import_ref Core//prelude/iterate, inst951 [indirect], loaded [symbolic = @Int.as.OrderedWith.impl.db3.%Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.a5a)]
// CHECK:STDOUT: %Core.import_ref.ab6 = import_ref Core//prelude/iterate, inst952 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.875 = import_ref Core//prelude/iterate, inst953 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.82b = import_ref Core//prelude/iterate, inst954 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.19a: @OrderedWith.%OrderedWith.assoc_type (%OrderedWith.assoc_type.03c) = import_ref Core//prelude/iterate, inst865 [indirect], loaded [symbolic = @OrderedWith.%assoc0 (constants.%assoc0.5db)]
// CHECK:STDOUT: %Core.import_ref.b2b: @Int.as.OrderedWith.impl.db3.%Int.as.OrderedWith.impl.Less.type (%Int.as.OrderedWith.impl.Less.type.2c7) = import_ref Core//prelude/iterate, inst954 [indirect], loaded [symbolic = @Int.as.OrderedWith.impl.db3.%Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.a5a)]
// CHECK:STDOUT: %Core.import_ref.ab6 = import_ref Core//prelude/iterate, inst955 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.875 = import_ref Core//prelude/iterate, inst956 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.82b = import_ref Core//prelude/iterate, inst957 [indirect], unloaded
// CHECK:STDOUT: %OrderedWith.impl_witness_table.476 = impl_witness_table (%Core.import_ref.b2b, %Core.import_ref.ab6, %Core.import_ref.875, %Core.import_ref.82b), @Int.as.OrderedWith.impl.db3 [concrete]
// CHECK:STDOUT: %Core.import_ref.13d: @OrderedWith.%OrderedWith.Less.type (%OrderedWith.Less.type.f19) = import_ref Core//prelude/iterate, inst1926 [indirect], loaded [symbolic = @OrderedWith.%OrderedWith.Less (constants.%OrderedWith.Less.02e)]
// CHECK:STDOUT: %Core.import_ref.13d: @OrderedWith.%OrderedWith.Less.type (%OrderedWith.Less.type.f19) = import_ref Core//prelude/iterate, inst1929 [indirect], loaded [symbolic = @OrderedWith.%OrderedWith.Less (constants.%OrderedWith.Less.02e)]
// CHECK:STDOUT: %CursorType: type = assoc_const_decl @CursorType [concrete] {}
// CHECK:STDOUT: %Core.import_ref.4f9: type = import_ref Core//prelude/iterate, loc12_18, loaded [concrete = %ElementType]
// CHECK:STDOUT: %ElementType: type = assoc_const_decl @ElementType [concrete] {}
// CHECK:STDOUT: %Core.Optional: %Optional.type = import_ref Core//prelude/types/optional, Optional, loaded [concrete = constants.%Optional.generic]
// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
// CHECK:STDOUT: %Core.OrderedWith: %OrderedWith.type.270 = import_ref Core//prelude/operators/comparison, OrderedWith, loaded [concrete = constants.%OrderedWith.generic]
// CHECK:STDOUT: %Core.import_ref.d49 = import_ref Core//prelude/iterate, inst6644 [indirect], unloaded
// CHECK:STDOUT: %Core.import_ref.d49 = import_ref Core//prelude/iterate, inst6655 [indirect], unloaded
// CHECK:STDOUT: %Core.Inc: type = import_ref Core//prelude/operators/arithmetic, Inc, loaded [concrete = constants.%Inc.type]
// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
// CHECK:STDOUT: }
@@ -1023,7 +1023,7 @@ fn Read() {
// CHECK:STDOUT: %Iterate.impl_witness_table.b32 = impl_witness_table (%Main.import_ref.e3faa9.1, %Main.import_ref.e3faa9.2, %Main.import_ref.11c, %Main.import_ref.f97), @IntRange.as.Iterate.impl [concrete]
// CHECK:STDOUT: %Main.import_ref.f1e294.4: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N.c80)]
// CHECK:STDOUT: %Main.import_ref.f1e294.5: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N.c80)]
// CHECK:STDOUT: %Main.import_ref.026 = import_ref Main//lib, inst1895 [indirect], unloaded
// CHECK:STDOUT: %Main.import_ref.026 = import_ref Main//lib, inst1898 [indirect], unloaded
// CHECK:STDOUT: %Main.import_ref.bdb: <witness> = import_ref Main//lib, loc4_39, loaded [symbolic = @IntRange.as.Destroy.impl.%Destroy.impl_witness (constants.%Destroy.impl_witness.45d)]
// CHECK:STDOUT: %Main.import_ref.f1e294.6: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N.c80)]
// CHECK:STDOUT: %Main.import_ref.daedfd.2: type = import_ref Main//lib, loc4_39, loaded [symbolic = @IntRange.as.Destroy.impl.%IntRange (constants.%IntRange.349)]
@@ -707,6 +707,12 @@ var n: Int(64) = MakeFromClass(FromLiteral(64) as OtherInt);
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.a71
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Add.Op(constants.%Add.facet.5a7) {
// CHECK:STDOUT: %Self => constants.%Add.facet.5a7
// CHECK:STDOUT: %Self.as_type => constants.%MyInt.09f
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.a71
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Double(constants.%int_64) {
// CHECK:STDOUT: %N => constants.%int_64
// CHECK:STDOUT: %MyInt => constants.%MyInt.f30
+21 -3
View File
@@ -456,7 +456,7 @@ fn G() {
// CHECK:STDOUT: %C.as.Destroy.impl.Op.type.1b919a.1: type = fn_type @C.as.Destroy.impl.Op, @C.as.Destroy.impl(%X) [symbolic]
// CHECK:STDOUT: %C.as.Destroy.impl.Op.65ca93.1: %C.as.Destroy.impl.Op.type.1b919a.1 = struct_value () [symbolic]
// CHECK:STDOUT: %ptr.40dc71.1: type = ptr_type %C.13320f.1 [symbolic]
// CHECK:STDOUT: %pattern_type.2a1: type = pattern_type %ptr.40dc71.1 [symbolic]
// CHECK:STDOUT: %pattern_type.2a1e48.1: type = pattern_type %ptr.40dc71.1 [symbolic]
// CHECK:STDOUT: %Y: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic]
// CHECK:STDOUT: %C.13320f.2: type = class_type @C, @C(%Y) [symbolic]
// CHECK:STDOUT: %I.impl_witness.7d9: <witness> = impl_witness imports.%I.impl_witness_table, @C.as.I.impl(%Y) [symbolic]
@@ -477,6 +477,7 @@ fn G() {
// CHECK:STDOUT: %C.as.Destroy.impl.Op.specific_fn.c52: <specific function> = specific_function %C.as.Destroy.impl.Op.65ca93.2, @C.as.Destroy.impl.Op(%Y) [symbolic]
// CHECK:STDOUT: %ptr.40dc71.2: type = ptr_type %C.13320f.2 [symbolic]
// CHECK:STDOUT: %require_complete.0b0: <witness> = require_complete_type %ptr.40dc71.2 [symbolic]
// CHECK:STDOUT: %pattern_type.2a1e48.2: type = pattern_type %ptr.40dc71.2 [symbolic]
// CHECK:STDOUT: %I.impl_witness.02b: <witness> = impl_witness imports.%I.impl_witness_table, @C.as.I.impl(%empty_tuple) [concrete]
// CHECK:STDOUT: %C.as.I.impl.F.type.af4856.1: type = fn_type @C.as.I.impl.F.1, @C.as.I.impl(%empty_tuple) [concrete]
// CHECK:STDOUT: %C.as.I.impl.F.5fa954.1: %C.as.I.impl.F.type.af4856.1 = struct_value () [concrete]
@@ -642,7 +643,7 @@ fn G() {
// CHECK:STDOUT: %X: %empty_tuple.type = bind_symbolic_name X, 0 [symbolic = %X (constants.%X)]
// CHECK:STDOUT: %C: type = class_type @C, @C(%X) [symbolic = %C (constants.%C.13320f.1)]
// CHECK:STDOUT: %ptr: type = ptr_type %C [symbolic = %ptr (constants.%ptr.40dc71.1)]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [symbolic = %pattern_type (constants.%pattern_type.2a1)]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [symbolic = %pattern_type (constants.%pattern_type.2a1e48.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
@@ -703,7 +704,7 @@ fn G() {
// CHECK:STDOUT: %X => constants.%X
// CHECK:STDOUT: %C => constants.%C.13320f.1
// CHECK:STDOUT: %ptr => constants.%ptr.40dc71.1
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.2a1
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.2a1e48.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C(constants.%Y) {
@@ -735,6 +736,23 @@ fn G() {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C.as.I.impl.F.2(constants.%Y) {}
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C.as.Destroy.impl(constants.%Y) {
// CHECK:STDOUT: %X => constants.%Y
// CHECK:STDOUT: %C => constants.%C.13320f.2
// CHECK:STDOUT: %Destroy.impl_witness => constants.%Destroy.impl_witness.5d03b3.2
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %C.as.Destroy.impl.Op.type => constants.%C.as.Destroy.impl.Op.type.1b919a.2
// CHECK:STDOUT: %C.as.Destroy.impl.Op => constants.%C.as.Destroy.impl.Op.65ca93.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C.as.Destroy.impl.Op(constants.%Y) {
// CHECK:STDOUT: %X => constants.%Y
// CHECK:STDOUT: %C => constants.%C.13320f.2
// CHECK:STDOUT: %ptr => constants.%ptr.40dc71.2
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.2a1e48.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C.as.I.impl(constants.%empty_tuple) {
// CHECK:STDOUT: %Y => constants.%empty_tuple
// CHECK:STDOUT: %C => constants.%C.607