Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for converting between integer types #4753

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/prelude/types/int.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ impl forall [N:! IntLiteral()] Int(N) as As(IntLiteral()) {
fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
}

// TODO: Allow as an implicit conversion if N > M.
impl forall [M:! IntLiteral(), N:! IntLiteral()] Int(M) as As(Int(N)) {
fn Convert[self: Self]() -> Int(N) = "int.convert";
}

// Comparisons.

impl forall [N:! IntLiteral()] Int(N) as Eq {
Expand Down
16 changes: 16 additions & 0 deletions core/prelude/types/uint.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package Core library "prelude/types/uint";

import library "prelude/types/int_literal";
import library "prelude/types/int";
import library "prelude/operators";

private fn MakeUInt(size: IntLiteral()) -> type = "int.make_type_unsigned";
Expand Down Expand Up @@ -32,6 +33,21 @@ impl forall [N:! IntLiteral()] UInt(N) as As(IntLiteral()) {
fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
}

// TODO: Allow as an implicit conversion if N > M.
impl forall [M:! IntLiteral(), N:! IntLiteral()] UInt(M) as As(UInt(N)) {
fn Convert[self: Self]() -> UInt(N) = "int.convert";
}

// TODO: Allow as an implicit conversion if N > M.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N > M + 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is right as-is: all values of uN fit in i(N+1), so it's OK for that to be implicit. The other comments could use >= instead of >, but that would only allow identity conversions which we already allow.

impl forall [M:! IntLiteral(), N:! IntLiteral()] UInt(M) as As(Int(N)) {
fn Convert[self: Self]() -> Int(N) = "int.convert";
}

// Never implicit.
impl forall [M:! IntLiteral(), N:! IntLiteral()] Int(M) as As(UInt(N)) {
fn Convert[self: Self]() -> UInt(N) = "int.convert";
}

// Comparisons.

impl forall [N:! IntLiteral()] UInt(N) as Eq {
Expand Down
26 changes: 26 additions & 0 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,26 @@ static auto ValidateFloatType(Context& context, SemIRLoc loc,
return ValidateFloatBitWidth(context, loc, result.bit_width_id);
}

// Performs a conversion between integer types, truncating if the value doesn't
// fit in the destination type.
static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
SemIR::TypeId dest_type_id) -> SemIR::ConstantId {
auto arg_val =
context.ints().Get(context.insts().GetAs<SemIR::IntValue>(arg_id).int_id);
auto [dest_is_signed, bit_width_id] =
context.sem_ir().types().GetIntTypeInfo(dest_type_id);
if (bit_width_id.is_valid()) {
// TODO: If the value fits in the destination type, reuse the existing
// int_id rather than recomputing it. This is probably the most common case.
bool src_is_signed = context.sem_ir().types().IsSignedInt(
context.insts().Get(arg_id).type_id());
unsigned width = context.ints().Get(bit_width_id).getZExtValue();
arg_val =
src_is_signed ? arg_val.sextOrTrunc(width) : arg_val.zextOrTrunc(width);
}
return MakeIntResult(context, dest_type_id, dest_is_signed, arg_val);
}

// Performs a conversion between integer types, diagnosing if the value doesn't
// fit in the destination type.
static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
Expand Down Expand Up @@ -1284,6 +1304,12 @@ static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc,
}

