mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 15:10:12 +01:00
Make template actions refer to values from the specific. (#7663)
When a template action is created, any (non-meta) instruction operand will refer to instructions in the corresponding generic, or possibly to a constant. This means that when the action is eventually executed when forming a specific, it would see the generic value for that operand rather than the intended specific value. Fix this by refining `InstId` operands to refer to a corresponding value in the specific, much like we would when rebuilding a constant in the eval block.
This commit is contained in:
@@ -214,6 +214,24 @@ static auto RefineTypedOperand(Context& context, SemIR::LocId loc_id,
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
template <typename DerivedInstIdT>
|
||||
requires SemIR::Internal::IsIdKindType<DerivedInstIdT> &&
|
||||
std::derived_from<DerivedInstIdT, SemIR::InstId>
|
||||
static auto RefineTypedOperand(Context& context, SemIR::LocId /*loc_id*/,
|
||||
DerivedInstIdT inst_id) -> DerivedInstIdT {
|
||||
// Refine an instruction that refers to a value within the current generic to
|
||||
// refer to the corresponding value within the specific. This is analogous to
|
||||
// the work we do to rebuild generic constants in the eval block, but is done
|
||||
// as refinement rather than rebuilding since action instructions *only* live
|
||||
// in the eval block.
|
||||
auto result = GetOrAddInstWithSpecificConstantValue(context, inst_id);
|
||||
if constexpr (requires { DerivedInstIdT(result); }) {
|
||||
return DerivedInstIdT(result);
|
||||
} else {
|
||||
return DerivedInstIdT::UnsafeMake(result);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BundleT>
|
||||
static auto RefineTypedOperand(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::BundleId<BundleT> bundle_id)
|
||||
|
||||
@@ -228,12 +228,11 @@ static auto AddGenericTypeToEvalBlock(Context& context, SemIR::LocId loc_id,
|
||||
}
|
||||
|
||||
// Adds instructions to compute the substituted value of `inst_id` in each
|
||||
// specific into the eval block for the current generic region. Returns a
|
||||
// symbolic constant instruction ID that refers to the substituted constant
|
||||
// value in each specific.
|
||||
static auto AddGenericConstantToEvalBlock(Context& context,
|
||||
SemIR::InstId inst_id)
|
||||
-> SemIR::ConstantId {
|
||||
// specific into the eval block for the current generic region. Returns the
|
||||
// instruction within the eval block that computes the substituted constant.
|
||||
static auto AddGenericConstantInstToEvalBlock(Context& context,
|
||||
SemIR::InstId inst_id)
|
||||
-> SemIR::InstId {
|
||||
CARBON_CHECK(context.constant_values().Get(inst_id).is_symbolic(),
|
||||
"Adding generic constant {0} with non-symbolic value {1}",
|
||||
context.insts().Get(inst_id),
|
||||
@@ -248,9 +247,29 @@ static auto AddGenericConstantToEvalBlock(Context& context,
|
||||
CARBON_CHECK(new_inst_id != const_inst_id,
|
||||
"No substitutions performed for generic constant {0}",
|
||||
context.insts().Get(inst_id));
|
||||
return new_inst_id;
|
||||
}
|
||||
|
||||
// Adds instructions to compute the substituted value of `inst_id` in each
|
||||
// specific into the eval block for the current generic region. Returns a
|
||||
// symbolic constant instruction ID that refers to the substituted constant
|
||||
// value in each specific.
|
||||
static auto AddGenericConstantToEvalBlock(Context& context,
|
||||
SemIR::InstId inst_id)
|
||||
-> SemIR::ConstantId {
|
||||
auto new_inst_id = AddGenericConstantInstToEvalBlock(context, inst_id);
|
||||
return context.constant_values().GetAttached(new_inst_id);
|
||||
}
|
||||
|
||||
auto GetOrAddInstWithSpecificConstantValue(Context& context,
|
||||
SemIR::InstId inst_id)
|
||||
-> SemIR::InstId {
|
||||
if (!context.constant_values().Get(inst_id).is_symbolic()) {
|
||||
return inst_id;
|
||||
}
|
||||
return AddGenericConstantInstToEvalBlock(context, inst_id);
|
||||
}
|
||||
|
||||
// Adds an instruction that performs a template action to the eval block for the
|
||||
// generic. The instruction should not yet have been added to any block. The
|
||||
// instruction might refer to types and constants that need to be rewritten, so
|
||||
|
||||
@@ -53,6 +53,15 @@ struct DependentInst {
|
||||
auto AttachDependentInstToCurrentGeneric(Context& context,
|
||||
DependentInst dependent_inst) -> void;
|
||||
|
||||
// Given an instruction that might have a generic constant value, returns an
|
||||
// instruction that has the corresponding specific constant value in the current
|
||||
// generic, if any. This is typically not necessary except when manually adding
|
||||
// instructions directly to the eval block, for example when building an Action
|
||||
// instruction.
|
||||
auto GetOrAddInstWithSpecificConstantValue(Context& context,
|
||||
SemIR::InstId inst_id)
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Discard the information about the current generic entity. This should be
|
||||
// called instead of `FinishGenericDecl` if the corresponding `Generic` object
|
||||
// would not actually be used, or when recovering from an error.
|
||||
|
||||
@@ -110,6 +110,55 @@ fn Test(d: D) {
|
||||
let _: i32 = AsI32(d);
|
||||
}
|
||||
|
||||
// --- as_type.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
//@dump-sem-ir-begin
|
||||
fn AsType[template T: type](x: T, template U: type) {
|
||||
let _: U = x as U;
|
||||
}
|
||||
//@dump-sem-ir-end
|
||||
|
||||
fn Test1(n: i32) {
|
||||
AsType(n, i32);
|
||||
}
|
||||
|
||||
class C {
|
||||
var n: i32;
|
||||
impl as Core.As(i32) {
|
||||
fn Convert(self) -> i32 { return self.n; }
|
||||
}
|
||||
}
|
||||
|
||||
fn Test2(c: C) {
|
||||
AsType(c, i32);
|
||||
}
|
||||
|
||||
// --- fail_cannot_as_type.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
fn AsType[template T: type](x: T, template U: type) {
|
||||
let _: U = x as U;
|
||||
}
|
||||
|
||||
class D {}
|
||||
|
||||
fn Test(d: D) {
|
||||
// CHECK:STDERR: fail_cannot_as_type.carbon:[[@LINE+10]]:3: error: unable to monomorphize specific `AsType(D, i32)` [ResolvingSpecificHere]
|
||||
// CHECK:STDERR: AsType(d, i32);
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_cannot_as_type.carbon:[[@LINE-9]]:14: note: cannot convert expression of type `D` to `i32` with `as` [ConversionFailure]
|
||||
// CHECK:STDERR: let _: U = x as U;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_cannot_as_type.carbon:[[@LINE-12]]:14: note: type `D` does not implement interface `Core.As(i32)` [MissingImplInMemberAccessInContext]
|
||||
// CHECK:STDERR: let _: U = x as U;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR:
|
||||
AsType(d, i32);
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- convert.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
@@ -445,3 +494,173 @@ fn Test(d: D) {
|
||||
// CHECK:STDOUT: %.loc6_18.2 => constants.%inst.splice_block.132
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- as_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %type: type = facet_type <type> [concrete]
|
||||
// CHECK:STDOUT: %.Self.frozen: %type = symbolic_binding .Self [symbolic_self]
|
||||
// CHECK:STDOUT: %pattern_type.98f: type = pattern_type type [concrete]
|
||||
// CHECK:STDOUT: %T.patt.d47011.1: %pattern_type.98f = symbolic_binding_pattern T, 0, template [template]
|
||||
// CHECK:STDOUT: %T.67db0b.1: type = symbolic_binding T, 0, template [template]
|
||||
// CHECK:STDOUT: %pattern_type.51d1c4.1: type = pattern_type %T.67db0b.1 [template]
|
||||
// CHECK:STDOUT: %x.param_patt.91d: %pattern_type.51d1c4.1 = value_param_pattern [template]
|
||||
// CHECK:STDOUT: %x.patt.260: %pattern_type.51d1c4.1 = wrapper_binding_pattern x, %x.param_patt.91d [template]
|
||||
// CHECK:STDOUT: %U.patt.014: %pattern_type.98f = symbolic_binding_pattern U, 1, template [template]
|
||||
// CHECK:STDOUT: %U.091: type = symbolic_binding U, 1, template [template]
|
||||
// CHECK:STDOUT: %AsType.type: type = fn_type @AsType [concrete]
|
||||
// CHECK:STDOUT: %AsType: %AsType.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]
|
||||
// CHECK:STDOUT: %require_complete.441: <witness> = require_complete_type %U.091 [template]
|
||||
// CHECK:STDOUT: %pattern_type.946: type = pattern_type %U.091 [template]
|
||||
// CHECK:STDOUT: %_.patt.972: %pattern_type.946 = value_binding_pattern _ [template]
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %i32.builtin: type = int_type signed, %int_32 [concrete]
|
||||
// CHECK:STDOUT: %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]
|
||||
// CHECK:STDOUT: %x.param_patt.cee: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt.e3b: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt.cee [concrete]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %As.type.155: type = facet_type <@As, @As(%i32)> [concrete]
|
||||
// CHECK:STDOUT: %As.impl_witness.80e: <witness> = impl_witness @C.as.As.impl.%As.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.98b: type = pattern_type %C [concrete]
|
||||
// CHECK:STDOUT: %C.as.As.impl.Convert.type: type = fn_type @C.as.As.impl.Convert [concrete]
|
||||
// CHECK:STDOUT: %C.as.As.impl.Convert: %C.as.As.impl.Convert.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %As.facet: %As.type.155 = facet_value %C, (%As.impl_witness.80e) [concrete]
|
||||
// CHECK:STDOUT: %As.WithSelf.Convert.type.087: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32, %As.facet) [concrete]
|
||||
// CHECK:STDOUT: %struct_type.n: type = struct_type {.n: %i32} [concrete]
|
||||
// CHECK:STDOUT: %complete_type.cdf: <witness> = complete_type_witness %struct_type.n [concrete]
|
||||
// CHECK:STDOUT: %x.param_patt.0f9: %pattern_type.98b = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt.953: %pattern_type.98b = wrapper_binding_pattern x, %x.param_patt.0f9 [concrete]
|
||||
// CHECK:STDOUT: %_.patt.bed: %pattern_type.6b6 = value_binding_pattern _ [concrete]
|
||||
// CHECK:STDOUT: %inst.as_compatible.1ff: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.775: %i32 = as_compatible @AsType.%x.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %inst.splice_block.5e1: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.093: %i32 = splice_block %.775 {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %inst.splice_block.520: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.b12: %i32 = splice_block %.093 {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %inst.as_compatible.d98: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.f8c: %C = as_compatible @AsType.%x.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.419: type = fn_type_with_self_type %As.WithSelf.Convert.type.087, %As.facet [concrete]
|
||||
// CHECK:STDOUT: %inst.splice_block.550: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.24f: %i32 = splice_block %.0bd {
|
||||
// CHECK:STDOUT: %impl.elem0.47b: %.419 = impl_witness_access %As.impl_witness.80e, element0 [concrete = %C.as.As.impl.Convert]
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.f8c, %impl.elem0.47b
|
||||
// CHECK:STDOUT: %C.as.As.impl.Convert.call: init %i32 = call %bound_method(%.f8c)
|
||||
// CHECK:STDOUT: %.0bd: %i32 = value_of_initializer %C.as.As.impl.Convert.call
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %inst.splice_block.022: <instruction> = inst_value [concrete] {
|
||||
// CHECK:STDOUT: %.77f: %i32 = splice_block %.24f {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: %AsType.decl: %AsType.type = fn_decl @AsType [concrete = constants.%AsType] {
|
||||
// CHECK:STDOUT: %T.patt.loc5_21.1: %pattern_type.98f = symbolic_binding_pattern T, 0, template [template = %T.patt.loc5_21.2 (constants.%T.patt.d47011.1)]
|
||||
// CHECK:STDOUT: %x.param_patt.loc5_30.1: @AsType.%pattern_type.loc5 (%pattern_type.51d1c4.1) = value_param_pattern [template = %x.param_patt.loc5_30.2 (constants.%x.param_patt.91d)]
|
||||
// CHECK:STDOUT: %x.patt.loc5_30.1: @AsType.%pattern_type.loc5 (%pattern_type.51d1c4.1) = wrapper_binding_pattern x, %x.param_patt.loc5_30.1 [template = %x.patt.loc5_30.2 (constants.%x.patt.260)]
|
||||
// CHECK:STDOUT: %U.patt.loc5_45.1: %pattern_type.98f = symbolic_binding_pattern U, 1, template [template = %U.patt.loc5_45.2 (constants.%U.patt.014)]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %.loc5_23.1: type = splice_block %.loc5_23.2 [concrete = type] {
|
||||
// CHECK:STDOUT: %.Self.frozen.loc5_21: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen]
|
||||
// CHECK:STDOUT: %.loc5_23.2: type = type_literal type [concrete = type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %T.loc5_21.2: type = symbolic_binding T, 0, template [template = %T.loc5_21.1 (constants.%T.67db0b.1)]
|
||||
// CHECK:STDOUT: %x.param: @AsType.%T.loc5_21.1 (%T.67db0b.1) = value_param call_param0
|
||||
// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc5_21.2 [template = %T.loc5_21.1 (constants.%T.67db0b.1)]
|
||||
// CHECK:STDOUT: %x: @AsType.%T.loc5_21.1 (%T.67db0b.1) = wrapper_binding x, %x.param
|
||||
// CHECK:STDOUT: %.loc5_47.1: type = splice_block %.loc5_47.2 [concrete = type] {
|
||||
// CHECK:STDOUT: %.Self.frozen.loc5_45: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen]
|
||||
// CHECK:STDOUT: %.loc5_47.2: type = type_literal type [concrete = type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %U.loc5_45.2: type = symbolic_binding U, 1, template [template = %U.loc5_45.1 (constants.%U.091)]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @AsType(%T.loc5_21.2: type, %U.loc5_45.2: type) {
|
||||
// CHECK:STDOUT: %T.patt.loc5_21.2: %pattern_type.98f = symbolic_binding_pattern T, 0, template [template = %T.patt.loc5_21.2 (constants.%T.patt.d47011.1)]
|
||||
// CHECK:STDOUT: %T.loc5_21.1: type = symbolic_binding T, 0, template [template = %T.loc5_21.1 (constants.%T.67db0b.1)]
|
||||
// CHECK:STDOUT: %pattern_type.loc5: type = pattern_type %T.loc5_21.1 [template = %pattern_type.loc5 (constants.%pattern_type.51d1c4.1)]
|
||||
// CHECK:STDOUT: %x.param_patt.loc5_30.2: @AsType.%pattern_type.loc5 (%pattern_type.51d1c4.1) = value_param_pattern [template = %x.param_patt.loc5_30.2 (constants.%x.param_patt.91d)]
|
||||
// CHECK:STDOUT: %x.patt.loc5_30.2: @AsType.%pattern_type.loc5 (%pattern_type.51d1c4.1) = wrapper_binding_pattern x, %x.param_patt.loc5_30.2 [template = %x.patt.loc5_30.2 (constants.%x.patt.260)]
|
||||
// CHECK:STDOUT: %U.patt.loc5_45.2: %pattern_type.98f = symbolic_binding_pattern U, 1, template [template = %U.patt.loc5_45.2 (constants.%U.patt.014)]
|
||||
// CHECK:STDOUT: %U.loc5_45.1: type = symbolic_binding U, 1, template [template = %U.loc5_45.1 (constants.%U.091)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete.loc5: <witness> = require_complete_type %T.loc5_21.1 [template = %require_complete.loc5 (constants.%require_complete.944)]
|
||||
// CHECK:STDOUT: %require_complete.loc6: <witness> = require_complete_type %U.loc5_45.1 [template = %require_complete.loc6 (constants.%require_complete.441)]
|
||||
// CHECK:STDOUT: %pattern_type.loc6: type = pattern_type %U.loc5_45.1 [template = %pattern_type.loc6 (constants.%pattern_type.946)]
|
||||
// CHECK:STDOUT: %_.patt.loc6_8.2: @AsType.%pattern_type.loc6 (%pattern_type.946) = value_binding_pattern _ [template = %_.patt.loc6_8.2 (constants.%_.patt.972)]
|
||||
// CHECK:STDOUT: %.loc6_16.4: <instruction> = refine_type_action %x.ref, %T.loc5_21.1 [template]
|
||||
// CHECK:STDOUT: %.loc6_16.5: <instruction> = convert_action %.loc6_16.1, %U.loc5_45.1, element7 [template]
|
||||
// CHECK:STDOUT: %.loc6_16.6: <instruction> = convert_to_category_action %.loc6_16.2, element1 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn(%x.param: @AsType.%T.loc5_21.1 (%T.67db0b.1)) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %x.ref: @AsType.%T.loc5_21.1 (%T.67db0b.1) = name_ref x, %x
|
||||
// CHECK:STDOUT: %U.ref.loc6_19: type = name_ref U, %U.loc5_45.2 [template = %U.loc5_45.1 (constants.%U.091)]
|
||||
// CHECK:STDOUT: %.loc6_16.1: @AsType.%T.loc5_21.1 (%T.67db0b.1) = splice_inst %.loc6_16.4
|
||||
// CHECK:STDOUT: %.loc6_16.2: @AsType.%U.loc5_45.1 (%U.091) = splice_inst %.loc6_16.5
|
||||
// CHECK:STDOUT: %.loc6_16.3: @AsType.%U.loc5_45.1 (%U.091) = splice_inst %.loc6_16.6
|
||||
// CHECK:STDOUT: %U.ref.loc6_10: type = name_ref U, %U.loc5_45.2 [template = %U.loc5_45.1 (constants.%U.091)]
|
||||
// CHECK:STDOUT: %_: @AsType.%U.loc5_45.1 (%U.091) = wrapper_binding _, %.loc6_16.3
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %_.patt.loc6_8.1: @AsType.%pattern_type.loc6 (%pattern_type.946) = value_binding_pattern _ [template = %_.patt.loc6_8.2 (constants.%_.patt.972)]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @AsType(constants.%T.67db0b.1, constants.%U.091) {
|
||||
// CHECK:STDOUT: %T.patt.loc5_21.2 => constants.%T.patt.d47011.1
|
||||
// CHECK:STDOUT: %T.loc5_21.1 => constants.%T.67db0b.1
|
||||
// CHECK:STDOUT: %pattern_type.loc5 => constants.%pattern_type.51d1c4.1
|
||||
// CHECK:STDOUT: %x.param_patt.loc5_30.2 => constants.%x.param_patt.91d
|
||||
// CHECK:STDOUT: %x.patt.loc5_30.2 => constants.%x.patt.260
|
||||
// CHECK:STDOUT: %U.patt.loc5_45.2 => constants.%U.patt.014
|
||||
// CHECK:STDOUT: %U.loc5_45.1 => constants.%U.091
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @AsType(constants.%i32, constants.%i32) {
|
||||
// CHECK:STDOUT: %T.patt.loc5_21.2 => constants.%T.patt.d47011.1
|
||||
// CHECK:STDOUT: %T.loc5_21.1 => constants.%i32
|
||||
// CHECK:STDOUT: %pattern_type.loc5 => constants.%pattern_type.6b6
|
||||
// CHECK:STDOUT: %x.param_patt.loc5_30.2 => constants.%x.param_patt.cee
|
||||
// CHECK:STDOUT: %x.patt.loc5_30.2 => constants.%x.patt.e3b
|
||||
// CHECK:STDOUT: %U.patt.loc5_45.2 => constants.%U.patt.014
|
||||
// CHECK:STDOUT: %U.loc5_45.1 => constants.%i32
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete.loc5 => constants.%complete_type.f8a
|
||||
// CHECK:STDOUT: %require_complete.loc6 => constants.%complete_type.f8a
|
||||
// CHECK:STDOUT: %pattern_type.loc6 => constants.%pattern_type.6b6
|
||||
// CHECK:STDOUT: %_.patt.loc6_8.2 => constants.%_.patt.bed
|
||||
// CHECK:STDOUT: %.loc6_16.4 => constants.%inst.as_compatible.1ff
|
||||
// CHECK:STDOUT: %.loc6_16.5 => constants.%inst.splice_block.5e1
|
||||
// CHECK:STDOUT: %.loc6_16.6 => constants.%inst.splice_block.520
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @AsType(constants.%C, constants.%i32) {
|
||||
// CHECK:STDOUT: %T.patt.loc5_21.2 => constants.%T.patt.d47011.1
|
||||
// CHECK:STDOUT: %T.loc5_21.1 => constants.%C
|
||||
// CHECK:STDOUT: %pattern_type.loc5 => constants.%pattern_type.98b
|
||||
// CHECK:STDOUT: %x.param_patt.loc5_30.2 => constants.%x.param_patt.0f9
|
||||
// CHECK:STDOUT: %x.patt.loc5_30.2 => constants.%x.patt.953
|
||||
// CHECK:STDOUT: %U.patt.loc5_45.2 => constants.%U.patt.014
|
||||
// CHECK:STDOUT: %U.loc5_45.1 => constants.%i32
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete.loc5 => constants.%complete_type.cdf
|
||||
// CHECK:STDOUT: %require_complete.loc6 => constants.%complete_type.f8a
|
||||
// CHECK:STDOUT: %pattern_type.loc6 => constants.%pattern_type.6b6
|
||||
// CHECK:STDOUT: %_.patt.loc6_8.2 => constants.%_.patt.bed
|
||||
// CHECK:STDOUT: %.loc6_16.4 => constants.%inst.as_compatible.d98
|
||||
// CHECK:STDOUT: %.loc6_16.5 => constants.%inst.splice_block.550
|
||||
// CHECK:STDOUT: %.loc6_16.6 => constants.%inst.splice_block.022
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user