// Integer conversions.
case SemIR::BuiltinFunctionKind::IntConvert: {
if (phase == Phase::Symbolic) {
return MakeConstantResult(context, call, phase);
}
return PerformIntConvert(context, arg_ids[0], call.type_id);
}
case SemIR::BuiltinFunctionKind::IntConvertChecked: {
if (phase == Phase::Symbolic) {
return MakeConstantResult(context, call, phase);
Expand Down
24 changes: 12 additions & 12 deletions toolchain/check/testdata/array/array_vs_tuple.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ fn G() {
// CHECK:STDOUT: %tuple.type.1: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [template]
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [template]
// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
// CHECK:STDOUT: %impl_witness.19: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.10: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.10: %Convert.type.10 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound.1: <bound method> = bound_method %int_1.1, %Convert.10 [template]
// CHECK:STDOUT: %impl_witness.20: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.11: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.11: %Convert.type.11 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound.1: <bound method> = bound_method %int_1.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.1: <specific function> = specific_function %Convert.bound.1, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_1.2: %i32 = int_value 1 [template]
// CHECK:STDOUT: %Convert.bound.2: <bound method> = bound_method %int_2.1, %Convert.10 [template]
// CHECK:STDOUT: %Convert.bound.2: <bound method> = bound_method %int_2.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.2: <specific function> = specific_function %Convert.bound.2, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_2.2: %i32 = int_value 2 [template]
// CHECK:STDOUT: %Convert.bound.3: <bound method> = bound_method %int_3.1, %Convert.10 [template]
// CHECK:STDOUT: %Convert.bound.3: <bound method> = bound_method %int_3.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.3: <specific function> = specific_function %Convert.bound.3, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_3.2: %i32 = int_value 3 [template]
// CHECK:STDOUT: %array: %array_type = tuple_value (%int_1.2, %int_2.2, %int_3.2) [template]
Expand Down Expand Up @@ -71,23 +71,23 @@ fn G() {
// CHECK:STDOUT: %int_2.loc13_25: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
// CHECK:STDOUT: %int_3.loc13: Core.IntLiteral = int_value 3 [template = constants.%int_3.1]
// CHECK:STDOUT: %.loc13_29.1: %tuple.type.1 = tuple_literal (%int_1.loc13_22, %int_2.loc13_25, %int_3.loc13)
// CHECK:STDOUT: %impl.elem0.loc13_29.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc13_29.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc13_29.1: <bound method> = bound_method %int_1.loc13_22, %impl.elem0.loc13_29.1 [template = constants.%Convert.bound.1]
// CHECK:STDOUT: %Convert.specific_fn.loc13_29.1: <specific function> = specific_function %Convert.bound.loc13_29.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
// CHECK:STDOUT: %int.convert_checked.loc13_29.1: init %i32 = call %Convert.specific_fn.loc13_29.1(%int_1.loc13_22) [template = constants.%int_1.2]
// CHECK:STDOUT: %.loc13_29.2: init %i32 = converted %int_1.loc13_22, %int.convert_checked.loc13_29.1 [template = constants.%int_1.2]
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0]
// CHECK:STDOUT: %.loc13_29.3: ref %i32 = array_index %a.var, %int_0
// CHECK:STDOUT: %.loc13_29.4: init %i32 = initialize_from %.loc13_29.2 to %.loc13_29.3 [template = constants.%int_1.2]
// CHECK:STDOUT: %impl.elem0.loc13_29.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc13_29.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc13_29.2: <bound method> = bound_method %int_2.loc13_25, %impl.elem0.loc13_29.2 [template = constants.%Convert.bound.2]
// CHECK:STDOUT: %Convert.specific_fn.loc13_29.2: <specific function> = specific_function %Convert.bound.loc13_29.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
// CHECK:STDOUT: %int.convert_checked.loc13_29.2: init %i32 = call %Convert.specific_fn.loc13_29.2(%int_2.loc13_25) [template = constants.%int_2.2]
// CHECK:STDOUT: %.loc13_29.5: init %i32 = converted %int_2.loc13_25, %int.convert_checked.loc13_29.2 [template = constants.%int_2.2]
// CHECK:STDOUT: %int_1.loc13_29: Core.IntLiteral = int_value 1 [template = constants.%int_1.1]
// CHECK:STDOUT: %.loc13_29.6: ref %i32 = array_index %a.var, %int_1.loc13_29
// CHECK:STDOUT: %.loc13_29.7: init %i32 = initialize_from %.loc13_29.5 to %.loc13_29.6 [template = constants.%int_2.2]
// CHECK:STDOUT: %impl.elem0.loc13_29.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc13_29.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc13_29.3: <bound method> = bound_method %int_3.loc13, %impl.elem0.loc13_29.3 [template = constants.%Convert.bound.3]
// CHECK:STDOUT: %Convert.specific_fn.loc13_29.3: <specific function> = specific_function %Convert.bound.loc13_29.3, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.3]
// CHECK:STDOUT: %int.convert_checked.loc13_29.3: init %i32 = call %Convert.specific_fn.loc13_29.3(%int_3.loc13) [template = constants.%int_3.2]
Expand All @@ -104,21 +104,21 @@ fn G() {
// CHECK:STDOUT: %int_2.loc14: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
// CHECK:STDOUT: %int_3.loc14: Core.IntLiteral = int_value 3 [template = constants.%int_3.1]
// CHECK:STDOUT: %.loc14_36.1: %tuple.type.1 = tuple_literal (%int_1.loc14, %int_2.loc14, %int_3.loc14)
// CHECK:STDOUT: %impl.elem0.loc14_36.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc14_36.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc14_36.1: <bound method> = bound_method %int_1.loc14, %impl.elem0.loc14_36.1 [template = constants.%Convert.bound.1]
// CHECK:STDOUT: %Convert.specific_fn.loc14_36.1: <specific function> = specific_function %Convert.bound.loc14_36.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
// CHECK:STDOUT: %int.convert_checked.loc14_36.1: init %i32 = call %Convert.specific_fn.loc14_36.1(%int_1.loc14) [template = constants.%int_1.2]
// CHECK:STDOUT: %.loc14_36.2: init %i32 = converted %int_1.loc14, %int.convert_checked.loc14_36.1 [template = constants.%int_1.2]
// CHECK:STDOUT: %tuple.elem0: ref %i32 = tuple_access %b.var, element0
// CHECK:STDOUT: %.loc14_36.3: init %i32 = initialize_from %.loc14_36.2 to %tuple.elem0 [template = constants.%int_1.2]
// CHECK:STDOUT: %impl.elem0.loc14_36.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc14_36.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc14_36.2: <bound method> = bound_method %int_2.loc14, %impl.elem0.loc14_36.2 [template = constants.%Convert.bound.2]
// CHECK:STDOUT: %Convert.specific_fn.loc14_36.2: <specific function> = specific_function %Convert.bound.loc14_36.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
// CHECK:STDOUT: %int.convert_checked.loc14_36.2: init %i32 = call %Convert.specific_fn.loc14_36.2(%int_2.loc14) [template = constants.%int_2.2]
// CHECK:STDOUT: %.loc14_36.4: init %i32 = converted %int_2.loc14, %int.convert_checked.loc14_36.2 [template = constants.%int_2.2]
// CHECK:STDOUT: %tuple.elem1: ref %i32 = tuple_access %b.var, element1
// CHECK:STDOUT: %.loc14_36.5: init %i32 = initialize_from %.loc14_36.4 to %tuple.elem1 [template = constants.%int_2.2]
// CHECK:STDOUT: %impl.elem0.loc14_36.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc14_36.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc14_36.3: <bound method> = bound_method %int_3.loc14, %impl.elem0.loc14_36.3 [template = constants.%Convert.bound.3]
// CHECK:STDOUT: %Convert.specific_fn.loc14_36.3: <specific function> = specific_function %Convert.bound.loc14_36.3, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.3]
// CHECK:STDOUT: %int.convert_checked.loc14_36.3: init %i32 = call %Convert.specific_fn.loc14_36.3(%int_3.loc14) [template = constants.%int_3.2]
Expand Down
10 changes: 5 additions & 5 deletions toolchain/check/testdata/array/assign_return_value.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ fn Run() {
// CHECK:STDOUT: %int_0.1: Core.IntLiteral = int_value 0 [template]
// CHECK:STDOUT: %tuple.type.3: type = tuple_type (Core.IntLiteral) [template]
// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
// CHECK:STDOUT: %impl_witness.19: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.10: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.10: %Convert.type.10 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.1, %Convert.10 [template]
// CHECK:STDOUT: %impl_witness.20: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.11: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.11: %Convert.type.11 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_0.2: %i32 = int_value 0 [template]
// CHECK:STDOUT: %tuple: %tuple.type.2 = tuple_value (%int_0.2) [template]
Expand Down Expand Up @@ -73,7 +73,7 @@ fn Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0.1]
// CHECK:STDOUT: %.loc11_30.1: %tuple.type.3 = tuple_literal (%int_0)
// CHECK:STDOUT: %impl.elem0: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0, %impl.elem0 [template = constants.%Convert.bound]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %Convert.specific_fn(%int_0) [template = constants.%int_0.2]
Expand Down
18 changes: 9 additions & 9 deletions toolchain/check/testdata/array/assign_var.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ var b: [i32; 3] = a;
// CHECK:STDOUT: %int_3.1: Core.IntLiteral = int_value 3 [template]
// CHECK:STDOUT: %tuple.type.3: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [template]
// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
// CHECK:STDOUT: %impl_witness.19: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.10: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.10: %Convert.type.10 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound.1: <bound method> = bound_method %int_1.1, %Convert.10 [template]
// CHECK:STDOUT: %impl_witness.20: <witness> = impl_witness (imports.%import_ref.14), @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.type.11: type = fn_type @Convert.2, @impl.1(%int_32) [template]
// CHECK:STDOUT: %Convert.11: %Convert.type.11 = struct_value () [template]
// CHECK:STDOUT: %Convert.bound.1: <bound method> = bound_method %int_1.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.1: <specific function> = specific_function %Convert.bound.1, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_1.2: %i32 = int_value 1 [template]
// CHECK:STDOUT: %Convert.bound.2: <bound method> = bound_method %int_2.1, %Convert.10 [template]
// CHECK:STDOUT: %Convert.bound.2: <bound method> = bound_method %int_2.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.2: <specific function> = specific_function %Convert.bound.2, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_2.2: %i32 = int_value 2 [template]
// CHECK:STDOUT: %Convert.bound.3: <bound method> = bound_method %int_3.1, %Convert.10 [template]
// CHECK:STDOUT: %Convert.bound.3: <bound method> = bound_method %int_3.1, %Convert.11 [template]
// CHECK:STDOUT: %Convert.specific_fn.3: <specific function> = specific_function %Convert.bound.3, @Convert.2(%int_32) [template]
// CHECK:STDOUT: %int_3.2: %i32 = int_value 3 [template]
// CHECK:STDOUT: %tuple: %tuple.type.2 = tuple_value (%int_1.2, %int_2.2, %int_3.2) [template]
Expand Down Expand Up @@ -67,21 +67,21 @@ var b: [i32; 3] = a;
// CHECK:STDOUT: %int_2.loc11: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [template = constants.%int_3.1]
// CHECK:STDOUT: %.loc11_34.1: %tuple.type.3 = tuple_literal (%int_1.loc11, %int_2.loc11, %int_3)
// CHECK:STDOUT: %impl.elem0.loc11_34.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc11_34.1: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc11_34.1: <bound method> = bound_method %int_1.loc11, %impl.elem0.loc11_34.1 [template = constants.%Convert.bound.1]
// CHECK:STDOUT: %Convert.specific_fn.loc11_34.1: <specific function> = specific_function %Convert.bound.loc11_34.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
// CHECK:STDOUT: %int.convert_checked.loc11_34.1: init %i32 = call %Convert.specific_fn.loc11_34.1(%int_1.loc11) [template = constants.%int_1.2]
// CHECK:STDOUT: %.loc11_34.2: init %i32 = converted %int_1.loc11, %int.convert_checked.loc11_34.1 [template = constants.%int_1.2]
// CHECK:STDOUT: %tuple.elem0.loc11: ref %i32 = tuple_access file.%a.var, element0
// CHECK:STDOUT: %.loc11_34.3: init %i32 = initialize_from %.loc11_34.2 to %tuple.elem0.loc11 [template = constants.%int_1.2]
// CHECK:STDOUT: %impl.elem0.loc11_34.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc11_34.2: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc11_34.2: <bound method> = bound_method %int_2.loc11, %impl.elem0.loc11_34.2 [template = constants.%Convert.bound.2]
// CHECK:STDOUT: %Convert.specific_fn.loc11_34.2: <specific function> = specific_function %Convert.bound.loc11_34.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
// CHECK:STDOUT: %int.convert_checked.loc11_34.2: init %i32 = call %Convert.specific_fn.loc11_34.2(%int_2.loc11) [template = constants.%int_2.2]
// CHECK:STDOUT: %.loc11_34.4: init %i32 = converted %int_2.loc11, %int.convert_checked.loc11_34.2 [template = constants.%int_2.2]
// CHECK:STDOUT: %tuple.elem1.loc11: ref %i32 = tuple_access file.%a.var, element1
// CHECK:STDOUT: %.loc11_34.5: init %i32 = initialize_from %.loc11_34.4 to %tuple.elem1.loc11 [template = constants.%int_2.2]
// CHECK:STDOUT: %impl.elem0.loc11_34.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.19, element0 [template = constants.%Convert.10]
// CHECK:STDOUT: %impl.elem0.loc11_34.3: %Convert.type.2 = impl_witness_access constants.%impl_witness.20, element0 [template = constants.%Convert.11]
// CHECK:STDOUT: %Convert.bound.loc11_34.3: <bound method> = bound_method %int_3, %impl.elem0.loc11_34.3 [template = constants.%Convert.bound.3]
// CHECK:STDOUT: %Convert.specific_fn.loc11_34.3: <specific function> = specific_function %Convert.bound.loc11_34.3, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.3]
// CHECK:STDOUT: %int.convert_checked.loc11_34.3: init %i32 = call %Convert.specific_fn.loc11_34.3(%int_3) [template = constants.%int_3.2]
Expand Down
Loading
Loading